From e240b7fedf7964430b0957438870d841dc16bce1 Mon Sep 17 00:00:00 2001 From: Paul Dino Jones Date: Mon, 17 Jul 2023 16:38:34 +0000 Subject: [PATCH] Adding browse features for telemetry viewer. Updates to telemetry logging --- src/gilles/gameloop/browseloop.c | 865 +++++++++++++++++++++++++++++++ src/gilles/gameloop/browseloop.h | 4 + src/gilles/gameloop/gameloop.c | 200 ++++--- src/gilles/gameloop/session.h | 130 +++++ src/gilles/helper/parameters.c | 51 +- src/gilles/helper/parameters.h | 1 + 6 files changed, 1168 insertions(+), 83 deletions(-) create mode 100644 src/gilles/gameloop/browseloop.c create mode 100644 src/gilles/gameloop/browseloop.h create mode 100644 src/gilles/gameloop/session.h diff --git a/src/gilles/gameloop/browseloop.c b/src/gilles/gameloop/browseloop.c new file mode 100644 index 0000000..14ab830 --- /dev/null +++ b/src/gilles/gameloop/browseloop.c @@ -0,0 +1,865 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; rowvalue); + 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; rowvalue; + *(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 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; +} + diff --git a/src/gilles/gameloop/browseloop.h b/src/gilles/gameloop/browseloop.h new file mode 100644 index 0000000..6439d79 --- /dev/null +++ b/src/gilles/gameloop/browseloop.h @@ -0,0 +1,4 @@ +#include "../helper/parameters.h" +#include "../helper/confighelper.h" + +int browseloop(Parameters* p); diff --git a/src/gilles/gameloop/gameloop.c b/src/gilles/gameloop/gameloop.c index 79832a0..eda33c9 100644 --- a/src/gilles/gameloop/gameloop.c +++ b/src/gilles/gameloop/gameloop.c @@ -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 (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 // | start_time | duration_min | elapsed_ms | laps | weather | -// air_temp | road_temp | start_grip | current_grip | is_finished -// | finish_time | last_activity | http_port +// air_temp | road_temp | start_grip | json_t *root = json_object(); 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_type", json_integer(1)); 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, "last_activity", json_string("2023-06-27")); 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, "weather", json_string("Windy")); + json_object_set_new(values, "http_port", json_integer(0)); json_array_append(json_arr, values); int res = h_insert(conn, root, NULL); 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) { -// 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 *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_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, "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); int res = h_insert(conn, root, NULL); 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); } +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) { // 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 *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]); } - //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); 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_insert(conn, j_query, NULL); slogt("got res %i", res1); 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; } @@ -1152,17 +1169,6 @@ void* simviewmysql(void* thargs) carid = addcar(conn, carid, simdata->car); // ?? 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 sessionstatus = 0; @@ -1188,16 +1194,32 @@ void* simviewmysql(void* thargs) int tick = 0; - slogt("spline %f", simdata->trackspline); int track_samples = simdata->trackspline / TRACK_SAMPLE_RATE; slogt("track samples %i", track_samples); + int stintlaps = 0; + int validstintlaps = 0; + bool validind = true; 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* acceldata = malloc(track_samples * sizeof(simdata->gas)); 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) { @@ -1208,9 +1230,31 @@ void* simviewmysql(void* thargs) slogt("normpos %i", pos); steerdata[pos] = simdata->steer; acceldata[pos] = simdata->gas; - speeddata[pos] = simdata->velocity; 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; sessionstatus = simdata->session; lap = simdata->lap; @@ -1218,6 +1262,7 @@ void* simviewmysql(void* thargs) { sessionid = addsession(conn, eventid, simdata->session, simdata->airtemp, simdata->tracktemp); pitstatus = 1; + stintlaps = 0; } if (simdata->inpit == true) { @@ -1226,21 +1271,38 @@ void* simviewmysql(void* thargs) if (pitstatus = 0 && pitstatus != lastpitstatus) { // close last stint + closestint(conn, stintid, stintlaps, validstintlaps); stintid = addstint(conn, sessionid, driverid, carid); + stintlaps = 0; } 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"); stintlapid = addstintlap(conn, stintid); int telemid = addtelemetry(conn, track_samples, stintlapid); 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), "brake", brakedata); - //print_bytes(acceldata, tick*sizeof(double)); - print_bytes(&acceldata[pos], sizeof(double)); - slogt("last accel %f on tick %i", acceldata[track_samples], track_samples); - slogt("telemetry respone: %i", b); - // close last stint lap and telemetry lap + b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "rpms", rpmdata); + b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "gear", geardata); + b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "speed", speeddata); + tick = 0; } lastpitstatus = pitstatus; diff --git a/src/gilles/gameloop/session.h b/src/gilles/gameloop/session.h new file mode 100644 index 0000000..f9779a7 --- /dev/null +++ b/src/gilles/gameloop/session.h @@ -0,0 +1,130 @@ + +#ifndef _SESSION_H +#define _SESSION_H + +#include +#include + +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 diff --git a/src/gilles/helper/parameters.c b/src/gilles/helper/parameters.c index 77ed66d..c70b9fc 100644 --- a/src/gilles/helper/parameters.c +++ b/src/gilles/helper/parameters.c @@ -40,34 +40,47 @@ ConfigError getParameters(int argc, char** argv, Parameters* p) // setup argument handling structures 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* cmd2 = arg_rex1(NULL, NULL, "browse", NULL, REG_ICASE, NULL); struct arg_str* arg_sim = arg_strn("s", "sim", "", 0, 1, NULL); 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_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* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit"); - struct arg_end* end = arg_end(20); - void* argtable[] = {cmd1,arg_sim,arg_verbosity,arg_cli,arg_mqtt,arg_mysql,help,vers,end}; - int nerrors; + struct arg_lit* help0 = arg_litn(NULL,"help", 0, 1, "print this help and exit"); + struct arg_lit* vers0 = arg_litn(NULL,"version", 0, 1, "print version information and exit"); + struct arg_end* end0 = arg_end(20); + struct arg_lit* help1 = arg_litn(NULL,"help", 0, 1, "print this help and exit"); + 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); 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->sim_string = strdup(arg_sim->sval[0]); - p->verbosity_count = arg_verbosity->count; + p->verbosity_count = arg_verbosity0->count; if (arg_cli->count > 0) { p->cli = true; @@ -83,17 +96,26 @@ ConfigError getParameters(int argc, char** argv, Parameters* p) 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 - if (help->count > 0) + if (help0->count > 0) { 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"); exitcode = E_SUCCESS_AND_EXIT; goto cleanup; } - if (vers->count > 0) + if (vers0->count > 0) { printf("%s Simulator Monitor\n",progname); printf("October 2022, Paul Dino Jones\n"); @@ -102,7 +124,8 @@ ConfigError getParameters(int argc, char** argv, Parameters* p) } 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; } diff --git a/src/gilles/helper/parameters.h b/src/gilles/helper/parameters.h index 9543e00..edb8007 100644 --- a/src/gilles/helper/parameters.h +++ b/src/gilles/helper/parameters.h @@ -33,6 +33,7 @@ Parameters; typedef enum { A_PLAY = 0, + A_BROWSE = 0 } ProgramAction;