Compare commits
17 Commits
master
...
newfeature
| Author | SHA1 | Date |
|---|---|---|
|
|
ee0315e620 | |
|
|
359f9b3a2d | |
|
|
18faa3a65a | |
|
|
66e9049891 | |
|
|
415a83a1f5 | |
|
|
0ce4fb5c2f | |
|
|
8b4c18ea4e | |
|
|
32accbfb77 | |
|
|
109d7b1fed | |
|
|
7823e777d4 | |
|
|
4772e759d4 | |
|
|
e0cc9de18f | |
|
|
e240b7fedf | |
|
|
0b3ff679a5 | |
|
|
a7718d8355 | |
|
|
496e875e70 | |
|
|
3318610cd2 |
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
argtable arg_parse
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
...
|
||||||
|
...
|
||||||
|
fun:arg_parse
|
||||||
|
...
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,8 @@ add_subdirectory(src/gilles/helper)
|
||||||
add_subdirectory(src/gilles/slog)
|
add_subdirectory(src/gilles/slog)
|
||||||
|
|
||||||
add_executable(gilles src/gilles/gilles.c)
|
add_executable(gilles src/gilles/gilles.c)
|
||||||
target_link_libraries(gilles m ncursesw argtable2 config gameloop helper slog simulatorapi eclipse-paho-mqtt-c::paho-mqtt3c pthread json-c)
|
target_link_libraries(gilles xdg-basedir m ncursesw argtable2 config gameloop helper slog simulatorapi eclipse-paho-mqtt-c::paho-mqtt3c pthread hoel jansson)
|
||||||
|
add_compile_definitions(gilles SIMMAP_ALL)
|
||||||
|
|
||||||
# used for enabling additional compiler options if supported
|
# used for enabling additional compiler options if supported
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
set(gameloop_source_files
|
set(gameloop_source_files
|
||||||
gameloop.c
|
gameloop.c
|
||||||
gameloop.h
|
gameloop.h
|
||||||
|
browseloop.c
|
||||||
|
browseloop.h
|
||||||
|
hoeldb.h
|
||||||
|
hoeldb.c
|
||||||
|
telemetry.h
|
||||||
|
telemetry.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBXML_INCLUDE_DIR /usr/include/libxml2)
|
|
||||||
include_directories("." ${LIBXML_INCLUDE_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
add_library(gameloop STATIC ${gameloop_source_files})
|
add_library(gameloop STATIC ${gameloop_source_files})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,666 @@
|
||||||
|
#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 <byteswap.h>
|
||||||
|
|
||||||
|
#include "hoeldb.h"
|
||||||
|
#include "telemetry.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
|
||||||
|
|
||||||
|
|
||||||
|
WINDOW* bwin1;
|
||||||
|
WINDOW* bwin2;
|
||||||
|
WINDOW* bwin3;
|
||||||
|
WINDOW* bwin4;
|
||||||
|
|
||||||
|
int bwinx, bwiny;
|
||||||
|
|
||||||
|
char blanks[1000];
|
||||||
|
|
||||||
|
void add_line()
|
||||||
|
{
|
||||||
|
wprintw(bwin1, "\n");
|
||||||
|
for (int j = 0; j < bwiny-1; ++j)
|
||||||
|
{
|
||||||
|
waddch(bwin1, ACS_HLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_spaces(int spaces)
|
||||||
|
{
|
||||||
|
blanks[spaces] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void b_handle_winch(int sig)
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
clear();
|
||||||
|
getmaxyx(stdscr, bwinx, bwiny);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int b_curses_init()
|
||||||
|
{
|
||||||
|
memset(blanks,' ',sizeof(blanks));
|
||||||
|
initscr();
|
||||||
|
start_color();
|
||||||
|
|
||||||
|
init_pair(1,COLOR_GREEN,0);
|
||||||
|
init_pair(2,COLOR_YELLOW,0);
|
||||||
|
init_pair(5,COLOR_BLACK,COLOR_YELLOW);
|
||||||
|
init_pair(3,COLOR_MAGENTA,0);
|
||||||
|
init_pair(4,COLOR_WHITE,0);
|
||||||
|
|
||||||
|
getmaxyx(stdscr, bwinx, bwiny);
|
||||||
|
slogt("windowx %i, windowy %i", bwinx, bwiny);
|
||||||
|
bwin1 = newwin(bwinx,bwiny,0,0);
|
||||||
|
|
||||||
|
wbkgd(bwin1,COLOR_PAIR(1));
|
||||||
|
wbkgd(bwin2,COLOR_PAIR(1));
|
||||||
|
wbkgd(bwin3,COLOR_PAIR(1));
|
||||||
|
wbkgd(bwin4,COLOR_PAIR(1));
|
||||||
|
|
||||||
|
signal(SIGWINCH, b_handle_winch);
|
||||||
|
curs_set(0);
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
|
||||||
|
box(bwin1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void* browseloop(Parameters* p, char* datadir)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct _h_result result;
|
||||||
|
struct _h_connection* conn;
|
||||||
|
conn = h_connect_pgsql(p->db_conn);
|
||||||
|
|
||||||
|
if (conn == NULL)
|
||||||
|
{
|
||||||
|
slogf("Unable to connect to configured Gilles database. Are the parameters in the config correct? Is the user allowed to access from this address?");
|
||||||
|
p->err = E_FAILED_DB_CONN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
slogt("Starting analyzer");
|
||||||
|
b_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);
|
||||||
|
DBField track;
|
||||||
|
track.type = HOEL_COL_TYPE_TEXT;
|
||||||
|
track.offset = offsetof(SessionRowData, track);
|
||||||
|
track.size = sizeof(unsigned char)*150;
|
||||||
|
DBField car;
|
||||||
|
car.type = HOEL_COL_TYPE_TEXT;
|
||||||
|
car.offset = offsetof(SessionRowData, car);
|
||||||
|
car.size = sizeof(unsigned char)*150;
|
||||||
|
DBField starttime;
|
||||||
|
starttime.type = HOEL_COL_TYPE_DATE;
|
||||||
|
starttime.offset = offsetof(SessionRowData, start_time);
|
||||||
|
starttime.size = sizeof(PDBTimeStamp);
|
||||||
|
|
||||||
|
//SessionFields sf;
|
||||||
|
sess.fields[0] = sessid;
|
||||||
|
sess.fields[1] = eventid;
|
||||||
|
sess.fields[2] = eventtype;
|
||||||
|
sess.fields[3] = laps;
|
||||||
|
sess.fields[4] = track;
|
||||||
|
sess.fields[5] = car;
|
||||||
|
sess.fields[6] = starttime;
|
||||||
|
//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 f_tyre_temp;
|
||||||
|
//f_tyre_temp.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//f_tyre_temp.offset = offsetof(LapRowData, f_tyre_temp);
|
||||||
|
//DBField r_tyre_temp;
|
||||||
|
//r_tyre_temp.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//r_tyre_temp.offset = offsetof(LapRowData, r_tyre_temp);
|
||||||
|
//DBField f_tyre_wear;
|
||||||
|
//f_tyre_wear.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//f_tyre_wear.offset = offsetof(LapRowData, f_tyre_wear);
|
||||||
|
//DBField r_tyre_wear;
|
||||||
|
//r_tyre_wear.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//r_tyre_wear.offset = offsetof(LapRowData, r_tyre_wear);
|
||||||
|
//DBField f_tyre_press;
|
||||||
|
//f_tyre_press.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//f_tyre_press.offset = offsetof(LapRowData, f_tyre_press);
|
||||||
|
//DBField r_tyre_press;
|
||||||
|
//r_tyre_press.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//r_tyre_press.offset = offsetof(LapRowData, r_tyre_press);
|
||||||
|
//DBField f_brake_temp;
|
||||||
|
//f_brake_temp.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//f_brake_temp.offset = offsetof(LapRowData, f_brake_temp);
|
||||||
|
//DBField r_brake_temp;
|
||||||
|
//r_brake_temp.type = HOEL_COL_TYPE_DOUBLE;
|
||||||
|
//r_brake_temp.offset = offsetof(LapRowData, r_brake_temp);
|
||||||
|
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;
|
||||||
|
//lapsdb.fields[13] = f_tyre_temp;
|
||||||
|
//lapsdb.fields[14] = r_tyre_temp;
|
||||||
|
//lapsdb.fields[15] = f_tyre_wear;
|
||||||
|
//lapsdb.fields[16] = r_tyre_wear;
|
||||||
|
//lapsdb.fields[17] = f_tyre_press;
|
||||||
|
//lapsdb.fields[18] = r_tyre_press;
|
||||||
|
//lapsdb.fields[19] = f_brake_temp;
|
||||||
|
//lapsdb.fields[20] = r_brake_temp;
|
||||||
|
|
||||||
|
//slogt("sessions has %i rows", sess.numrows);
|
||||||
|
|
||||||
|
action = 2;
|
||||||
|
|
||||||
|
|
||||||
|
int go = true;
|
||||||
|
char lastsimstatus = false;
|
||||||
|
|
||||||
|
int screen = SESSIONS_SCREEN;
|
||||||
|
char ch;
|
||||||
|
box(bwin1, 0, 0);
|
||||||
|
wrefresh(bwin1);
|
||||||
|
int stint_useid = 0;
|
||||||
|
int lap_useid = 0;
|
||||||
|
while (go == true)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (lastselection != selection)
|
||||||
|
{
|
||||||
|
action = 1;
|
||||||
|
lastselection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == 2)
|
||||||
|
{
|
||||||
|
slogt("going to perform an action");
|
||||||
|
int err = E_NO_ERROR;
|
||||||
|
sessions = getsessions(conn, "Sessions", &sess);
|
||||||
|
if (sessions < 0)
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curresults = sessions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == 3)
|
||||||
|
{
|
||||||
|
slogt("going to perform an action");
|
||||||
|
|
||||||
|
int err = E_NO_ERROR;
|
||||||
|
stintsid = getstints(conn, "Stints", &stints, stint_useid);
|
||||||
|
curresults = stintsid;
|
||||||
|
if (stintsid < 0)
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curresults = stintsid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action == 4)
|
||||||
|
{
|
||||||
|
slogt("going to perform an action");
|
||||||
|
|
||||||
|
int err = E_NO_ERROR;
|
||||||
|
lapsresults = getlaps(conn, "laps", &lapsdb, lap_useid);
|
||||||
|
slogt("laps query executed");
|
||||||
|
curresults = lapsresults;
|
||||||
|
if (lapsresults < 0)
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curresults = lapsresults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action > 0)
|
||||||
|
{
|
||||||
|
wclear(bwin1);
|
||||||
|
|
||||||
|
switch(screen)
|
||||||
|
{
|
||||||
|
case SESSIONS_SCREEN:
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0; i<sessions+1; i++)
|
||||||
|
{
|
||||||
|
int displaycolumns = 6;
|
||||||
|
int width1 = displaycolumns + 1;
|
||||||
|
int width2 = displaycolumns * 2;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
wattrset(bwin1, COLOR_PAIR(2));
|
||||||
|
wattron(bwin1, A_BOLD);
|
||||||
|
mvwaddnstr(bwin1, 2, bwiny/2, "Sessions", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/width2, "idx", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/width1+bwiny/width2, "name", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*2)+bwiny/width2, "track", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*3)+bwiny/width2, "car", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*4)+bwiny/width2, "stints", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*5)+bwiny/width2, "time", -1);
|
||||||
|
mvwhline(bwin1, 4, 0, 0, bwiny);
|
||||||
|
wattroff(bwin1, A_BOLD);
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( i == selection )
|
||||||
|
{
|
||||||
|
wattrset(bwin1, COLOR_PAIR(5));
|
||||||
|
stint_useid = sess.rows[i-1].session_id;
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2, " * ", 3);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6, " ", 3);
|
||||||
|
}
|
||||||
|
char idchar[4];
|
||||||
|
snprintf(idchar, 4, "%i", sess.rows[i-1].session_id);
|
||||||
|
char lapschar[4];
|
||||||
|
snprintf(lapschar, 4, "%i", sess.rows[i-1].laps);
|
||||||
|
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+2, idchar, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+bwiny/width1, "my session name", -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*2), sess.rows[i-1].track, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*3), sess.rows[i-1].car, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*4), lapschar, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*5), sess.rows[i-1].start_time, -1);
|
||||||
|
}
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STINTS_SCREEN:
|
||||||
|
if (stintsid == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(int i=0; i<stintsid+1; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
wattrset(bwin1, COLOR_PAIR(2));
|
||||||
|
wattron(bwin1, A_BOLD);
|
||||||
|
mvwaddnstr(bwin1, 2, bwiny/2, "Stints", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/6, "idx", 3);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/4+bwiny/6, "name", 4);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/4)*2)+bwiny/6, "laps", 4);
|
||||||
|
mvwhline(bwin1, 4, 0, 0, bwiny);
|
||||||
|
wattroff(bwin1, A_BOLD);
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( i == selection )
|
||||||
|
{
|
||||||
|
wattrset(bwin1, COLOR_PAIR(5));
|
||||||
|
lap_useid = stints.rows[i-1].stint_id;
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6, " * ", 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6, " ", 3);
|
||||||
|
}
|
||||||
|
char idchar[4];
|
||||||
|
snprintf(idchar, 4, "%i", stints.rows[i-1].stint_id);
|
||||||
|
char lapschar[4];
|
||||||
|
snprintf(lapschar, 4, "%i", stints.rows[i-1].laps);
|
||||||
|
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6+2, idchar, 4);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6+bwiny/4, "my session name", 15);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/6+((bwiny/4)*2), lapschar, 4);
|
||||||
|
}
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LAPS_SCREEN:
|
||||||
|
if (lapsresults == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<lapsresults+1; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
int displaycolumns = 4;
|
||||||
|
int width1 = displaycolumns + 1;
|
||||||
|
int width2 = displaycolumns * 2;
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
wattrset(bwin1, COLOR_PAIR(2));
|
||||||
|
wattron(bwin1, A_BOLD);
|
||||||
|
mvwaddnstr(bwin1, 2, bwiny/2, "Laps", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/width2, "idx", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, bwiny/width1+bwiny/width2, "name", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*2)+bwiny/width2, "tyre", -1);
|
||||||
|
mvwaddnstr(bwin1, 3, ((bwiny/width1)*3)+bwiny/width2, "maxspeed", -1);
|
||||||
|
mvwhline(bwin1, 4, 0, 0, bwiny);
|
||||||
|
wattroff(bwin1, A_BOLD);
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
//stint_useid = lapsdb.rows[i-1].rows;
|
||||||
|
if ( lapsdb.rows[i-1].lap_id == selection1 )
|
||||||
|
{
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/7 - 4, " 1 ", 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ( lapsdb.rows[i-1].lap_id == selection2 )
|
||||||
|
{
|
||||||
|
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/7 - 4, " 2 ", 3);
|
||||||
|
}
|
||||||
|
if ( i == selection )
|
||||||
|
{
|
||||||
|
wattrset(bwin1, COLOR_PAIR(5));
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/7, " * ", 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/7, " ", 3);
|
||||||
|
|
||||||
|
}
|
||||||
|
char idchar[4];
|
||||||
|
snprintf(idchar, 4, "%i", lapsdb.rows[i-1].lap_id);
|
||||||
|
char tyrechar[10];
|
||||||
|
snprintf(tyrechar, 10, "%s", lapsdb.rows[i-1].tyre);
|
||||||
|
char maxspeedchar[4];
|
||||||
|
snprintf(maxspeedchar, 4, "%i", lapsdb.rows[i-1].max_speed);
|
||||||
|
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+2, idchar, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+bwiny/width1, "my session name", -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*2), lapsdb.rows[i-1].tyre, -1);
|
||||||
|
mvwaddnstr(bwin1, 4+i, bwiny/width2+((bwiny/width1)*3), maxspeedchar, -1);
|
||||||
|
}
|
||||||
|
wattrset(bwin1, COLOR_PAIR(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
action = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
box(bwin1, 0, 0);
|
||||||
|
wrefresh(bwin1);
|
||||||
|
|
||||||
|
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 == 'g')
|
||||||
|
{
|
||||||
|
//selection1 = 363;
|
||||||
|
//selection2 = 362;
|
||||||
|
if (p->gnuplotfound == 1)
|
||||||
|
{
|
||||||
|
if (selection1 > 0 && selection2 > 0)
|
||||||
|
{
|
||||||
|
dumptelemetrytofile(conn, datadir, selection1, selection2);
|
||||||
|
|
||||||
|
slogi("finished dumping data");
|
||||||
|
size_t strsize = strlen(datadir) + strlen(p->gnuplot_file) + 1;
|
||||||
|
char* plotfile = malloc(strsize);
|
||||||
|
snprintf(plotfile, strsize, "%s%s", datadir, p->gnuplot_file);
|
||||||
|
static char* argv1[]= {"gnuplot", "-p", "plotfile.gp", NULL};
|
||||||
|
argv1[2] = plotfile;
|
||||||
|
slogi("Using gnu plot file %s", plotfile);
|
||||||
|
if(!fork())
|
||||||
|
{
|
||||||
|
execv(p->gnuplot_bin, argv1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("No gnuplot binary found or specified");
|
||||||
|
}
|
||||||
|
action = 4;
|
||||||
|
}
|
||||||
|
if (ch == 'B' || ch == 'l')
|
||||||
|
{
|
||||||
|
selection++;
|
||||||
|
if (selection > curresults)
|
||||||
|
{
|
||||||
|
selection = curresults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == 'A' || ch == 'k')
|
||||||
|
{
|
||||||
|
selection--;
|
||||||
|
if (selection <= 1)
|
||||||
|
{
|
||||||
|
selection = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch == '1')
|
||||||
|
{
|
||||||
|
selection1 = lapsdb.rows[selection-1].lap_id;
|
||||||
|
action = 1;
|
||||||
|
}
|
||||||
|
if (ch == '2')
|
||||||
|
{
|
||||||
|
selection2 = lapsdb.rows[selection-1].lap_id;
|
||||||
|
action = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wrefresh(bwin1);
|
||||||
|
delwin(bwin1);
|
||||||
|
endwin();
|
||||||
|
|
||||||
|
h_close_db(conn);
|
||||||
|
h_clean_connection(conn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include "../helper/parameters.h"
|
||||||
|
#include "../helper/confighelper.h"
|
||||||
|
|
||||||
|
int browseloop(Parameters* p, char* datadir);
|
||||||
|
|
@ -1,22 +1,32 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <MQTTClient.h>
|
#include <MQTTClient.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <hoel.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#include "hoeldb.h"
|
||||||
|
#include "telemetry.h"
|
||||||
#include "gameloop.h"
|
#include "gameloop.h"
|
||||||
#include "../helper/parameters.h"
|
#include "../helper/parameters.h"
|
||||||
#include "../helper/confighelper.h"
|
#include "../helper/confighelper.h"
|
||||||
|
#include "../helper/dirhelper.h"
|
||||||
#include "../simulatorapi/simapi/simapi/simdata.h"
|
#include "../simulatorapi/simapi/simapi/simdata.h"
|
||||||
#include "../simulatorapi/simapi/simapi/simmapper.h"
|
#include "../simulatorapi/simapi/simapi/simmapper.h"
|
||||||
#include "../slog/slog.h"
|
#include "../slog/slog.h"
|
||||||
|
|
||||||
#include <json-c/json.h>
|
#define DEFAULT_UPDATE_RATE 60
|
||||||
|
#define DATA_UPDATE_RATE 32
|
||||||
#define DEFAULT_UPDATE_RATE 100
|
#define TRACK_SAMPLE_RATE 4
|
||||||
|
#define SIM_CHECK_RATE 1
|
||||||
|
|
||||||
#define ADDRESS "tcp://localhost:1883"
|
#define ADDRESS "tcp://localhost:1883"
|
||||||
#define CLIENTID "gilles"
|
#define CLIENTID "gilles"
|
||||||
|
|
@ -99,7 +109,7 @@ int curses_init()
|
||||||
box(win4, 0, 0);
|
box(win4, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * removeSpacesFromStr(char *string)
|
char* removeSpacesFromStr(char* string)
|
||||||
{
|
{
|
||||||
int non_space_count = 0;
|
int non_space_count = 0;
|
||||||
|
|
||||||
|
|
@ -119,41 +129,195 @@ char * removeSpacesFromStr(char *string)
|
||||||
void update_date()
|
void update_date()
|
||||||
{
|
{
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
struct tm * timeinfo;
|
struct tm* timeinfo;
|
||||||
time ( &rawtime );
|
time ( &rawtime );
|
||||||
timeinfo = localtime ( &rawtime );
|
timeinfo = localtime ( &rawtime );
|
||||||
sprintf(datestring, "%.24s", asctime (timeinfo));
|
sprintf(datestring, "%.24s", asctime (timeinfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* looper(void* thargs)
|
|
||||||
|
int mainloop(Parameters* p)
|
||||||
{
|
{
|
||||||
Parameters* p = (Parameters*) thargs;
|
pthread_t ui_thread;
|
||||||
|
pthread_t mqtt_thread;
|
||||||
|
pthread_t mysql_thread;
|
||||||
|
|
||||||
SimData* simdata = malloc(sizeof(SimData));
|
SimData* simdata = malloc(sizeof(SimData));
|
||||||
SimMap* simmap = malloc(sizeof(SimMap));
|
SimMap* simmap = malloc(sizeof(SimMap));
|
||||||
|
|
||||||
int error = siminit(simdata, simmap, 1);
|
struct termios newsettings, canonicalmode;
|
||||||
if (error != GILLES_ERROR_NONE)
|
tcgetattr(0, &canonicalmode);
|
||||||
|
newsettings = canonicalmode;
|
||||||
|
newsettings.c_lflag &= (~ICANON & ~ECHO);
|
||||||
|
newsettings.c_cc[VMIN] = 1;
|
||||||
|
newsettings.c_cc[VTIME] = 0;
|
||||||
|
tcsetattr(0, TCSANOW, &newsettings);
|
||||||
|
char ch;
|
||||||
|
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
|
||||||
|
|
||||||
|
p->simdata = simdata;
|
||||||
|
p->simmap = simmap;
|
||||||
|
fprintf(stdout, "Searching for sim data... Press q to quit...\n");
|
||||||
|
|
||||||
|
double update_rate = SIM_CHECK_RATE;
|
||||||
|
int go = true;
|
||||||
|
char lastsimstatus = false;
|
||||||
|
while (go == true)
|
||||||
{
|
{
|
||||||
slogf("Fatal error getting simulator data");
|
|
||||||
//return error;
|
getSim(simdata, simmap, &p->simon, &p->sim);
|
||||||
|
|
||||||
|
if (p->simon == true && simdata->simstatus > 1)
|
||||||
|
{
|
||||||
|
p->program_state = 1;
|
||||||
|
if (p->cli == true)
|
||||||
|
{
|
||||||
|
if (pthread_create(&ui_thread, NULL, &clilooper, p) != 0)
|
||||||
|
{
|
||||||
|
printf("Uh-oh!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pthread_create(&ui_thread, NULL, &looper, p) != 0)
|
||||||
|
{
|
||||||
|
printf("Uh-oh!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (p->mqtt == true)
|
||||||
|
//{
|
||||||
|
// if (pthread_create(&mqtt_thread, NULL, &b4madmqtt, p) != 0)
|
||||||
|
// {
|
||||||
|
// printf("Uh-oh!\n");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
if (p->mysql == true)
|
||||||
|
{
|
||||||
|
if (pthread_create(&mysql_thread, NULL, &simviewmysql, p) != 0)
|
||||||
|
{
|
||||||
|
printf("Uh-oh!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_join(ui_thread, NULL);
|
||||||
|
p->program_state = -1;
|
||||||
|
//if (p->mqtt == true)
|
||||||
|
//{
|
||||||
|
// pthread_join(mqtt_thread, NULL);
|
||||||
|
//}
|
||||||
|
if (p->mysql == true)
|
||||||
|
{
|
||||||
|
pthread_join(mysql_thread, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->simon == true)
|
||||||
|
{
|
||||||
|
p->simon = false;
|
||||||
|
fprintf(stdout, "Searching for sim data... Press q again to quit...\n");
|
||||||
|
sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( poll(&mypoll, 1, 1000.0/update_rate) )
|
||||||
|
{
|
||||||
|
scanf("%c", &ch);
|
||||||
|
if(ch == 'q')
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fflush(stdout);
|
||||||
|
tcsetattr(0, TCSANOW, &canonicalmode);
|
||||||
|
|
||||||
|
free(simdata);
|
||||||
|
free(simmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* clilooper(void* thargs)
|
||||||
|
{
|
||||||
|
Parameters* p = (Parameters*) thargs;
|
||||||
|
SimData* simdata = p->simdata;
|
||||||
|
SimMap* simmap = p->simmap;
|
||||||
|
|
||||||
|
struct termios newsettings, canonicalmode;
|
||||||
|
tcgetattr(0, &canonicalmode);
|
||||||
|
newsettings = canonicalmode;
|
||||||
|
newsettings.c_lflag &= (~ICANON & ~ECHO);
|
||||||
|
newsettings.c_cc[VMIN] = 1;
|
||||||
|
newsettings.c_cc[VTIME] = 0;
|
||||||
|
tcsetattr(0, TCSANOW, &newsettings);
|
||||||
|
char ch;
|
||||||
|
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
|
||||||
|
|
||||||
|
fprintf(stdout, "Press q to quit...\n");
|
||||||
|
fprintf(stdout, "Press c for a useful readout of car telemetry...\n");
|
||||||
|
fprintf(stdout, "Press s for basic sesion information...\n");
|
||||||
|
fprintf(stdout, "Press l for basic lap / stint information...\n");
|
||||||
|
|
||||||
|
double update_rate = DEFAULT_UPDATE_RATE;
|
||||||
|
int go = true;
|
||||||
|
char lastsimstatus = false;
|
||||||
|
while (go == true && simdata->simstatus > 1)
|
||||||
|
{
|
||||||
|
simdatamap(simdata, simmap, p->sim);
|
||||||
|
|
||||||
|
if( poll(&mypoll, 1, 1000.0/update_rate) )
|
||||||
|
{
|
||||||
|
scanf("%c", &ch);
|
||||||
|
if(ch == 'q')
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
if(ch == 'c')
|
||||||
|
{
|
||||||
|
slogi("speed: %i gear: %i", simdata->velocity, simdata->gear);
|
||||||
|
}
|
||||||
|
if(ch == 's')
|
||||||
|
{
|
||||||
|
slogi("status: %i", simdata->simstatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
fflush(stdout);
|
||||||
|
tcsetattr(0, TCSANOW, &canonicalmode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* looper(void* thargs)
|
||||||
|
{
|
||||||
|
Parameters* p = (Parameters*) thargs;
|
||||||
|
SimData* simdata = p->simdata;
|
||||||
|
SimMap* simmap = p->simmap;
|
||||||
|
|
||||||
curses_init();
|
curses_init();
|
||||||
|
|
||||||
timeout(DEFAULT_UPDATE_RATE);
|
timeout(DEFAULT_UPDATE_RATE);
|
||||||
|
|
||||||
int go = true;
|
int go = true;
|
||||||
char lastsimstatus = false;
|
char lastsimstatus = false;
|
||||||
while (go == true)
|
while (go == true && simdata->simstatus > 1)
|
||||||
{
|
{
|
||||||
simdatamap(simdata, simmap, 1);
|
simdatamap(simdata, simmap, p->sim);
|
||||||
|
|
||||||
wclear(win1);
|
wclear(win1);
|
||||||
wclear(win2);
|
wclear(win2);
|
||||||
wclear(win3);
|
wclear(win3);
|
||||||
wclear(win4);
|
wclear(win4);
|
||||||
|
|
||||||
{ // window 1 car diagnostics
|
{
|
||||||
|
// window 1 car diagnostics
|
||||||
|
|
||||||
char spacer[14];
|
char spacer[14];
|
||||||
sprintf(spacer, "\n");
|
sprintf(spacer, "\n");
|
||||||
|
|
@ -308,7 +472,8 @@ void* looper(void* thargs)
|
||||||
rectangle(18, 18, 22, 22); // right rear
|
rectangle(18, 18, 22, 22); // right rear
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // window 2 session info
|
{
|
||||||
|
// window 2 session info
|
||||||
|
|
||||||
char spacer[14];
|
char spacer[14];
|
||||||
sprintf(spacer, "\n");
|
sprintf(spacer, "\n");
|
||||||
|
|
@ -371,7 +536,8 @@ void* looper(void* thargs)
|
||||||
wattrset(win2, COLOR_PAIR(1));
|
wattrset(win2, COLOR_PAIR(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // window 3 basic timing and scoring
|
{
|
||||||
|
// window 3 basic timing and scoring
|
||||||
|
|
||||||
char spacer[14];
|
char spacer[14];
|
||||||
sprintf(spacer, "\n");
|
sprintf(spacer, "\n");
|
||||||
|
|
@ -436,7 +602,8 @@ void* looper(void* thargs)
|
||||||
wattrset(win3, COLOR_PAIR(1));
|
wattrset(win3, COLOR_PAIR(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // window 4 live standings timing and scoring
|
{
|
||||||
|
// window 4 live standings timing and scoring
|
||||||
char spacer[14];
|
char spacer[14];
|
||||||
sprintf(spacer, "\n");
|
sprintf(spacer, "\n");
|
||||||
waddstr(win4, spacer);
|
waddstr(win4, spacer);
|
||||||
|
|
@ -471,7 +638,9 @@ void* looper(void* thargs)
|
||||||
for(i=0; i<displaycars; i++)
|
for(i=0; i<displaycars; i++)
|
||||||
{
|
{
|
||||||
if((ihold+1)==simdata->cars[i].pos)
|
if((ihold+1)==simdata->cars[i].pos)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wattrset(win4, COLOR_PAIR(2));
|
wattrset(win4, COLOR_PAIR(2));
|
||||||
|
|
@ -501,8 +670,8 @@ void* looper(void* thargs)
|
||||||
|
|
||||||
if(simdata->cars[i].inpitlane == 0 && simdata->cars[i].inpit == 0)
|
if(simdata->cars[i].inpitlane == 0 && simdata->cars[i].inpit == 0)
|
||||||
{
|
{
|
||||||
wattrset(win4, COLOR_PAIR(1));
|
wattrset(win4, COLOR_PAIR(1));
|
||||||
wprintw(win4, " ontrack ");
|
wprintw(win4, " ontrack ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -553,159 +722,191 @@ void* looper(void* thargs)
|
||||||
delwin(win1);
|
delwin(win1);
|
||||||
endwin();
|
endwin();
|
||||||
|
|
||||||
free(simdata);
|
|
||||||
free(simmap);
|
|
||||||
|
|
||||||
//return 0;
|
//return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* b4madmqtt(void* thargs)
|
void* simviewmysql(void* thargs)
|
||||||
{
|
{
|
||||||
Parameters* p = (Parameters*) thargs;
|
Parameters* p = (Parameters*) thargs;
|
||||||
SimData* simdata = malloc(sizeof(SimData));
|
SimData* simdata = p->simdata;
|
||||||
SimMap* simmap = malloc(sizeof(SimMap));
|
SimMap* simmap = p->simmap;
|
||||||
long unix_time_start;
|
|
||||||
char time_buff[11];
|
|
||||||
|
|
||||||
int error = siminit(simdata, simmap, 1);
|
struct _h_result result;
|
||||||
if (error != GILLES_ERROR_NONE)
|
struct _h_connection* conn;
|
||||||
|
conn = h_connect_pgsql(p->db_conn);
|
||||||
|
|
||||||
|
if (conn == NULL)
|
||||||
{
|
{
|
||||||
slogf("Fatal error getting simulator data");
|
slogf("Unable to connect to configured Gilles database. Are the parameters in the config correct? Is the user allowed to access from this address?");
|
||||||
//return error;
|
p->err = E_FAILED_DB_CONN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
slogi("Starting telemetry");
|
||||||
|
|
||||||
|
int trackconfig = gettrack(conn, simdata->track);
|
||||||
|
if (trackconfig == -1)
|
||||||
|
{
|
||||||
|
slogf("Problem performing select query. Does the db user have read permissions?");
|
||||||
|
p->err = E_FAILED_DB_CONN;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mqtt = p->mqtt;
|
trackconfig = addtrackconfig(conn, trackconfig, simdata->track, simdata->trackdistancearound);
|
||||||
bool mqtt_connected = false;
|
if (trackconfig == -1)
|
||||||
|
|
||||||
MQTTClient client;
|
|
||||||
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
|
|
||||||
MQTTClient_message pubmsg = MQTTClient_message_initializer;
|
|
||||||
MQTTClient_deliveryToken token;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
// Create a new MQTT client
|
|
||||||
MQTTClient_create(&client, ADDRESS, CLIENTID,
|
|
||||||
MQTTCLIENT_PERSISTENCE_NONE, NULL);
|
|
||||||
|
|
||||||
// Connect to the MQTT server
|
|
||||||
if (mqtt == true)
|
|
||||||
{
|
{
|
||||||
conn_opts.keepAliveInterval = 20;
|
slogf("Problem performing insert query. Does the db user have write permissions?");
|
||||||
conn_opts.cleansession = 1;
|
p->err = E_FAILED_DB_CONN;
|
||||||
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
|
return 0;
|
||||||
MQTTClient_disconnect(client, 10000);
|
|
||||||
sloge("Failed to connect, return code %d", rc);
|
|
||||||
return NULL;
|
|
||||||
//exit(-1);
|
|
||||||
}
|
|
||||||
mqtt_connected = true;
|
|
||||||
}
|
}
|
||||||
|
slogt("Detected track configuration id: %i", trackconfig);
|
||||||
|
int eventid = addevent(conn, trackconfig);
|
||||||
|
int driverid = getdriver(conn, simdata->driver);
|
||||||
|
driverid = adddriver(conn, driverid, simdata->driver);
|
||||||
|
int carid = getcar(conn, simdata->car);
|
||||||
|
carid = addcar(conn, carid, simdata->car);
|
||||||
|
|
||||||
int go = false;
|
// ?? close last session
|
||||||
if (mqtt_connected == true)
|
|
||||||
{
|
int pitstatus = simdata->inpit;
|
||||||
go = true;
|
int sessionstatus = 0;
|
||||||
}
|
int lastpitstatus = pitstatus;
|
||||||
|
int lastsessionstatus = 0;
|
||||||
|
int lap = 0;
|
||||||
|
int lastlap = 0;
|
||||||
|
int sector = 0;
|
||||||
|
int lastsector = 0;
|
||||||
|
|
||||||
|
int stintid = 0;
|
||||||
|
int stintlapid = 0;
|
||||||
|
int sessionid = 0;
|
||||||
|
sessionid = addsession(conn, eventid, carid, simdata->session, simdata->airtemp, simdata->tracktemp, simdata);
|
||||||
|
stintid = addstint(conn, sessionid, driverid, carid, simdata);
|
||||||
|
stintlapid = addstintlap(conn, stintid, simdata);
|
||||||
|
sessionstatus = simdata->session;
|
||||||
|
lastsessionstatus = sessionstatus;
|
||||||
|
lap = simdata->lap;
|
||||||
|
lastlap = lap;
|
||||||
|
double update_rate = DATA_UPDATE_RATE;
|
||||||
|
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
|
||||||
|
int go = true;
|
||||||
char lastsimstatus = false;
|
char lastsimstatus = false;
|
||||||
while (go == true && p->program_state == 1)
|
int tick = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int track_samples = simdata->trackspline / TRACK_SAMPLE_RATE;
|
||||||
|
slogt("track samples %i", track_samples);
|
||||||
|
|
||||||
|
int stintlaps = 1;
|
||||||
|
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));
|
||||||
|
|
||||||
|
int sectortimes[4];
|
||||||
|
|
||||||
|
if (p->program_state < 0)
|
||||||
|
{
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (go == true)
|
||||||
{
|
{
|
||||||
|
|
||||||
char simstatus = (simdata->simstatus > 0) ? true : false;
|
slogt("tick %i", tick);
|
||||||
if (simdata->simstatus > 0 && simstatus != lastsimstatus)
|
int pos = (int) track_samples * simdata->playerspline;
|
||||||
|
slogt("pos %f normpos %i of samples %i", simdata->playerspline, pos, track_samples);
|
||||||
|
|
||||||
|
steerdata[pos] = simdata->steer;
|
||||||
|
acceldata[pos] = simdata->gas;
|
||||||
|
brakedata[pos] = simdata->brake;
|
||||||
|
speeddata[pos] = simdata->velocity;
|
||||||
|
rpmdata[pos] = simdata->rpms;
|
||||||
|
geardata[pos] = simdata->gear;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sessionstatus = simdata->session;
|
||||||
|
lap = simdata->lap;
|
||||||
|
sector = simdata->sectorindex;
|
||||||
|
if (simdata->lapisvalid == false && validind == true)
|
||||||
{
|
{
|
||||||
//update_date();
|
validind = false;
|
||||||
unix_time_start = (unsigned long) time(NULL);
|
|
||||||
sprintf(time_buff, "%lu", unix_time_start);
|
|
||||||
//sprintf(time_buff, "%lu", (unsigned long)time(NULL));
|
|
||||||
//newdatestring = removeSpacesFromStr(datestring);
|
|
||||||
}
|
}
|
||||||
lastsimstatus = simstatus;
|
sectortimes[simdata->sectorindex] = simdata->lastsectorinms;
|
||||||
simdatamap(simdata, simmap, 1);
|
if (sessionstatus != lastsessionstatus)
|
||||||
|
|
||||||
if (mqtt_connected == true && simdata->simstatus > 0)
|
|
||||||
{
|
{
|
||||||
|
closestint(conn, stintid, stintlaps, validstintlaps);
|
||||||
|
closesession(conn, sessionid);
|
||||||
|
if (sessionstatus > 1)
|
||||||
|
{
|
||||||
|
sessionid = addsession(conn, eventid, carid, simdata->session, simdata->airtemp, simdata->tracktemp, simdata);
|
||||||
|
}
|
||||||
|
|
||||||
json_object *root = json_object_new_object();
|
//pitstatus = 1;
|
||||||
//if (!root)
|
stintlaps = 1;
|
||||||
// return;
|
validstintlaps = 0;
|
||||||
|
}
|
||||||
|
pitstatus = simdata->inpit;
|
||||||
|
if (simdata->inpit == true && pitstatus != lastpitstatus)
|
||||||
|
{
|
||||||
|
//pitstatus = 1;
|
||||||
|
//}
|
||||||
|
//if (pitstatus = 0 && pitstatus != lastpitstatus)
|
||||||
|
//{
|
||||||
|
// close last stint
|
||||||
|
|
||||||
json_object *child = json_object_new_object();
|
closestint(conn, stintid, stintlaps, validstintlaps);
|
||||||
|
stintid = addstint(conn, sessionid, driverid, carid, simdata);
|
||||||
|
stintlaps = 1;
|
||||||
|
validstintlaps = 0;
|
||||||
|
}
|
||||||
|
if (lap != lastlap)
|
||||||
|
{
|
||||||
|
slogt("New lap detected");
|
||||||
|
stintlaps++;
|
||||||
|
if (validind == true)
|
||||||
|
{
|
||||||
|
validstintlaps++;
|
||||||
|
}
|
||||||
|
|
||||||
struct timeval tv;
|
closelap(conn, stintlapid, sectortimes[1], sectortimes[2], simdata->lastsectorinms, 0, 0, 0, 0, simdata);
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
unsigned long long millisecondsSinceEpoch = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
|
|
||||||
|
|
||||||
json_object_object_add(root, "time", json_object_new_int64(millisecondsSinceEpoch)); //unix time milliseconds
|
stintlapid = addstintlap(conn, stintid, simdata);
|
||||||
|
int telemid = addtelemetry(conn, track_samples, stintlapid);
|
||||||
const char* topic_root = "racing/gilles/TuxRacerX";
|
int b = updatetelemetrydata(conn, track_samples, telemid, stintlapid, speeddata, geardata, rpmdata, steerdata, acceldata, brakedata);
|
||||||
//const char* game_name = "Assetto Corsa (64 bit)";
|
tick = 0;
|
||||||
const char* game_name = "assetto_64_bit";
|
// assume lap is valid until it isn't
|
||||||
const char* session_type = "Practice";
|
validind = true;
|
||||||
|
|
||||||
json_object_object_add(child, "CarModel", json_object_new_string(simdata->car));
|
|
||||||
json_object_object_add(child, "GameName", json_object_new_string(game_name));
|
|
||||||
json_object_object_add(child, "SessionId", json_object_new_int(unix_time_start));
|
|
||||||
json_object_object_add(child, "SessionTypeName", json_object_new_string("Practice"));
|
|
||||||
json_object_object_add(child, "TrackCode", json_object_new_string(simdata->track));
|
|
||||||
|
|
||||||
json_object_object_add(child, "Clutch", json_object_new_double(simdata->clutch));
|
|
||||||
json_object_object_add(child, "Brake", json_object_new_double(simdata->brake));
|
|
||||||
json_object_object_add(child, "Throtte", json_object_new_double(simdata->gas));
|
|
||||||
json_object_object_add(child, "HandBrake", json_object_new_double(simdata->handbrake));
|
|
||||||
json_object_object_add(child, "SteeringAngle", json_object_new_double(simdata->steer));
|
|
||||||
json_object_object_add(child, "Rpms", json_object_new_int(simdata->rpms));
|
|
||||||
json_object_object_add(child, "Gear", json_object_new_int(simdata->gear));
|
|
||||||
json_object_object_add(child, "SpeedMs", json_object_new_double(simdata->velocity * 0.2777778));
|
|
||||||
json_object_object_add(child, "DistanceRoundTrack", json_object_new_double(simdata->trackdistancearound));
|
|
||||||
json_object_object_add(child, "WorldPosition_x", json_object_new_double(simdata->worldposx));
|
|
||||||
json_object_object_add(child, "WorldPosition_y", json_object_new_double(simdata->worldposy));
|
|
||||||
json_object_object_add(child, "WorldPosition_z", json_object_new_double(simdata->worldposz));
|
|
||||||
json_object_object_add(child, "CurrentLap", json_object_new_int(simdata->playerlaps));
|
|
||||||
json_object_object_add(child, "CurrentLapTime", json_object_new_int(simdata->currentlapinseconds));
|
|
||||||
json_object_object_add(child, "LapTimePrevious", json_object_new_int(simdata->lastlapinseconds));
|
|
||||||
json_object_object_add(child, "CurrentLapIsValid", json_object_new_int(simdata->lapisvalid));
|
|
||||||
json_object_object_add(child, "PreviousLapWasValid", json_object_new_int(1));
|
|
||||||
|
|
||||||
json_object_object_add(root, "telemetry", child);
|
|
||||||
|
|
||||||
slogi(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
|
||||||
|
|
||||||
// TODO: generate this topic string only once
|
|
||||||
char* topic = ( char* ) malloc(1 + strlen(topic_root) + strlen("/") + strlen(game_name) + strlen("/") + strlen(session_type)
|
|
||||||
+ strlen("/") + strlen(simdata->car) + strlen("/") + strlen(simdata->track) + strlen("/") + 11);
|
|
||||||
strcpy(topic, topic_root);
|
|
||||||
strcat(topic, "/");
|
|
||||||
strcat(topic, time_buff);
|
|
||||||
strcat(topic, "/");
|
|
||||||
strcat(topic, game_name);
|
|
||||||
strcat(topic, "/");
|
|
||||||
strcat(topic, simdata->track);
|
|
||||||
strcat(topic, "/");
|
|
||||||
strcat(topic, simdata->car);
|
|
||||||
strcat(topic, "/");
|
|
||||||
strcat(topic, session_type);
|
|
||||||
|
|
||||||
char* payload1;
|
|
||||||
sprintf(payload1, json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
|
||||||
pubmsg.payload = payload1;
|
|
||||||
//pubmsg.payload = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY);
|
|
||||||
//pubmsg.payloadlen = strlen(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
|
||||||
pubmsg.payloadlen = strlen(payload1);
|
|
||||||
pubmsg.qos= QOS;
|
|
||||||
pubmsg.retained = 0;
|
|
||||||
|
|
||||||
MQTTClient_publishMessage(client, topic, &pubmsg, &token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
lastpitstatus = pitstatus;
|
||||||
if (mqtt_connected == true)
|
lastsessionstatus = sessionstatus;
|
||||||
{
|
lastsector = sector;
|
||||||
MQTTClient_disconnect(client, 10000);
|
lastlap = lap;
|
||||||
}
|
tick++;
|
||||||
MQTTClient_destroy(&client);
|
|
||||||
|
|
||||||
free(simdata);
|
|
||||||
free(simmap);
|
poll(&mypoll, 1, 1000 / DATA_UPDATE_RATE);
|
||||||
return NULL;
|
|
||||||
//return 0;
|
if (p->program_state < 0)
|
||||||
|
{
|
||||||
|
int telemid = addtelemetry(conn, track_samples, stintlapid);
|
||||||
|
int b = updatetelemetrydata(conn, track_samples, telemid, stintlapid, speeddata, geardata, rpmdata, steerdata, acceldata, brakedata);
|
||||||
|
closelap(conn, stintlapid, sectortimes[1], sectortimes[2], simdata->lastsectorinms, 0, 0, 0, 0, simdata);
|
||||||
|
closestint(conn, stintid, stintlaps, validstintlaps);
|
||||||
|
closesession(conn, sessionid);
|
||||||
|
go = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h_close_db(conn);
|
||||||
|
h_clean_connection(conn);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#include "../helper/parameters.h"
|
#include "../helper/parameters.h"
|
||||||
#include "../helper/confighelper.h"
|
#include "../helper/confighelper.h"
|
||||||
|
|
||||||
|
int mainloop(Parameters* p);
|
||||||
|
void* clilooper(void* params);
|
||||||
void* looper(void* params);
|
void* looper(void* params);
|
||||||
void* b4madmqtt(void* params);
|
void* b4madmqtt(void* params);
|
||||||
|
void* simviewmysql(void* params);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,676 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <hoel.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#include "hoeldb.h"
|
||||||
|
#include "../simulatorapi/simapi/simapi/simdata.h"
|
||||||
|
#include "../helper/confighelper.h"
|
||||||
|
#include "../slog/slog.h"
|
||||||
|
|
||||||
|
int getLastInsertID(struct _h_connection* conn)
|
||||||
|
{
|
||||||
|
json_t* last_id = (h_last_insert_id(conn));
|
||||||
|
int id = json_integer_value(last_id);
|
||||||
|
json_decref(last_id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(515 * sizeof(char));
|
||||||
|
slogt("Performing query sessions");
|
||||||
|
|
||||||
|
sprintf(query, "select sessions.session_id, events.event_id, sessions.event_type, table1.stints, track_config.display_name, cars.car_name, start_time "
|
||||||
|
"FROM %s JOIN events ON sessions.event_id=events.event_id JOIN track_config ON events.track_config_id=track_config.track_config_id "
|
||||||
|
"JOIN cars ON sessions.car_id=cars.car_id "
|
||||||
|
"JOIN (Select session_id, COUNT(stint_id) AS stints FROM stints GROUP BY session_id) AS table1 ON table1.session_id=sessions.session_id "
|
||||||
|
"ORDER BY session_id DESC LIMIT 25", "Sessions");
|
||||||
|
|
||||||
|
int errcode = h_query_select(conn, query, &result);
|
||||||
|
if (errcode == H_OK)
|
||||||
|
{
|
||||||
|
sess->rows = malloc(sizeof(SessionRowData) * result.nb_rows);
|
||||||
|
get_row_results(result, sess->fields, sess->rows, sizeof(SessionRowData));
|
||||||
|
h_clean_result(&result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
slogt("execute query %s", query);
|
||||||
|
int errcode = h_query_select(conn, query, &result);
|
||||||
|
if (errcode == H_OK)
|
||||||
|
{
|
||||||
|
stint->rows = malloc(sizeof(StintRowData) * result.nb_rows);
|
||||||
|
get_row_results(result, stint->fields, stint->rows, sizeof(StintRowData));
|
||||||
|
h_clean_result(&result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
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(250 * sizeof(char));
|
||||||
|
slogt("Performing query laps");
|
||||||
|
|
||||||
|
sprintf(query, "select lap_id, stint_id, sector_1, sector_2, sector_3, grip, tyre, time, cuts, crashes, max_speed, avg_speed, finished_at FROM %s WHERE %s=%i", "Laps", "stint_id", use_id);
|
||||||
|
int errcode = h_query_select(conn, query, &result);
|
||||||
|
if (errcode == H_OK)
|
||||||
|
{
|
||||||
|
laps->rows = malloc(sizeof(LapRowData) * result.nb_rows);
|
||||||
|
get_row_results(result, laps->fields, laps->rows, sizeof(LapRowData));
|
||||||
|
h_clean_result(&result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(query);
|
||||||
|
|
||||||
|
return result.nb_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gettrack(struct _h_connection* conn, const char* trackname)
|
||||||
|
{
|
||||||
|
|
||||||
|
json_t* j_result;
|
||||||
|
char* where_clause = h_build_where_clause(conn, "config_name=%s AND track_name=%s", "default", trackname);
|
||||||
|
json_t* j_query = json_pack("{sss[s]s{s{ssss}}}", "table", "track_config", "columns", "track_config_id", "where", " ", "operator", "raw",
|
||||||
|
"value", where_clause);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_select(conn, j_query, &j_result, &qq);
|
||||||
|
|
||||||
|
// Deallocate j_query since it won't be needed anymore
|
||||||
|
//json_decref(j_query);
|
||||||
|
//h_free(where_clause);
|
||||||
|
int track_config = -1;
|
||||||
|
// 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);
|
||||||
|
//if (index1 == 0)
|
||||||
|
//{
|
||||||
|
// slogw("no config for this track");
|
||||||
|
//}
|
||||||
|
//else {
|
||||||
|
json_t* jj = json_array_get(j_result, index1-1);
|
||||||
|
track_config = json_integer_value(json_object_get(jj, "track_config_id"));
|
||||||
|
//}
|
||||||
|
// Deallocate data result
|
||||||
|
|
||||||
|
//free(dump);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing select query %s: %d", qq, res);
|
||||||
|
}
|
||||||
|
json_decref(j_result);
|
||||||
|
free(qq);
|
||||||
|
json_decref(j_query);
|
||||||
|
h_free(where_clause);
|
||||||
|
return track_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getdriver(struct _h_connection* conn, const char* driver_name)
|
||||||
|
{
|
||||||
|
json_t* j_result;
|
||||||
|
char* where_clause = h_build_where_clause(conn, "driver_name=%s", driver_name);
|
||||||
|
json_t* j_query = json_pack("{sss[s]s{s{ssss}}}","table", "drivers", "columns", "driver_id", "where", " ", "operator", "raw",
|
||||||
|
"value", where_clause);
|
||||||
|
|
||||||
|
slogi("Looking for driver named %s", driver_name);
|
||||||
|
char* qq;
|
||||||
|
int res = h_select(conn, j_query, &j_result, &qq);
|
||||||
|
//slogi("here your query: %s", qq);
|
||||||
|
// Deallocate j_query since it won't be needed anymore
|
||||||
|
int driver_id = -1;
|
||||||
|
// Test query execution result
|
||||||
|
if (res == H_OK)
|
||||||
|
{
|
||||||
|
// Print result
|
||||||
|
char* dump = json_dumps(j_result, JSON_INDENT(2));
|
||||||
|
slogt("json select result is\n%s", dump);
|
||||||
|
int index1 = json_array_size(j_result);
|
||||||
|
if (index1 == 0)
|
||||||
|
{
|
||||||
|
slogw("no driver by this name");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json_t* jj = json_array_get(j_result, index1-1);
|
||||||
|
driver_id = json_integer_value(json_object_get(jj, "driver_id"));
|
||||||
|
}
|
||||||
|
// Deallocate data result
|
||||||
|
free(dump);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing select query %s: %d", qq, res);
|
||||||
|
}
|
||||||
|
json_decref(j_result);
|
||||||
|
free(qq);
|
||||||
|
json_decref(j_query);
|
||||||
|
h_free(where_clause);
|
||||||
|
return driver_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getcar(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", "cars", "columns", "car_id", "where", " ", "operator", "raw",
|
||||||
|
"value", where_clause);
|
||||||
|
|
||||||
|
slogi("Looking for car named %s", carname);
|
||||||
|
char* qq;
|
||||||
|
int res = h_select(conn, j_query, &j_result, &qq);
|
||||||
|
//slogi("here your query: %s", qq);
|
||||||
|
// Deallocate j_query since it won't be needed anymore
|
||||||
|
|
||||||
|
int car_id = -1;
|
||||||
|
// Test query execution result
|
||||||
|
if (res == H_OK)
|
||||||
|
{
|
||||||
|
// Print result
|
||||||
|
char* dump = json_dumps(j_result, JSON_INDENT(2));
|
||||||
|
slogt("json select result is\n%s", dump);
|
||||||
|
int index1 = json_array_size(j_result);
|
||||||
|
if (index1 == 0)
|
||||||
|
{
|
||||||
|
slogw("no car by this name");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json_t* jj = json_array_get(j_result, index1-1);
|
||||||
|
car_id = json_integer_value(json_object_get(jj, "car_id"));
|
||||||
|
}
|
||||||
|
// Deallocate data result
|
||||||
|
free(dump);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sloge("Error executing select query %s: %d", qq, res);
|
||||||
|
}
|
||||||
|
json_decref(j_result);
|
||||||
|
free(qq);
|
||||||
|
json_decref(j_query);
|
||||||
|
h_free(where_clause);
|
||||||
|
return car_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// inserts
|
||||||
|
int addtrackconfig(struct _h_connection* conn, int trackconfigid, const char* track, int length)
|
||||||
|
{
|
||||||
|
//track_config_id | track_name | config_name | display_name | country | city | length
|
||||||
|
if (trackconfigid > 0)
|
||||||
|
{
|
||||||
|
return trackconfigid;
|
||||||
|
}
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("track_config") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "track_name", json_string(track));
|
||||||
|
json_object_set_new(values, "config_name", json_string("default"));
|
||||||
|
json_object_set_new(values, "display_name", json_string(track));
|
||||||
|
json_object_set_new(values, "country", json_string("USA"));
|
||||||
|
json_object_set_new(values, "city", json_string("USA"));
|
||||||
|
json_object_set_new(values, "length", json_integer(length));
|
||||||
|
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("track config insert result %i", res);
|
||||||
|
sloge("track config query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackconfigid = getLastInsertID(conn);
|
||||||
|
return trackconfigid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addsession(struct _h_connection* conn, int eventid, int carid, int eventtype, int airtemp, int tracktemp, SimData* simdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
// session_id | event_id | event_type | track_time | session_name
|
||||||
|
// | start_time | duration_min | elapsed_ms | laps | weather |
|
||||||
|
// air_temp | road_temp | start_grip |
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("sessions") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "event_id", json_integer(eventid));
|
||||||
|
json_object_set_new(values, "car_id", json_integer(carid));
|
||||||
|
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, "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);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("track config insert result %i", res);
|
||||||
|
sloge("track config query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int adddriver(struct _h_connection* conn, int driverid, const char* drivername)
|
||||||
|
{
|
||||||
|
if (driverid > 0)
|
||||||
|
{
|
||||||
|
return driverid;
|
||||||
|
}
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("drivers") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "driver_name", json_string(drivername));
|
||||||
|
json_object_set_new(values, "prev_name", json_string(drivername));
|
||||||
|
json_object_set_new(values, "steam64_id", json_integer(17));
|
||||||
|
json_object_set_new(values, "country", json_string("USA"));
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("driver insert result %i", res);
|
||||||
|
sloge("driver insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
driverid = getLastInsertID(conn);
|
||||||
|
return driverid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int addevent(struct _h_connection* conn, int track_config)
|
||||||
|
{
|
||||||
|
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("events") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "track_config_id", json_integer(track_config));
|
||||||
|
json_object_set_new(values, "event_name", json_string("default"));
|
||||||
|
//event_id | server_name | track_config_id | event_name | team_event | active | livery_preview | use_number | practice_duration | quali_duration | race_duration | race_duration_type | race_wait_time | race_extra_laps | reverse_grid_positions
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("event insert result %i", res);
|
||||||
|
sloge("event insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid, SimData* simdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("stints") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
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, "laps", json_integer(0));
|
||||||
|
json_object_set_new(values, "valid_laps", json_integer(0));
|
||||||
|
json_object_set_new(values, "tyre", json_string(simdata->tyrecompound) );
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("stint insert result %i", res);
|
||||||
|
sloge("stint insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addstintlap(struct _h_connection* conn, int stintid, SimData* simdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
slogt("adding stint lap");
|
||||||
|
// stint laps
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("laps") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
|
||||||
|
json_object_set_new(values, "stint_id", json_integer(stintid));
|
||||||
|
json_object_set_new(values, "tyre", json_string(simdata->tyrecompound) );
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("stint lap insert result %i", res);
|
||||||
|
sloge("stint lap insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addcar(struct _h_connection* conn, int carid, const char* carname)
|
||||||
|
{
|
||||||
|
|
||||||
|
// car_id | display_name | car_name | manufacturer | car_class
|
||||||
|
|
||||||
|
if (carid > 0)
|
||||||
|
{
|
||||||
|
return carid;
|
||||||
|
}
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("cars") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "display_name", json_string(carname));
|
||||||
|
json_object_set_new(values, "car_name", json_string(carname));
|
||||||
|
json_object_set_new(values, "manufacturer", json_string("Unknown"));
|
||||||
|
json_object_set_new(values, "car_class", json_string("Unknown"));
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("car insert result %i", res);
|
||||||
|
sloge("car insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addtelemetry(struct _h_connection* conn, int points, int stintid)
|
||||||
|
{
|
||||||
|
|
||||||
|
slogt("adding telemetry record");
|
||||||
|
|
||||||
|
json_t* root = json_object();
|
||||||
|
json_t* json_arr = json_array();
|
||||||
|
|
||||||
|
json_object_set_new( root, "table", json_string("telemetry") );
|
||||||
|
json_object_set_new( root, "values", json_arr );
|
||||||
|
|
||||||
|
json_t* values = json_object();
|
||||||
|
json_object_set_new(values, "lap_id", json_integer(stintid));
|
||||||
|
json_object_set_new(values, "points", json_integer(points));
|
||||||
|
json_array_append(json_arr, values);
|
||||||
|
|
||||||
|
char* qq;
|
||||||
|
int res = h_insert(conn, root, &qq);
|
||||||
|
json_decref(root);
|
||||||
|
json_decref(values);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
sloge("telemetry insert result %i", res);
|
||||||
|
sloge("telemetry insert query %s", qq);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getLastInsertID(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int closelap(struct _h_connection* conn, int lapid, int sector1, int sector2, int sector3, int cuts, int crashes, int maxspeed, int avgspeed, SimData* simdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
// stint laps
|
||||||
|
// lap_id | stint_id | sector_1 | sector_2 | sector_3 | grip | tyre | time | cuts | crashes
|
||||||
|
// max_speed | avg_speed | finished_at
|
||||||
|
|
||||||
|
slogt("closing previous lap ", lapid);
|
||||||
|
|
||||||
|
char* query = malloc((sizeof(char)*650));
|
||||||
|
sprintf(query, "UPDATE %s SET %s=%i, %s=%i, %s=%i, %s=%i, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, finished_at=NOW() WHERE lap_id=%i;",
|
||||||
|
"laps", "time", simdata->lastlap, "sector_1", sector1, "sector_2", sector2, "sector_3", sector3,
|
||||||
|
"right_front_tyre_temp", simdata->tyretemp[1],
|
||||||
|
"right_rear_tyre_temp", simdata->tyretemp[3],
|
||||||
|
"right_front_tyre_wear", simdata->tyrewear[1],
|
||||||
|
"right_rear_tyre_wear", simdata->tyrewear[3],
|
||||||
|
"right_front_tyre_press",simdata->tyrepressure[1],
|
||||||
|
"right_rear_tyre_press", simdata->tyrepressure[3],
|
||||||
|
"right_front_brake_temp",simdata->braketemp[1],
|
||||||
|
"right_rear_brake_temp", simdata->braketemp[3],
|
||||||
|
"left_front_tyre_temp", simdata->tyretemp[0],
|
||||||
|
"left_rear_tyre_temp", simdata->tyretemp[2],
|
||||||
|
"left_front_tyre_wear", simdata->tyrewear[0],
|
||||||
|
"left_rear_tyre_wear", simdata->tyrewear[2],
|
||||||
|
"left_front_tyre_press",simdata->tyrepressure[0],
|
||||||
|
"left_rear_tyre_press", simdata->tyrepressure[2],
|
||||||
|
"left_front_brake_temp",simdata->braketemp[0],
|
||||||
|
"left_rear_brake_temp", simdata->braketemp[2],
|
||||||
|
lapid);
|
||||||
|
|
||||||
|
int errcode = h_query_update(conn, query);
|
||||||
|
if (errcode != H_OK)
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
slogt("closed previous lap");
|
||||||
|
free(query);
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int closesession(struct _h_connection* conn, int sessionid)
|
||||||
|
{
|
||||||
|
|
||||||
|
slogt("closing previous session ", 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)*100));
|
||||||
|
sprintf(query, "UPDATE %s SET is_finished=1, finished_at=NOW() WHERE session_id=%i",
|
||||||
|
"sessions", sessionid);
|
||||||
|
|
||||||
|
int errcode = h_query_update(conn, query);
|
||||||
|
if (errcode != H_OK)
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
slogt("closed previous session");
|
||||||
|
free(query);
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int closestint(struct _h_connection* conn, int stintid, int stintlaps, int validstintlaps)
|
||||||
|
{
|
||||||
|
|
||||||
|
// best_lap_id
|
||||||
|
slogt("closing previous stint ", stintid);
|
||||||
|
|
||||||
|
char* query = malloc((sizeof(char)*146));
|
||||||
|
sprintf(query, "UPDATE %s SET %s = %i, %s = %i, is_finished=1, finished_at=NOW() WHERE stint_id=%i",
|
||||||
|
"stints", "laps", stintlaps, "valid_laps", validstintlaps, stintid);
|
||||||
|
|
||||||
|
int errcode = h_query_update(conn, query);
|
||||||
|
if (errcode != H_OK)
|
||||||
|
{
|
||||||
|
sloge("Error executing query %s returned %i", query, errcode);
|
||||||
|
free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
slogt("closed previous stint");
|
||||||
|
free(query);
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
|
||||||
|
#ifndef _HOELDB_H
|
||||||
|
#define _HOELDB_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../simulatorapi/simapi/simapi/simdata.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[27];
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned char track[150];
|
||||||
|
unsigned char car[150];
|
||||||
|
PDBTimeStamp start_time;
|
||||||
|
//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;
|
||||||
|
unsigned char tyre[10];
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
PDBTimeStamp finished_at;
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
LapRowData;
|
||||||
|
|
||||||
|
typedef struct SessionDbo
|
||||||
|
{
|
||||||
|
int numrows;
|
||||||
|
bool hasdata;
|
||||||
|
|
||||||
|
DBField fields[7];
|
||||||
|
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[13];
|
||||||
|
LapRowData* rows;
|
||||||
|
}
|
||||||
|
LapDbo;
|
||||||
|
|
||||||
|
int getLastInsertID(struct _h_connection* conn);
|
||||||
|
|
||||||
|
void get_row_results(struct _h_result result, DBField* fields, void* rows, size_t rowsize);
|
||||||
|
|
||||||
|
int getsessions(struct _h_connection* conn, const char* sessionname, SessionDbo* sess);
|
||||||
|
|
||||||
|
int getstints(struct _h_connection* conn, const char* sessionname, StintDbo* stint, int use_id);
|
||||||
|
|
||||||
|
int getlaps(struct _h_connection* conn, const char* sessionname, LapDbo* laps, int use_id);
|
||||||
|
|
||||||
|
int gettrack(struct _h_connection* conn, const char* trackname);
|
||||||
|
|
||||||
|
int getdriver(struct _h_connection* conn, const char* driver_name);
|
||||||
|
|
||||||
|
int getcar(struct _h_connection* conn, const char* carname);
|
||||||
|
|
||||||
|
int addtrackconfig(struct _h_connection* conn, int trackconfigid, const char* track, int length);
|
||||||
|
|
||||||
|
int adddriver(struct _h_connection* conn, int driverid, const char* drivername);
|
||||||
|
|
||||||
|
int addevent(struct _h_connection* conn, int track_config);
|
||||||
|
|
||||||
|
int addsession(struct _h_connection* conn, int eventid, int carid, int eventtype, int airtemp, int tracktemp, SimData* simdata);
|
||||||
|
|
||||||
|
int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid, SimData* simdata);
|
||||||
|
|
||||||
|
int addstintlap(struct _h_connection* conn, int stintid, SimData* simdata);
|
||||||
|
|
||||||
|
int addcar(struct _h_connection* conn, int carid, const char* carname);
|
||||||
|
|
||||||
|
int addtelemetry(struct _h_connection* conn, int points, int stintid);
|
||||||
|
|
||||||
|
int closelap(struct _h_connection* conn, int lapid, int sector1, int sector2, int sector3, int cuts, int crashes, int maxspeed, int avgspeed, SimData* simdata);
|
||||||
|
|
||||||
|
int closestint(struct _h_connection* conn, int stintid, int stintlaps, int validstintlaps);
|
||||||
|
|
||||||
|
int closesession(struct _h_connection* conn, int sessionid);
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,297 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <hoel.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#include "telemetry.h"
|
||||||
|
#include "../helper/confighelper.h"
|
||||||
|
#include "../slog/slog.h"
|
||||||
|
|
||||||
|
int telem_result(struct _h_result result, int doublefields, int intfields, int* intarrays, double* doublearrays)
|
||||||
|
{
|
||||||
|
int col, row, i;
|
||||||
|
char buf[64];
|
||||||
|
slogt("rows: %d, col: %d", result.nb_rows, result.nb_columns);
|
||||||
|
//int* intarrays;
|
||||||
|
int points = 0;
|
||||||
|
//int doublefields = 3;
|
||||||
|
//int intfields = 3;
|
||||||
|
//int* intarrays;
|
||||||
|
//int* doublearrays;
|
||||||
|
//int* intarrays = malloc((sizeof(int)*1736)*3);
|
||||||
|
//double* doublearrays = malloc((sizeof(double)*1736)*3);
|
||||||
|
int intarrayoffset = 0;
|
||||||
|
int doublearrayoffset = 0;
|
||||||
|
|
||||||
|
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:
|
||||||
|
int cc = ((struct _h_type_int*)result.data[row][col].t_data)->value;
|
||||||
|
if (col == 1)
|
||||||
|
{
|
||||||
|
points = cc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HOEL_COL_TYPE_DOUBLE:
|
||||||
|
//intarrays = malloc((sizeof(int)*1736)*3);
|
||||||
|
break;
|
||||||
|
case HOEL_COL_TYPE_TEXT:
|
||||||
|
slogi("| %s ", ((struct _h_type_text*)result.data[row][col].t_data)->value);
|
||||||
|
break;
|
||||||
|
case HOEL_COL_TYPE_BLOB:
|
||||||
|
int offset2 = 0;
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
i = 2;
|
||||||
|
if (col < 5)
|
||||||
|
{
|
||||||
|
while (i<((struct _h_type_blob*)result.data[row][col].t_data)->length)
|
||||||
|
{
|
||||||
|
char sss[10];
|
||||||
|
sss[0] = '0';
|
||||||
|
sss[1] = 'x';
|
||||||
|
sss[2] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+2);
|
||||||
|
sss[3] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+3);
|
||||||
|
sss[4] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+4);
|
||||||
|
sss[5] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+5);
|
||||||
|
sss[6] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+6);
|
||||||
|
sss[7] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+7);
|
||||||
|
sss[8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+8);
|
||||||
|
sss[9] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+9);
|
||||||
|
long val;
|
||||||
|
int number = (int)strtol(sss, NULL, 16);
|
||||||
|
int swapped = __bswap_32(number);
|
||||||
|
|
||||||
|
intarrays[j+intarrayoffset] = __bswap_32(number);
|
||||||
|
offset2 = offset2 + 8;
|
||||||
|
i+=8;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
intarrayoffset += points;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (i<((struct _h_type_blob*)result.data[row][col].t_data)->length)
|
||||||
|
{
|
||||||
|
char sss[18];
|
||||||
|
sss[0] = '0';
|
||||||
|
sss[1] = 'x';
|
||||||
|
sss[2] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+2);
|
||||||
|
sss[3] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+3);
|
||||||
|
sss[4] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+4);
|
||||||
|
sss[5] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+5);
|
||||||
|
sss[6] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+6);
|
||||||
|
sss[7] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+7);
|
||||||
|
sss[8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+8);
|
||||||
|
sss[9] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+9);
|
||||||
|
sss[2+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+2+8);
|
||||||
|
sss[3+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+3+8);
|
||||||
|
sss[4+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+4+8);
|
||||||
|
sss[5+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+5+8);
|
||||||
|
sss[6+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+6+8);
|
||||||
|
sss[7+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+7+8);
|
||||||
|
sss[8+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+8+8);
|
||||||
|
sss[9+8] = *((char*)((struct _h_type_blob*)result.data[row][col].t_data)->value+offset2+9+8);
|
||||||
|
long val;
|
||||||
|
int64_t number = (int64_t) strtoll(sss, NULL, 16);
|
||||||
|
int64_t swapped = __bswap_64(number);
|
||||||
|
double d = *((double*)&swapped);
|
||||||
|
doublearrays[j+doublearrayoffset] = (double) d;
|
||||||
|
offset2 = offset2 + 16;
|
||||||
|
i+=16;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
doublearrayoffset += points;
|
||||||
|
|
||||||
|
}
|
||||||
|
//snprintf( "blob value: %.*s", ((struct _h_type_blob *)result.data[row][col].t_data)->length, ((struct _h_type_blob *)result.data[row][col].t_data)->value);
|
||||||
|
//char* b = malloc(sizeof(int)*1736);
|
||||||
|
//for (i=0; i<((struct _h_type_blob *)result.data[row][col].t_data)->length; i++) {
|
||||||
|
// //slogi("%c", *((char*)(((struct _h_type_blob *)result.data[row][col].t_data)->value+i)));
|
||||||
|
// memcpy(&b[i], ((struct _h_type_blob *)result.data[row][col].t_data)->value+1*sizeof(char), sizeof(char));
|
||||||
|
//}
|
||||||
|
// FILE *out = fopen("memory.bin", "wb");
|
||||||
|
// if(out != NULL)
|
||||||
|
// {
|
||||||
|
// size_t to_go = sizeof(int)*1736;
|
||||||
|
// while(to_go > 0)
|
||||||
|
// {
|
||||||
|
// const size_t wrote = fwrite(b, to_go, 1, out);
|
||||||
|
// if(wrote == 0)
|
||||||
|
// break;
|
||||||
|
// to_go -= wrote;
|
||||||
|
// }
|
||||||
|
// fclose(out);
|
||||||
|
// }
|
||||||
|
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:
|
||||||
|
slogi("| [null] ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("|\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dumptelemetrytofile(struct _h_connection* conn, char* datadir, int lap1id, int lap2id)
|
||||||
|
{
|
||||||
|
|
||||||
|
slogt("dumping telemetry to temp file: lap1id: %d lap2id: %d", lap1id, lap2id);
|
||||||
|
|
||||||
|
int points = 0;
|
||||||
|
int intfields = 3;
|
||||||
|
int doublefields = 3;
|
||||||
|
|
||||||
|
struct _h_result result;
|
||||||
|
struct _h_data* data;
|
||||||
|
char* query = malloc(150 * sizeof(char));
|
||||||
|
sprintf(query, "SELECT lap_id, points FROM %s WHERE %s=%i", "telemetry", "lap_id", lap1id);
|
||||||
|
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));
|
||||||
|
points = telem_result(result, 3, 3, NULL, NULL);
|
||||||
|
//get_stint_result(result, stint);
|
||||||
|
h_clean_result(&result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Error executing query\n");
|
||||||
|
}
|
||||||
|
free(query);
|
||||||
|
|
||||||
|
|
||||||
|
int* intarrays1 = malloc((sizeof(int))*points*intfields);
|
||||||
|
double* doublearrays1 = malloc((sizeof(double))*points*doublefields);
|
||||||
|
int* intarrays2 = malloc((sizeof(int))*points*intfields);
|
||||||
|
double* doublearrays2 = malloc((sizeof(double))*points*doublefields);
|
||||||
|
|
||||||
|
struct _h_result result1;
|
||||||
|
struct _h_data* data1;
|
||||||
|
char* query1 = malloc(150 * sizeof(char));
|
||||||
|
sprintf(query1, "SELECT lap_id, points, speed, gear, rpms, brake, accel, steer FROM %s WHERE %s=%i", "telemetry", "lap_id", lap1id);
|
||||||
|
if (h_query_select(conn, query1, &result1) == H_OK)
|
||||||
|
{
|
||||||
|
//laps->rows = malloc(sizeof(LapRowData) * result.nb_rows);
|
||||||
|
//get_row_results(result, laps->fields, laps->rows, sizeof(LapRowData));
|
||||||
|
points = telem_result(result1, intfields, doublefields, intarrays1, doublearrays1);
|
||||||
|
//get_stint_result(result, stint);
|
||||||
|
h_clean_result(&result1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Error executing query\n");
|
||||||
|
}
|
||||||
|
free(query1);
|
||||||
|
|
||||||
|
struct _h_result result2;
|
||||||
|
struct _h_data* data2;
|
||||||
|
char* query2 = malloc(150 * sizeof(char));
|
||||||
|
sprintf(query2, "SELECT lap_id, points, speed, gear, rpms, brake, accel, steer FROM %s WHERE %s=%i", "telemetry", "lap_id", lap2id);
|
||||||
|
if (h_query_select(conn, query2, &result2) == H_OK)
|
||||||
|
{
|
||||||
|
//laps->rows = malloc(sizeof(LapRowData) * result.nb_rows);
|
||||||
|
//get_row_results(result, laps->fields, laps->rows, sizeof(LapRowData));
|
||||||
|
points = telem_result(result2, intfields, doublefields, intarrays2, doublearrays2);
|
||||||
|
//get_stint_result(result, stint);
|
||||||
|
h_clean_result(&result2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Error executing query\n");
|
||||||
|
}
|
||||||
|
free(query2);
|
||||||
|
|
||||||
|
char* filename1 = "data.out";
|
||||||
|
size_t strsize = strlen(datadir) + strlen(filename1) + 1;
|
||||||
|
char* datafile = malloc(strsize);
|
||||||
|
|
||||||
|
snprintf(datafile, strsize, "%s%s", datadir, filename1);
|
||||||
|
slogt("dumping %i points to file %s", points, datafile);
|
||||||
|
FILE* out = fopen(datafile, "w");
|
||||||
|
fprintf(out, "%s %s %s %s %s %s %s %s %s %s %s %s %s\n", "point", "speed1", "rpms1", "gear1", "brake1", "accel1", "steer1", "speed2", "rpms2", "gear2", "brake2", "accel2", "steer2" );
|
||||||
|
for (int i=0; i<points; i++)
|
||||||
|
{
|
||||||
|
fprintf(out, "%i %i %i %i %f %f %f", i+1, intarrays1[i], intarrays1[i+points], intarrays1[i+(points*2)], doublearrays1[i], doublearrays1[i+points], doublearrays1[i+(points*2)]);
|
||||||
|
fprintf(out, "%i %i %i %i %f %f %f\n", i+1, intarrays2[i], intarrays2[i+points], intarrays2[i+(points*2)], doublearrays2[i], doublearrays2[i+points], doublearrays2[i+(points*2)]);
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
|
||||||
|
free(intarrays1);
|
||||||
|
free(intarrays2);
|
||||||
|
free(doublearrays1);
|
||||||
|
free(doublearrays2);
|
||||||
|
free(datafile);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_bytes(void* ptr, int size)
|
||||||
|
{
|
||||||
|
char* pp = malloc((size*2)+1);
|
||||||
|
char output[(size * 2) + 1];
|
||||||
|
char* ppp = &output[0];
|
||||||
|
unsigned char* p = ptr;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<size; i++)
|
||||||
|
{
|
||||||
|
slogt("%02hhX", p[i]);
|
||||||
|
ppp += sprintf(ppp, "%02X", p[i]);
|
||||||
|
//snprintf(pp, (size*2)+1, "%s%02hhX", pp, p[i]);
|
||||||
|
}
|
||||||
|
slogt("\n");
|
||||||
|
slogt("bytes %s", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
int updatetelemetry(struct _h_connection* conn, int telemid, int size, const char* column, void* data)
|
||||||
|
{
|
||||||
|
|
||||||
|
//char *pp = malloc((size*2)+1);
|
||||||
|
char output[(size * 2) + 1];
|
||||||
|
char* ppp = &output[0];
|
||||||
|
unsigned char* p = data;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<size; i++)
|
||||||
|
{
|
||||||
|
ppp += sprintf(ppp, "%02hhX", p[i]);
|
||||||
|
//snprintf(pp, (size*2)+1, "%s%02hhX", pp, p[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return res1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int updatetelemetrydata(struct _h_connection* conn, int tracksamples, int telemid, int lapid,
|
||||||
|
int* speeddata, int* rpmdata, int* geardata,
|
||||||
|
double* steerdata, double* acceldata, double* brakedata)
|
||||||
|
{
|
||||||
|
int b = 0;
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(double), "steer", steerdata);
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(double), "accel", acceldata);
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(double), "brake", brakedata);
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(int), "rpms", rpmdata);
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(int), "gear", geardata);
|
||||||
|
b = updatetelemetry(conn, telemid, tracksamples*sizeof(int), "speed", speeddata);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef _TELEMETRY_H
|
||||||
|
#define _TELEMETRY_H
|
||||||
|
|
||||||
|
int dumptelemetrytofile(struct _h_connection* conn, char* datadir, int lap1id, int lap2id);
|
||||||
|
|
||||||
|
void print_bytes(void* ptr, int size);
|
||||||
|
|
||||||
|
int updatetelemetrydata(struct _h_connection* conn, int tracksamples, int telemid, int lapid,
|
||||||
|
int* speeddata, int* rpmdata, int* geardata,
|
||||||
|
double* steerdata, double* acceldata, double* brakedata);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -5,42 +6,22 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <basedir_fs.h>
|
||||||
|
|
||||||
#include "gameloop/gameloop.h"
|
#include "gameloop/gameloop.h"
|
||||||
|
#include "gameloop/browseloop.h"
|
||||||
#include "helper/parameters.h"
|
#include "helper/parameters.h"
|
||||||
#include "helper/dirhelper.h"
|
#include "helper/dirhelper.h"
|
||||||
#include "helper/confighelper.h"
|
#include "helper/confighelper.h"
|
||||||
#include "slog/slog.h"
|
#include "slog/slog.h"
|
||||||
|
|
||||||
|
#define PROGRAM_NAME "gilles"
|
||||||
int create_dir(char* dir)
|
|
||||||
{
|
|
||||||
struct stat st = {0};
|
|
||||||
if (stat(dir, &st) == -1)
|
|
||||||
{
|
|
||||||
mkdir(dir, 0700);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char* create_user_dir(char* dirtype)
|
|
||||||
{
|
|
||||||
char* home_dir_str = gethome();
|
|
||||||
char* config_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen(dirtype) + strlen("gilles/"));
|
|
||||||
strcpy(config_dir_str, home_dir_str);
|
|
||||||
strcat(config_dir_str, dirtype);
|
|
||||||
strcat(config_dir_str, "gilles/");
|
|
||||||
|
|
||||||
create_dir(config_dir_str);
|
|
||||||
free(config_dir_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
Parameters* p = malloc(sizeof(Parameters));
|
Parameters* p = malloc(sizeof(Parameters));
|
||||||
GillesSettings* gs = malloc(sizeof(GillesSettings));;
|
GillesSettings* gs = malloc(sizeof(GillesSettings));;
|
||||||
|
|
||||||
ConfigError ppe = getParameters(argc, argv, p);
|
ConfigError ppe = getParameters(argc, argv, p);
|
||||||
if (ppe == E_SUCCESS_AND_EXIT)
|
if (ppe == E_SUCCESS_AND_EXIT)
|
||||||
{
|
{
|
||||||
|
|
@ -50,22 +31,15 @@ int main(int argc, char** argv)
|
||||||
p->program_state = 1;
|
p->program_state = 1;
|
||||||
|
|
||||||
char* home_dir_str = gethome();
|
char* home_dir_str = gethome();
|
||||||
create_user_dir("/.config/");
|
|
||||||
create_user_dir("/.cache/");
|
char* cachedir = create_user_dir(home_dir_str, ".cache", PROGRAM_NAME);
|
||||||
char* config_file_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.config/") + strlen("gilles/gilles.config"));
|
|
||||||
char* cache_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.cache/gilles/"));
|
|
||||||
strcpy(config_file_str, home_dir_str);
|
|
||||||
strcat(config_file_str, "/.config/");
|
|
||||||
strcpy(cache_dir_str, home_dir_str);
|
|
||||||
strcat(cache_dir_str, "/.cache/gilles/");
|
|
||||||
strcat(config_file_str, "gilles/gilles.config");
|
|
||||||
|
|
||||||
slog_config_t slgCfg;
|
slog_config_t slgCfg;
|
||||||
slog_config_get(&slgCfg);
|
slog_config_get(&slgCfg);
|
||||||
slgCfg.eColorFormat = SLOG_COLORING_TAG;
|
slgCfg.eColorFormat = SLOG_COLORING_TAG;
|
||||||
slgCfg.eDateControl = SLOG_TIME_ONLY;
|
slgCfg.eDateControl = SLOG_TIME_ONLY;
|
||||||
strcpy(slgCfg.sFileName, "gilles.log");
|
strcpy(slgCfg.sFileName, "gilles.log");
|
||||||
strcpy(slgCfg.sFilePath, cache_dir_str);
|
strcpy(slgCfg.sFilePath, cachedir);
|
||||||
slgCfg.nTraceTid = 0;
|
slgCfg.nTraceTid = 0;
|
||||||
slgCfg.nToScreen = 1;
|
slgCfg.nToScreen = 1;
|
||||||
slgCfg.nUseHeap = 0;
|
slgCfg.nUseHeap = 0;
|
||||||
|
|
@ -82,42 +56,50 @@ int main(int argc, char** argv)
|
||||||
slog_disable(SLOG_DEBUG);
|
slog_disable(SLOG_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_t ui_thread;
|
char* configdir = create_user_dir(home_dir_str, ".config", PROGRAM_NAME);
|
||||||
pthread_t mqtt_thread;
|
char* datadir = create_user_dir(home_dir_str, ".local/share", PROGRAM_NAME);
|
||||||
|
|
||||||
if (pthread_create(&ui_thread, NULL, &looper, p) != 0)
|
xdgHandle xdg;
|
||||||
|
if(!xdgInitHandle(&xdg))
|
||||||
{
|
{
|
||||||
printf("Uh-oh!\n");
|
slogf("Function xdgInitHandle() failed, is $HOME unset?");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (p->mqtt == true)
|
|
||||||
{
|
|
||||||
if (pthread_create(&mqtt_thread, NULL, &b4madmqtt, p) != 0)
|
|
||||||
{
|
|
||||||
printf("Uh-oh!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_join(ui_thread, NULL);
|
char* config_file_str = get_config_file(p->config_path, &xdg);
|
||||||
p->program_state = -1;
|
int err = loadconfig(config_file_str, p);
|
||||||
if (p->mqtt == true)
|
|
||||||
{
|
|
||||||
pthread_join(mqtt_thread, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(config_file_str);
|
free(config_file_str);
|
||||||
free(cache_dir_str);
|
xdgWipeHandle(&xdg);
|
||||||
|
|
||||||
|
if (err == E_NO_ERROR)
|
||||||
|
{
|
||||||
|
if (p->program_action == A_PLAY)
|
||||||
|
{
|
||||||
|
mainloop(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
browseloop(p, datadir);
|
||||||
|
}
|
||||||
|
if (p->err != E_NO_ERROR)
|
||||||
|
{
|
||||||
|
sloge("Error occured during execution.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
configcleanup:
|
configcleanup:
|
||||||
//config_destroy(&cfg);
|
//config_destroy(&cfg);
|
||||||
|
|
||||||
cleanup_final:
|
cleanup_final:
|
||||||
|
freeparams(p);
|
||||||
free(gs);
|
free(gs);
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
|
free(configdir);
|
||||||
|
free(datadir);
|
||||||
|
free(cachedir);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,37 +2,125 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "confighelper.h"
|
#include "confighelper.h"
|
||||||
|
|
||||||
#include "../slog/slog.h"
|
#include "../slog/slog.h"
|
||||||
|
#include "parameters.h"
|
||||||
|
|
||||||
int strtogame(const char* game, GillesSettings* gs)
|
//int strtogame(const char* game, GillesSettings* gs)
|
||||||
|
//{
|
||||||
|
// slogd("Checking for %s in list of supported simulators.", game);
|
||||||
|
// if (strcmp(game, "ac") == 0)
|
||||||
|
// {
|
||||||
|
// slogd("Setting simulator to Assetto Corsa");
|
||||||
|
// gs->sim_name = SIMULATOR_ASSETTO_CORSA;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// if (strcmp(game, "test") == 0)
|
||||||
|
// {
|
||||||
|
// slogd("Setting simulator to Test Data");
|
||||||
|
// gs->sim_name = SIMULATOR_GILLES_TEST;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// slogi("%s does not appear to be a supported simulator.", game);
|
||||||
|
// return GILLES_ERROR_INVALID_SIM;
|
||||||
|
// }
|
||||||
|
// return GILLES_ERROR_NONE;
|
||||||
|
//}
|
||||||
|
|
||||||
|
int loaddbconfig(config_t* cfg, Parameters* p)
|
||||||
{
|
{
|
||||||
slogd("Checking for %s in list of supported simulators.", game);
|
config_setting_t* config_db_array = NULL;
|
||||||
if (strcmp(game, "ac") == 0)
|
config_db_array = config_lookup(cfg, "db");
|
||||||
{
|
|
||||||
slogd("Setting simulator to Assetto Corsa");
|
config_setting_t* config_db = NULL;
|
||||||
gs->sim_name = SIMULATOR_ASSETTO_CORSA;
|
config_db = config_setting_get_elem(config_db_array, 0);
|
||||||
|
|
||||||
|
if (config_db == NULL) {
|
||||||
|
slogi("found no db settings");
|
||||||
|
return E_BAD_CONFIG;
|
||||||
}
|
}
|
||||||
else
|
const char* temp;
|
||||||
if (strcmp(game, "test") == 0)
|
config_setting_lookup_string(config_db, "user", &temp);
|
||||||
{
|
p->db_user = strdup(temp);
|
||||||
slogd("Setting simulator to Test Data");
|
config_setting_lookup_string(config_db, "password", &temp);
|
||||||
gs->sim_name = SIMULATOR_GILLES_TEST;
|
p->db_pass = strdup(temp);
|
||||||
}
|
config_setting_lookup_string(config_db, "server", &temp);
|
||||||
else
|
p->db_serv = strdup(temp);
|
||||||
{
|
config_setting_lookup_string(config_db, "database", &temp);
|
||||||
slogi("%s does not appear to be a supported simulator.", game);
|
p->db_dbnm = strdup(temp);
|
||||||
return GILLES_ERROR_INVALID_SIM;
|
|
||||||
}
|
size_t strsize = strlen(p->db_user) + strlen(p->db_pass) + strlen(p->db_serv) + strlen(p->db_dbnm) + 29 + 1;
|
||||||
return GILLES_ERROR_NONE;
|
p->db_conn = malloc(strsize);
|
||||||
|
|
||||||
|
snprintf(p->db_conn, strsize, "host=%s dbname=%s user=%s password=%s", p->db_serv, p->db_dbnm, p->db_user, p->db_pass);
|
||||||
|
|
||||||
|
return E_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int loadconfig(const char* config_file_str, Parameters* p)
|
||||||
int loadconfig(const char* config_file)
|
|
||||||
{
|
{
|
||||||
|
config_t cfg;
|
||||||
|
config_init(&cfg);
|
||||||
|
if (!config_read_file(&cfg, config_file_str))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slogi("Parsing config file");
|
||||||
|
|
||||||
|
|
||||||
|
if (p->program_action == A_BROWSE)
|
||||||
|
{
|
||||||
|
char* gnuplotbin = "/usr/bin/gnuplot";
|
||||||
|
config_setting_t* config_graph_array = NULL;
|
||||||
|
config_graph_array = config_lookup(&cfg, "graph");
|
||||||
|
|
||||||
|
config_setting_t* config_graph = NULL;
|
||||||
|
config_graph = config_setting_get_elem(config_graph_array, 0);
|
||||||
|
|
||||||
|
if (config_graph == NULL) {
|
||||||
|
slogi("found no graph settings");
|
||||||
|
return E_BAD_CONFIG;
|
||||||
|
}
|
||||||
|
const char* temp;
|
||||||
|
config_setting_lookup_string(config_graph, "gnuplotfile", &temp);
|
||||||
|
p->gnuplot_file = strdup(temp);
|
||||||
|
slogt("set gnuplot config file %s", p->gnuplot_file);
|
||||||
|
|
||||||
|
int found = config_setting_lookup_string(config_graph, "gnuplotbin", &temp);
|
||||||
|
if (found > 0)
|
||||||
|
{
|
||||||
|
p->gnuplot_bin = strdup(temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->gnuplot_bin = strdup(gnuplotbin);
|
||||||
|
}
|
||||||
|
p->gnuplotfound = 0;
|
||||||
|
if (access(p->gnuplot_bin, F_OK) == 0)
|
||||||
|
{
|
||||||
|
p->gnuplotfound = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->mysql == true || p->program_action == A_BROWSE)
|
||||||
|
{
|
||||||
|
int err = loaddbconfig(&cfg, p);
|
||||||
|
if (err != E_NO_ERROR)
|
||||||
|
{
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config_destroy(&cfg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,6 @@
|
||||||
|
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
SIMULATOR_GILLES_TEST = 0,
|
|
||||||
SIMULATOR_ASSETTO_CORSA = 1
|
|
||||||
}
|
|
||||||
Simulator;
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SIMULATOR_UPDATE_DEFAULT = 0,
|
SIMULATOR_UPDATE_DEFAULT = 0,
|
||||||
|
|
@ -25,15 +18,6 @@ typedef enum
|
||||||
}
|
}
|
||||||
SimulatorUpdate;
|
SimulatorUpdate;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
GILLES_ERROR_NONE = 0,
|
|
||||||
GILLES_ERROR_UNKNOWN = 1,
|
|
||||||
GILLES_ERROR_INVALID_SIM = 2,
|
|
||||||
GILLES_ERROR_NODATA = 4,
|
|
||||||
}
|
|
||||||
GillesError;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ProgramAction program_action;
|
ProgramAction program_action;
|
||||||
|
|
@ -41,6 +25,8 @@ typedef struct
|
||||||
}
|
}
|
||||||
GillesSettings;
|
GillesSettings;
|
||||||
|
|
||||||
|
int loadconfig(const char* config_file_str, Parameters* p);
|
||||||
|
|
||||||
int strtogame(const char* game, GillesSettings* gs);
|
int strtogame(const char* game, GillesSettings* gs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,65 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "../slog/slog.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CONFIG_FILE "gilles/gilles.config"
|
||||||
|
|
||||||
|
void create_dir(char* dir)
|
||||||
|
{
|
||||||
|
struct stat st = {0};
|
||||||
|
if (stat(dir, &st) == -1)
|
||||||
|
{
|
||||||
|
mkdir(dir, 0700);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programname)
|
||||||
|
{
|
||||||
|
// +3 for slashes
|
||||||
|
size_t ss = (4 + strlen(home_dir_str) + strlen(dirtype) + strlen(programname));
|
||||||
|
char* config_dir_str = malloc(ss);
|
||||||
|
|
||||||
|
snprintf (config_dir_str, ss, "%s/%s/%s/", home_dir_str, dirtype, programname);
|
||||||
|
|
||||||
|
slogt("creating dir for %s if necessary", config_dir_str);
|
||||||
|
create_dir(config_dir_str);
|
||||||
|
return config_dir_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* get_config_file(const char* confpath, xdgHandle* xdg)
|
||||||
|
{
|
||||||
|
if ((confpath != NULL) && (strcmp(confpath, "") != 0))
|
||||||
|
{
|
||||||
|
slogw("Using custom config path %s", confpath);
|
||||||
|
return strdup(confpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* relpath = CONFIG_FILE;
|
||||||
|
char* confpath1 = xdgConfigFind(relpath, xdg);
|
||||||
|
slogi("config path is %s", confpath1);
|
||||||
|
return confpath1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* get_dir_with_default(const char* dirpath, char* defaultpath)
|
||||||
|
{
|
||||||
|
if ((dirpath != NULL) && (strcmp(dirpath, "") != 0))
|
||||||
|
{
|
||||||
|
slogw("Using custom config path %s", dirpath);
|
||||||
|
return strdup(dirpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultpath;
|
||||||
|
}
|
||||||
|
|
||||||
char* gethome()
|
char* gethome()
|
||||||
{
|
{
|
||||||
char* homedir = getenv("HOME");
|
char* homedir = getenv("HOME");
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,16 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <basedir_fs.h>
|
||||||
|
|
||||||
|
void create_dir(char* dir);
|
||||||
|
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programpath);
|
||||||
char* gethome();
|
char* gethome();
|
||||||
char* str2md5(const char* str, int length);
|
char* str2md5(const char* str, int length);
|
||||||
bool does_directory_exist(char* path, char* dirname);
|
bool does_directory_exist(char* path, char* dirname);
|
||||||
void restrict_folders_to_cache(char* path, int cachesize);
|
void restrict_folders_to_cache(char* path, int cachesize);
|
||||||
void delete_dir(char* path);
|
void delete_dir(char* path);
|
||||||
|
char* get_config_file(const char* confpath, xdgHandle* xdg);
|
||||||
|
char* get_dir_with_default(const char* dirpath, char* defaultpath);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,34 @@
|
||||||
#include <argtable2.h>
|
#include <argtable2.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
|
int freeparams(Parameters* p)
|
||||||
|
{
|
||||||
|
if(p->sim_string != NULL)
|
||||||
|
{
|
||||||
|
free(p->sim_string);
|
||||||
|
}
|
||||||
|
if (p->mysql == true || p->program_action == A_BROWSE)
|
||||||
|
{
|
||||||
|
if(p->db_user != NULL)
|
||||||
|
{
|
||||||
|
free(p->db_user);
|
||||||
|
}
|
||||||
|
if(p->db_conn != NULL)
|
||||||
|
{
|
||||||
|
free(p->db_conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->program_action == A_BROWSE)
|
||||||
|
{
|
||||||
|
free(p->gnuplot_bin);
|
||||||
|
}
|
||||||
|
if (p->config_path != NULL)
|
||||||
|
{
|
||||||
|
free(p->config_path);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ConfigError getParameters(int argc, char** argv, Parameters* p)
|
ConfigError getParameters(int argc, char** argv, Parameters* p)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -15,64 +43,107 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
|
||||||
|
|
||||||
// set return structure defaults
|
// set return structure defaults
|
||||||
p->program_action = 0;
|
p->program_action = 0;
|
||||||
|
p->cli = false;
|
||||||
p->mqtt = false;
|
p->mqtt = false;
|
||||||
|
p->mysql = false;
|
||||||
|
p->simon = false;
|
||||||
p->verbosity_count = 0;
|
p->verbosity_count = 0;
|
||||||
|
|
||||||
// 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_cpath = arg_strn("f", "configpath", "<path of config>", 0, 1, 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_mqtt = arg_lit0("S", NULL, "send data to local mqtt server");
|
struct arg_lit* arg_cli = arg_lit0("c", "textui", "text only ui");
|
||||||
struct arg_lit* help = arg_litn(NULL,"help", 0, 1, "print this help and exit");
|
struct arg_lit* arg_mqtt = arg_lit0("Q", "mqtt", "send data to local mqtt server with connection settings speciifed in config");
|
||||||
struct arg_lit* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit");
|
struct arg_lit* arg_mysql = arg_lit0("M", "mysql", "send data to local mysql server with connection settings specified in config");
|
||||||
struct arg_end* end = arg_end(20);
|
struct arg_lit* help0 = arg_litn(NULL,"help", 0, 1, "print this help and exit");
|
||||||
void* argtable[] = {cmd1,arg_sim,arg_verbosity,arg_mqtt,help,vers,end};
|
struct arg_lit* vers0 = arg_litn(NULL,"version", 0, 1, "print version information and exit");
|
||||||
int nerrors;
|
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);
|
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 = 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)
|
||||||
|
{
|
||||||
|
p->cli = true;
|
||||||
|
}
|
||||||
if (arg_mqtt->count > 0)
|
if (arg_mqtt->count > 0)
|
||||||
{
|
{
|
||||||
p->mqtt = true;
|
p->mqtt = true;
|
||||||
}
|
}
|
||||||
|
if (arg_mysql->count > 0)
|
||||||
|
{
|
||||||
|
p->mysql = true;
|
||||||
|
}
|
||||||
|
if (arg_cpath->sval[0] != NULL)
|
||||||
|
{
|
||||||
|
p->config_path = strdup(arg_cpath->sval[0]);
|
||||||
|
}
|
||||||
exitcode = E_SUCCESS_AND_DO;
|
exitcode = E_SUCCESS_AND_DO;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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);
|
||||||
printf("\nReport bugs on the github github.com/spacefreak18/csimtelem.\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;
|
exitcode = E_SUCCESS_AND_EXIT;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vers->count > 0)
|
if (vers0->count > 0)
|
||||||
{
|
{
|
||||||
printf("%s Simulator Hardware Manager\n",progname);
|
printf("%s Simulator Monitor\n",progname);
|
||||||
printf("October 2022, Paul Dino Jones\n");
|
printf("October 2022, Paul Dino Jones\n");
|
||||||
exitcode = E_SUCCESS_AND_EXIT;
|
exitcode = E_SUCCESS_AND_EXIT;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,43 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../simulatorapi/simapi/simapi/simapi.h"
|
||||||
|
#include "../simulatorapi/simapi/simapi/simdata.h"
|
||||||
|
#include "../simulatorapi/simapi/simapi/simmapper.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
char* sim_string;
|
||||||
int program_action;
|
int program_action;
|
||||||
int program_state;
|
int program_state;
|
||||||
const char* sim_string;
|
char* config_path;
|
||||||
bool mqtt;
|
char* gnuplot_file;
|
||||||
int verbosity_count;
|
char* gnuplot_bin;
|
||||||
|
int gnuplotfound;
|
||||||
|
|
||||||
|
bool cli;
|
||||||
|
bool mqtt;
|
||||||
|
bool mysql;
|
||||||
|
bool simon;
|
||||||
|
int verbosity_count;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
char* db_user;
|
||||||
|
char* db_serv;
|
||||||
|
char* db_dbnm;
|
||||||
|
char* db_pass;
|
||||||
|
char* db_conn;
|
||||||
|
|
||||||
|
Simulator sim;
|
||||||
|
SimData* simdata;
|
||||||
|
SimMap* simmap;
|
||||||
}
|
}
|
||||||
Parameters;
|
Parameters;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
A_PLAY = 0,
|
A_PLAY = 0,
|
||||||
|
A_BROWSE = 1,
|
||||||
}
|
}
|
||||||
ProgramAction;
|
ProgramAction;
|
||||||
|
|
||||||
|
|
@ -27,7 +51,17 @@ typedef enum
|
||||||
}
|
}
|
||||||
ConfigError;
|
ConfigError;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
E_NO_ERROR = 0,
|
||||||
|
E_BAD_CONFIG = 1,
|
||||||
|
E_FAILED_DB_CONN = 2,
|
||||||
|
E_DB_QUERY_FAIL = 3,
|
||||||
|
}
|
||||||
|
GillesError;
|
||||||
|
|
||||||
ConfigError getParameters(int argc, char** argv, Parameters* p);
|
ConfigError getParameters(int argc, char** argv, Parameters* p);
|
||||||
|
int freeparams(Parameters* p);
|
||||||
|
|
||||||
struct _errordesc
|
struct _errordesc
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 618920440e0eb60f6209bdb4cb734b366c32780c
|
Subproject commit 51e29ec8e32cb70c455b381a84f7614f6594516f
|
||||||
Loading…
Reference in New Issue