New Event History Setup and Logging to a Log File, part 1; #186

This commit is contained in:
lwvmobile
2025-04-22 23:50:07 -04:00
parent 51727b815d
commit cb89fb69c1
15 changed files with 639 additions and 265 deletions

View File

@@ -88,6 +88,34 @@
extern volatile uint8_t exitflag; //fix for issue #136 extern volatile uint8_t exitflag; //fix for issue #136
//event history (each item)
typedef struct {
uint8_t write; //if this event needs to be written to a log file
int8_t systype; //indentifier of which decoded system type this is from (P25, DMR, etc)
int8_t subtype; //subtype of systpe (VLC, TLC, PDU data, System Event, etc)
uint8_t gi; //group or individual
uint8_t enc; //clear or encrypted
uint8_t enc_alg; //alg if encrypted
uint16_t enc_key; //enc key id value, if encrypted (not key value or key variable)
uint64_t mi; //mi, or iv base value from OTA if provided
uint16_t svc; //other relevant svc opts if applicable
uint32_t source_id;//source radio id or other source value
uint32_t target_id;//group or individual target, or destination value
uint32_t channel; //if this occurs on a trunking channel, which channel
time_t event_time; //time event occurred
uint8_t pdu[128*24]; //relevant link control, or full PDU if data call (in bytes)
char alias[2000]; //if this event has a source radio talker alias or similar
char gps_s[2000]; //gps, if returned, expressed as a string
char text_message[2000]; //if this event is a decoded text message, then it goes here
char event_string[2000]; //user legible and printable string for the event that happened
} Event_History;
//event history for number of each items above
typedef struct {
Event_History Event_History_Items[255];
} Event_History_I;
//new audio filter stuff from: https://github.com/NedSimao/FilteringLibrary //new audio filter stuff from: https://github.com/NedSimao/FilteringLibrary
typedef struct { typedef struct {
float coef[2]; float coef[2];
@@ -280,6 +308,7 @@ typedef struct
char wav_out_file_raw[1024]; char wav_out_file_raw[1024];
char symbol_out_file[1024]; char symbol_out_file[1024];
char lrrp_out_file[1024]; char lrrp_out_file[1024];
char event_out_file[1024];
char szNumbers[1024]; //**tera 10/32/64 char str char szNumbers[1024]; //**tera 10/32/64 char str
short int mbe_out; //flag for mbe out, don't attempt fclose more than once short int mbe_out; //flag for mbe out, don't attempt fclose more than once
short int mbe_outR; //flag for mbe out, don't attempt fclose more than once short int mbe_outR; //flag for mbe out, don't attempt fclose more than once
@@ -546,6 +575,8 @@ typedef struct
int lasttgR; int lasttgR;
int lastsrc; int lastsrc;
int lastsrcR; int lastsrcR;
uint8_t gi[2]; //group, or private call, per slot
uint8_t eh_index;
int nac; int nac;
int errs; int errs;
int errs2; int errs2;
@@ -688,8 +719,8 @@ typedef struct
uint8_t dmr_alias_format[2]; //per slot uint8_t dmr_alias_format[2]; //per slot
uint8_t dmr_alias_len[2]; //per slot uint8_t dmr_alias_len[2]; //per slot
char dmr_alias_block_segment[2][4][7][16]; //2 slots, by 4 blocks, by up to 7 alias bytes that are up to 16-bit chars char dmr_alias_block_segment[2][4][7][16]; //2 slots, by 4 blocks, by up to 7 alias bytes that are up to 16-bit chars
char dmr_embedded_gps[2][200]; //2 slots by 99 char string for string embedded gps char dmr_embedded_gps[2][600]; //2 slots by 99 char string for string embedded gps
char dmr_lrrp_gps[2][200]; //2 slots by 99 char string for string lrrp gps char dmr_lrrp_gps[2][600]; //2 slots by 99 char string for string lrrp gps
char dmr_site_parms[200]; //string for site/net info depending on type of DMR system (TIII or Con+) char dmr_site_parms[200]; //string for site/net info depending on type of DMR system (TIII or Con+)
char call_string[2][200]; //string for call information char call_string[2][200]; //string for call information
char active_channel[31][200]; //string for storing and displaying active trunking channels char active_channel[31][200]; //string for storing and displaying active trunking channels
@@ -699,6 +730,9 @@ typedef struct
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame; dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
//event history itemized per slot
Event_History_I event_history_s[2];
//new audio filter structs //new audio filter structs
LPFilter RCFilter; LPFilter RCFilter;
HPFilter HRCFilter; HPFilter HRCFilter;
@@ -1354,6 +1388,14 @@ char * getDateH();
char * getDateS(); char * getDateS();
char * getDateN(time_t t); char * getDateN(time_t t);
//event history functions
void init_event_history (Event_History_I * event_struct, uint8_t start, uint8_t stop);
void push_event_history (Event_History_I * event_struct);
void write_event_to_log_file (dsd_opts * opts, dsd_state * state, char * event_string);
void watchdog_event_history (dsd_opts * opts, dsd_state * state, uint8_t slot);
void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot);
void watchdog_event_datacall (dsd_opts * opts, dsd_state * state, uint32_t src, uint32_t dst, char * data_string, uint8_t slot);
//dmr alg stuff //dmr alg stuff
void dmr_alg_reset (dsd_opts * opts, dsd_state * state); void dmr_alg_reset (dsd_opts * opts, dsd_state * state);
void dmr_alg_refresh (dsd_opts * opts, dsd_state * state); void dmr_alg_refresh (dsd_opts * opts, dsd_state * state);

View File

@@ -1050,8 +1050,12 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
if (enc_check == 1 && decrypted_pdu == 0) //check for encryption and if it was decrypted first or not if (enc_check == 1 && decrypted_pdu == 0) //check for encryption and if it was decrypted first or not
{ {
fprintf (stderr, "%s", KRED); fprintf (stderr, "%s", KRED);
fprintf (stderr, "\n Slot %d - Encrypted Data Packet;", slot+1); fprintf (stderr, "\n Slot %d - Encrypted PDU;", slot+1);
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
char enc_str[200]; memset (enc_str, 200, sizeof(enc_str));
sprintf (enc_str, "DATA TGT: %d; SRC: %d; Encrypted PDU;", state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot]);
watchdog_event_datacall (opts, state, state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot], enc_str, slot);
} }
else if (CRCCorrect || opts->aggressive_framesync == 0) else if (CRCCorrect || opts->aggressive_framesync == 0)
{ {
@@ -1108,6 +1112,19 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
else if (mnis_type == 0x33) //check any potential texts in this message else if (mnis_type == 0x33) //check any potential texts in this message
utf8_to_text(state, 0, 15, state->dmr_pdu_sf[slot]+7); //seen some ARS radio IDs in ASCII/ISO7/UTF8 format here utf8_to_text(state, 0, 15, state->dmr_pdu_sf[slot]+7); //seen some ARS radio IDs in ASCII/ISO7/UTF8 format here
if (mnis_type != 0x11)
{
char mnis_str[200]; memset (mnis_str, 200, sizeof(mnis_str));
sprintf (mnis_str, "MNIS TGT: %d; SRC: %d;", state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot]);
watchdog_event_datacall (opts, state, state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot], mnis_str, slot);
}
}
else
{
char unk_str[200]; memset (unk_str, 200, sizeof(unk_str));
sprintf (unk_str, "DATA TGT: %d; SRC: %d; Unknown PDU Format;", state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot]);
watchdog_event_datacall (opts, state, state->dmr_lrrp_source[slot], state->dmr_lrrp_target[slot], unk_str, slot);
} }
} }

View File

@@ -584,6 +584,14 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
} }
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//slot 2 for TDMA systems
watchdog_event_history(opts, state, 1);
watchdog_event_current(opts, state, 1);
// //
if (timestr != NULL) if (timestr != NULL)
{ {

View File

@@ -402,8 +402,8 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
{ {
state->dmr_fid = 0; state->dmr_fid = 0;
state->dmr_so = 0; state->dmr_so = 0;
// state->lasttg = 0; state->lasttg = 0;
// state->lastsrc = 0; state->lastsrc = 0;
state->payload_algid = 0; state->payload_algid = 0;
state->payload_mi = 0; state->payload_mi = 0;
state->payload_keyid = 0; state->payload_keyid = 0;
@@ -415,8 +415,8 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
{ {
state->dmr_fidR = 0; state->dmr_fidR = 0;
state->dmr_soR = 0; state->dmr_soR = 0;
// state->lasttgR = 0; state->lasttgR = 0;
// state->lastsrcR = 0; state->lastsrcR = 0;
state->payload_algidR = 0; state->payload_algidR = 0;
state->payload_miR = 0; state->payload_miR = 0;
state->payload_keyidR = 0; state->payload_keyidR = 0;

View File

@@ -310,6 +310,10 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
} }
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
} // end loop } // end loop
END: END:

View File

@@ -22,6 +22,7 @@ uint16_t convert_hex_to_dec(uint16_t input)
void utf16_to_text (dsd_state * state, uint8_t wr, uint16_t len, uint8_t * input) void utf16_to_text (dsd_state * state, uint8_t wr, uint16_t len, uint8_t * input)
{ {
uint8_t slot = state->currentslot; uint8_t slot = state->currentslot;
sprintf (state->event_history_s[slot].Event_History_Items[0].text_message, "%s", "Full Text: "); //full text string
// fprintf (stderr, "\n UTF16 Text: "); // fprintf (stderr, "\n UTF16 Text: ");
uint16_t ch16 = 0; uint16_t ch16 = 0;
for (uint16_t i = 0; i < len; i += 2) for (uint16_t i = 0; i < len; i += 2)
@@ -43,9 +44,14 @@ void utf16_to_text (dsd_state * state, uint8_t wr, uint16_t len, uint8_t * input
//for now, just rip the first 40 or so chars lower byte value //for now, just rip the first 40 or so chars lower byte value
//in the ASCII Range (should be alright for a quick visual) //in the ASCII Range (should be alright for a quick visual)
char c[2]; c[0] = (char)input[i+1]; c[2] = 0; char c[2]; c[0] = (char)input[i+1]; c[2] = 0;
if (wr == 1&& i < 76 && input[i+1] < 0x7F && input[i+1] >= 0x20) if (wr == 1 && i < 76 && input[i+1] < 0x7F && input[i+1] >= 0x20)
strcat (state->dmr_lrrp_gps[slot], c); strcat (state->dmr_lrrp_gps[slot], c);
//this is the long version, complete message for logging purposes
if (wr == 1 && input[i+1] < 0x7F && input[i+1] >= 0x20)
// if (wr == 1)
strcat (state->event_history_s[slot].Event_History_Items[0].text_message, c);
} }
//add elipses to indicate this is possibly truncated //add elipses to indicate this is possibly truncated
@@ -104,6 +110,11 @@ void dmr_sd_pdu (dsd_opts * opts, dsd_state * state, uint16_t len, uint8_t * DMR
// utf16_to_text(state, 0, len, DMR_PDU); //generic catch-all to see if anything relevant is there // utf16_to_text(state, 0, len, DMR_PDU); //generic catch-all to see if anything relevant is there
} }
//TODO: This
// char comp_string[500]; memset (comp_string, 0, sizeof(comp_string));
// sprintf (comp_string, "Src Port Idx: %d (%s); Dst Port Idx: %d (%s); ", spid, portstring[0], dpid, portstring[1]);
// watchdog_event_datacall (opts, state, said, daid, comp_string, slot);
} }
//reading ETSI, seems like these aren't compressed, just that they are preset indexed values on the radio //reading ETSI, seems like these aren't compressed, just that they are preset indexed values on the radio
@@ -235,6 +246,14 @@ void dmr_udp_comp_pdu (dsd_opts * opts, dsd_state * state, uint16_t len, uint8_t
} }
else fprintf (stderr, "Unknown Decode Format;"); else fprintf (stderr, "Unknown Decode Format;");
uint8_t slot = 0;
if (state->currentslot == 1)
slot = 1;
char comp_string[500]; memset (comp_string, 0, sizeof(comp_string));
sprintf (comp_string, "Src Port Idx: %d (%s); Dst Port Idx: %d (%s); ", spid, portstring[0], dpid, portstring[1]);
watchdog_event_datacall (opts, state, said, daid, comp_string, slot);
} }
//IP PDU header decode and port forward to appropriate decoder //IP PDU header decode and port forward to appropriate decoder
@@ -459,7 +478,7 @@ void decode_ip_pdu (dsd_opts * opts, dsd_state * state, uint16_t len, uint8_t *
} }
else else
{ {
sprintf (state->dmr_lrrp_gps[slot], " IP Call SRC: %d; Port; %d; DST: %d; Port: %d;", src24, port1, dst24, port2); sprintf (state->dmr_lrrp_gps[slot], "IP SRC: %d.%d.%d.%d:%d; DST: %d.%d.%d.%d:%d;", input[12], input[13], input[14], input[15], port1, input[16], input[17], input[18], input[19], port2);
fprintf (stderr, "Unknown UDP Port;"); fprintf (stderr, "Unknown UDP Port;");
// if (len > 28) //default catch all (debug only) // if (len > 28) //default catch all (debug only)
// utf8_to_text(state, 0, len-28, input+28); // utf8_to_text(state, 0, len-28, input+28);
@@ -470,13 +489,15 @@ void decode_ip_pdu (dsd_opts * opts, dsd_state * state, uint16_t len, uint8_t *
else else
{ {
sprintf (state->dmr_lrrp_gps[slot], " IP Call SRC: %d; DST: %d; Protocol: %d;", src24, dst24, prot); sprintf (state->dmr_lrrp_gps[slot], "IP SRC: %d; DST: %d; Protocol: %d;", input[12], input[13], input[14], input[15], input[16], input[17], input[18], input[19], prot);
fprintf(stderr, "Unknown IP Protocol: %02X;", prot); fprintf(stderr, "Unknown IP Protocol: %02X;", prot);
// if (len > 28) //default catch all (debug only) // if (len > 28) //default catch all (debug only)
// utf8_to_text(state, 0, len-28, input+28); // utf8_to_text(state, 0, len-28, input+28);
// else utf8_to_text(state, 0, len, input+28); // else utf8_to_text(state, 0, len, input+28);
} }
watchdog_event_datacall (opts, state, src24, dst24, state->dmr_lrrp_gps[slot], slot);
} }
//The contents of this function are mostly trial and error //The contents of this function are mostly trial and error
@@ -745,6 +766,7 @@ void dmr_lrrp (dsd_opts * opts, dsd_state * state, uint16_t len, uint32_t source
sprintf (velstr, "%s", ""); sprintf (velstr, "%s", "");
sprintf (degstr, "%s", ""); sprintf (degstr, "%s", "");
if (lat) sprintf (lrrpstr, "LRRP SRC: %0d; (%lf, %lf)", source, lat_fin, lon_fin); if (lat) sprintf (lrrpstr, "LRRP SRC: %0d; (%lf, %lf)", source, lat_fin, lon_fin);
else sprintf (lrrpstr, "LRRP SRC: %0d; Unknown Format; ", source);
if (vel_set) sprintf (velstr, " %.4lf km/h", velocity * 3.6); if (vel_set) sprintf (velstr, " %.4lf km/h", velocity * 3.6);
if (deg_set) sprintf (degstr, " %d%s ", degrees, deg_glyph); if (deg_set) sprintf (degstr, " %d%s ", degrees, deg_glyph);
sprintf (state->dmr_lrrp_gps[slot], "%s%s%s", lrrpstr, velstr, degstr); sprintf (state->dmr_lrrp_gps[slot], "%s%s%s", lrrpstr, velstr, degstr);

View File

@@ -230,6 +230,14 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
} }
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//slot 2 for TDMA systems
watchdog_event_history(opts, state, 1);
watchdog_event_current(opts, state, 1);
if ((opts->symboltiming == 1) && (state->carrier == 1)) if ((opts->symboltiming == 1) && (state->carrier == 1))
{ {
//fprintf (stderr,"\nSymbol Timing:\n"); //fprintf (stderr,"\nSymbol Timing:\n");

View File

@@ -265,6 +265,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->lastsrc = 0; state->lastsrc = 0;
state->lasttgR = 0; state->lasttgR = 0;
state->lastsrcR = 0; state->lastsrcR = 0;
state->gi[0] = 0;
state->gi[1] = 0;
//zero out vc frequencies? //zero out vc frequencies?
state->p25_vc_freq[0] = 0; state->p25_vc_freq[0] = 0;
@@ -301,6 +303,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
state->lastsrc = 0; state->lastsrc = 0;
state->lasttgR = 0; state->lasttgR = 0;
state->lastsrcR = 0; state->lastsrcR = 0;
state->gi[0] = 0;
state->gi[1] = 0;
} }
@@ -624,6 +628,7 @@ initOpts (dsd_opts * opts)
opts->wav_out_file_raw[0] = 0; opts->wav_out_file_raw[0] = 0;
opts->symbol_out_file[0] = 0; opts->symbol_out_file[0] = 0;
opts->lrrp_out_file[0] = 0; opts->lrrp_out_file[0] = 0;
opts->event_out_file[0] = 0;
//csv import filenames //csv import filenames
opts->group_in_file[0] = 0; opts->group_in_file[0] = 0;
opts->lcn_in_file[0] = 0; opts->lcn_in_file[0] = 0;
@@ -942,6 +947,9 @@ initState (dsd_state * state)
state->lastsrc = 0; state->lastsrc = 0;
state->lasttgR = 0; state->lasttgR = 0;
state->lastsrcR = 0; state->lastsrcR = 0;
state->gi[0] = 0;
state->gi[1] = 0;
state->eh_index = 0;
state->nac = 0; state->nac = 0;
state->errs = 0; state->errs = 0;
state->errs2 = 0; state->errs2 = 0;
@@ -1313,6 +1321,10 @@ initState (dsd_state * state)
state->dmr_color_code = 16; state->dmr_color_code = 16;
//initialize event history items (0 to 255)
for (uint8_t i = 0; i < 2; i++)
init_event_history(&state->event_history_s[i], 0, 255);
} //init_state } //init_state
void void
@@ -1779,7 +1791,7 @@ main (int argc, char **argv)
exitflag = 0; exitflag = 0;
while ((c = getopt (argc, argv, "yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF01:2:345:6:7:89Ek:I:JO")) != -1) while ((c = getopt (argc, argv, "~:yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF01:2:345:6:7:89Ek:I:JO")) != -1)
{ {
switch (c) switch (c)
@@ -2142,6 +2154,12 @@ main (int argc, char **argv)
fprintf (stderr,"Writing + Appending LRRP data to file %s\n", opts.lrrp_out_file); fprintf (stderr,"Writing + Appending LRRP data to file %s\n", opts.lrrp_out_file);
break; break;
case '~': //Event output to file
strncpy(opts.event_out_file, optarg, 1023);
opts.event_out_file[1023] = '\0';
fprintf (stderr,"Writing + Appending Event History to file %s\n", opts.lrrp_out_file);
break;
case '7': //make a custom wav file directory in the current working directory -- use this before -P case '7': //make a custom wav file directory in the current working directory -- use this before -P
strncpy(opts.wav_out_dir, optarg, 511); strncpy(opts.wav_out_dir, optarg, 511);
opts.wav_out_dir[511] = '\0'; opts.wav_out_dir[511] = '\0';

View File

@@ -31,6 +31,8 @@ struct stat st_wav = {0};
static char alias_ch[10][50]; static char alias_ch[10][50];
int reset = 0; int reset = 0;
uint8_t eh_slot = 0; //testing only, have a toggle slot for history
uint8_t eh_off = 0; //testing only, index offset for scrolling history
int tg; int tg;
int tgR; int tgR;
@@ -59,24 +61,24 @@ char * FM_bannerN[9] = {
}; };
char * SyncTypes[44] = { char * SyncTypes[44] = {
"P25P1", "P25p1",
"P25P1", "P25p1",
"X2TDMA DATA", "X2TDMA DATA",
"X2TDMA DATA", "X2TDMA DATA",
"X2TDMA VOICE", "X2TDMA VOICE",
"X2TDMA VOICE", "X2TDMA VOICE",
"DSTAR", //voice "DSTAR", //voice
"DSTAR", //voice "DSTAR", //voice
"NXDN VOICE", "M17",
"NXDN VOICE", "M17",
"DMR", //10 "DMR", //10
"DMR", "DMR",
"DMR", "DMR",
"DMR", "DMR",
"EDACS/PV", "EDACS/PV",
"EDACS/PV", "EDACS/PV",
"NXDN VOICE", //DATA "M17 STR", //M17 Voice Stream
"NXDN VOICE", //DATA "M17 STR", //M17 Voice Stream
"DSTAR", //header "DSTAR", //header
"DSTAR", //header "DSTAR", //header
"dPMR", //20 "dPMR", //20
@@ -94,12 +96,12 @@ char * SyncTypes[44] = {
"DMR", "DMR",
"DMR", "DMR",
"DMR", "DMR",
"P25P2", "P25p2",
"P25P2", "P25p2",
"EDACS/PV", //37 "EDACS/PV", //37
"EDACS/PV", //38 "EDACS/PV", //38
"", "ANALOG", //39 Generic Sync Types
"" "DIGITAL" //40 Generic Sync Types
}; };
char * DMRBusrtTypes[32] = { char * DMRBusrtTypes[32] = {
@@ -3823,7 +3825,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
else else
{ {
printw ("| Monitoring VC - LCN [%02d]", state->edacs_tuned_lcn); printw ("| Monitoring VC - LCN [%02d]\n", state->edacs_tuned_lcn);
//since we are tuned, keep updating the time so it doesn't disappear during call //since we are tuned, keep updating the time so it doesn't disappear during call
call_matrix[state->edacs_tuned_lcn][5] = time(NULL); call_matrix[state->edacs_tuned_lcn][5] = time(NULL);
} }
@@ -4003,233 +4005,23 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_history == 1) if (opts->ncurses_history == 1)
{ {
attron(COLOR_PAIR(4)); //cyan for history attron(COLOR_PAIR(4)); //cyan for history
printw ("--Call History----------------------------------------------------------------\n"); printw ("--Latest Event History ([|])---Slot %d (\\)-------------------------------------\n", eh_slot+1);
for (short int j = 0; j < 10; j++) for (uint8_t i = (state->eh_index+1); i < (state->eh_index+11); i++)
{ {
//only print if a valid time was assigned to the matrix, and not EDACS/PV, and source is not zero char text_string[2000];
if ( ((time(NULL) - call_matrix[9-j][5]) < 999999) && call_matrix[9-j][0] != 14 && call_matrix[9-j][0] != 15 && call_matrix[9-j][0] != 37 && call_matrix[9-j][0] != 38 && call_matrix[9-j][2] != 0) // sprintf (text_string, "%s", "BUMBLEBEETUNA");
uint8_t slot = eh_slot;
if (strncmp(text_string, state->event_history_s[slot].Event_History_Items[i].event_string, 13) != 0)
{ {
char * timestrCH = getTimeN(call_matrix[9-j][5]); memcpy(text_string, state->event_history_s[slot].Event_History_Items[i].event_string, 71*sizeof(char));
char * datestrCH = getDateN(call_matrix[9-j][5]); text_string[71] = 0; //terminate string
printw ("| #%02d %s \n", i, text_string);
printw ("| ");
printw ("%s ", datestrCH);
printw ("%s ", timestrCH);
if (datestrCH != NULL)
{
free (datestrCH);
datestrCH = NULL;
}
if (timestrCH != NULL)
{
free (timestrCH);
timestrCH = NULL;
}
if (lls == 28 || lls == 29)
{
if (idas == 0) printw ("RAN [%02lld] ", call_matrix[9-j][4]);
if (idas == 1) printw ("Area [%02lld] ", call_matrix[9-j][4]);
printw ("TG [%5lld] ", call_matrix[9-j][1]);
printw ("RID [%5lld] ", call_matrix[9-j][2]);
}
//dPMR
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)
{
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("DCC [%2lld] ", call_matrix[9-j][4]);
}
//P25
if (call_matrix[9-j][0] == 0 || call_matrix[9-j][0] == 1 || call_matrix[9-j][0] == 35 || call_matrix[9-j][0] == 36)
{
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("NAC [0x%03llX] ", call_matrix[9-j][4]);
}
//DMR BS Types
if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 )
{
// printw ("S[%lld] ", call_matrix[9-j][3]); //%d
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
}
//DMR MS Types
if (call_matrix[9-j][0] == 32 || call_matrix[9-j][0] == 33 || call_matrix[9-j][0] == 34 )
{
// printw ("S[%lld] ", call_matrix[9-j][3]);
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
}
// #ifdef LIMAZULUTWEAKS
//Group Name Labels from CSV import
for (int k = 0; k < state->group_tally; k++)
{
if (state->group_array[k].groupNumber == call_matrix[9-j][1])
{
attron(COLOR_PAIR(4));
printw ("[%s]", state->group_array[k].groupName);
printw ("[%s] ", state->group_array[k].groupMode);
}
else if (state->group_array[k].groupNumber == call_matrix[9-j][2])
{
attron(COLOR_PAIR(4));
printw ("[%s]", state->group_array[k].groupName);
printw ("[%s] ", state->group_array[k].groupMode);
}
}
//alias values here
printw ("%s", alias_ch[9-j]);
// #endif
printw ("\n");
} }
sprintf (text_string, "%s", "BUMBLEBEETUNA");
//EDACS and ProVoice, outside of timestamp loop if (strncmp(text_string, state->event_history_s[slot].Event_History_Items[i].text_message, 13) != 0)
if (call_matrix[j][0] == 14 || call_matrix[j][0] == 15 || call_matrix[j][0] == 37 || call_matrix[j][0] == 38 ) printw ("| %s \n", state->event_history_s[slot].Event_History_Items[i].text_message);
{ }
if (call_matrix[j][2] != 0)
{
printw ("| ");
char * timestrCHE = getTimeN(call_matrix[j][5]);
char * datestrCHE = getDateN(call_matrix[j][5]);
printw ("%s ", datestrCHE);
printw ("%s ", timestrCHE);
if (datestrCHE != NULL)
{
free (datestrCHE);
datestrCHE = NULL;
}
if (timestrCHE != NULL)
{
free (timestrCHE);
timestrCHE = NULL;
}
printw ("LCN [%2lld] ", call_matrix[j][1]);
if (state->ea_mode == 1)
{
// Voice call
if ((call_matrix[j][4] & EDACS_IS_VOICE) != 0)
{
// Group call
if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0)
printw ("Target [%8lld] Source [%8lld]", call_matrix[j][2], call_matrix[j][3]);
// I-Call
else if ((call_matrix[j][4] & EDACS_IS_INDIVIDUAL) != 0)
printw ("Target [%8lld] Source [%8lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
// System all-call
else if ((call_matrix[j][4] & EDACS_IS_ALL_CALL) != 0)
printw ("Target [ SYSTEM ] Source [%8lld] All-Call", call_matrix[j][3]);
// Interconnect
else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0)
printw ("Target [ SYSTEM ] Source [%8lld] Interconnect", call_matrix[j][3]);
// Test call
else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0)
printw ("Target [ SYSTEM ] Source [ SYSTEM ] Test Call");
// Unknown call
else
printw ("Unknown call type");
// Call flags
if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {}
else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
else printw (" [Dig]");
if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
}
else
// Data call
printw ("Target [ DATA ] Source [%8lld] Data", call_matrix[j][3]);
}
else
{
// Voice call
if ((call_matrix[j][4] & EDACS_IS_VOICE) != 0)
{
// Compute AFS for display purposes only
int a = (call_matrix[j][2] >> state->edacs_a_shift) & state->edacs_a_mask;
int f = (call_matrix[j][2] >> state->edacs_f_shift) & state->edacs_f_mask;
int s = call_matrix[j][2] & state->edacs_s_mask;
// Group call
if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0) {
char afs_str[8];
getAfsString(state, afs_str, a, f, s);
printw ("Target [%6lld][%s] Source [%5lld]", call_matrix[j][2], afs_str, call_matrix[j][3]);
}
// I-Call
else if ((call_matrix[j][4] & EDACS_IS_INDIVIDUAL) != 0)
if (getAfsStringLength(state) == 6)
printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
else
printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
// System all-call
else if ((call_matrix[j][4] & EDACS_IS_ALL_CALL) != 0)
if (getAfsStringLength(state) == 6)
printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]);
else
printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]);
// Interconnect
else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0)
if (getAfsStringLength(state) == 6)
printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]);
else
printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]);
// Test call
else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0)
if (getAfsStringLength(state) == 6)
printw ("Target [ SYSTEM ] Source [ SYS ] Test Call");
else
printw ("Target [ SYSTEM ] Source [ SYS ] Test Call");
// Unknown call
else
printw ("Unknown call type");
// Call flags
if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {}
else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
else printw (" [Dig]");
if ((call_matrix[j][4] & EDACS_IS_AGENCY_CALL) != 0) printw ("[A]");
if ((call_matrix[j][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]");
if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
}
// Data call
else
if (getAfsStringLength(state) == 6)
printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]);
else
printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]);
}
//test
for (int k = 0; k < state->group_tally; k++)
{
if (state->group_array[k].groupNumber == call_matrix[j][2] && call_matrix[j][2] != 0)
{
attron(COLOR_PAIR(4));
printw ("[%s] ", state->group_array[k].groupName);
break;
}
else if (state->group_array[k].groupNumber == call_matrix[j][3] && call_matrix[j][3] != 0)
{
attron(COLOR_PAIR(4));
printw ("[%s] ", state->group_array[k].groupName);
break;
}
}
//end test
printw ("\n");
}
}
} //end Call History
//fence bottom
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
attroff(COLOR_PAIR(4)); //cyan for history attroff(COLOR_PAIR(4)); //cyan for history
} }
@@ -4798,6 +4590,28 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
noCarrier(opts, state); noCarrier(opts, state);
} }
if (c == 93) //']' key - increment event history indexer
{
if (state->eh_index < 244)
state->eh_index++;
else state->eh_index = 0; //rollover just before we run out of items in the arrray
}
if (c == 91) //'[' key - decrement event history indexer
{
if (state->eh_index > 0)
state->eh_index--;
}
if (c == 92) //'\' key - toggle events for slot displayed, and reset eh_index
{
eh_slot ^= 1;
state->eh_index = 0;
}
//attempt retry to TCP Audio server //attempt retry to TCP Audio server
if (c == 56) // '8' key, try audio in type 8 (TCP Audio Server connection) using defaults OR whatever the user last specified if (c == 56) // '8' key, try audio in type 8 (TCP Audio Server connection) using defaults OR whatever the user last specified
{ {
@@ -5062,9 +4876,6 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//so probably just write a function to handle c input, and when c = certain values //so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those //needing an entry box, then stop all of those
//allocated memory pointer needs to be free'd //allocated memory pointer needs to be free'd
if (timestr != NULL) if (timestr != NULL)
{ {
@@ -5084,3 +4895,402 @@ void ncursesClose ()
endwin(); endwin();
} }
//init each event history struct passed into here
void init_event_history (Event_History_I * event_struct, uint8_t start, uint8_t stop)
{
for (uint8_t i = start; i < stop; i++)
{
event_struct->Event_History_Items[i].write = 0;
event_struct->Event_History_Items[i].systype = -1;
event_struct->Event_History_Items[i].subtype = -1;
event_struct->Event_History_Items[i].gi = 0;
event_struct->Event_History_Items[i].enc = 0;
event_struct->Event_History_Items[i].enc_alg = 0;
event_struct->Event_History_Items[i].enc_key = 0;
event_struct->Event_History_Items[i].mi = 0;
event_struct->Event_History_Items[i].svc = 0;
event_struct->Event_History_Items[i].source_id = 0;
event_struct->Event_History_Items[i].target_id = 0;
event_struct->Event_History_Items[i].channel = 0;
event_struct->Event_History_Items[i].event_time = 0;
memset (event_struct->Event_History_Items[i].pdu, 0, sizeof(event_struct->Event_History_Items[0].pdu));
sprintf (event_struct->Event_History_Items[i].alias, "%s", "BUMBLEBEETUNA");
sprintf (event_struct->Event_History_Items[i].gps_s, "%s", "BUMBLEBEETUNA");
sprintf (event_struct->Event_History_Items[i].text_message, "%s", "BUMBLEBEETUNA");
sprintf (event_struct->Event_History_Items[i].event_string, "%s", "BUMBLEBEETUNA");
}
}
void push_event_history (Event_History_I * event_struct)
{
//Fixed, had it going in the wrong direction first time
for (uint8_t i = 254; i >= 1; i--)
{
event_struct->Event_History_Items[i].write = event_struct->Event_History_Items[i-1].write;
event_struct->Event_History_Items[i].systype = event_struct->Event_History_Items[i-1].systype;
event_struct->Event_History_Items[i].subtype = event_struct->Event_History_Items[i-1].subtype;
event_struct->Event_History_Items[i].gi = event_struct->Event_History_Items[i-1].gi;
event_struct->Event_History_Items[i].enc = event_struct->Event_History_Items[i-1].enc;
event_struct->Event_History_Items[i].enc_alg = event_struct->Event_History_Items[i-1].enc_alg;
event_struct->Event_History_Items[i].enc_key = event_struct->Event_History_Items[i-1].enc_key;
event_struct->Event_History_Items[i].mi = event_struct->Event_History_Items[i-1].mi;
event_struct->Event_History_Items[i].svc = event_struct->Event_History_Items[i-1].svc;
event_struct->Event_History_Items[i].source_id = event_struct->Event_History_Items[i-1].source_id;
event_struct->Event_History_Items[i].target_id = event_struct->Event_History_Items[i-1].target_id;
event_struct->Event_History_Items[i].channel = event_struct->Event_History_Items[i-1].channel;
event_struct->Event_History_Items[i].event_time = event_struct->Event_History_Items[i+1].event_time;
memcpy (event_struct->Event_History_Items[i].pdu, event_struct->Event_History_Items[i-1].pdu, sizeof(event_struct->Event_History_Items[0].pdu));
sprintf (event_struct->Event_History_Items[i].alias, "%s", event_struct->Event_History_Items[i-1].alias);
sprintf (event_struct->Event_History_Items[i].gps_s, "%s", event_struct->Event_History_Items[i-1].gps_s);
sprintf (event_struct->Event_History_Items[i].text_message, "%s", event_struct->Event_History_Items[i-1].text_message);
sprintf (event_struct->Event_History_Items[i].event_string, "%s", event_struct->Event_History_Items[i-1].event_string);
}
}
void write_event_to_log_file (dsd_opts * opts, dsd_state * state, char * event_string) //pass completed event string here that is in the struct
{
//May reconfigure this to pull the struct directly, or pass supplimental strings for text messages, etc
UNUSED(state);
FILE * event_log_file;
event_log_file = fopen(opts->event_out_file, "a");
fprintf (event_log_file, "%s \n", event_string);
char text_string[2000]; sprintf (text_string, "%s", "BUMBLEBEETUNA");
uint8_t slot = state->currentslot;
if (strncmp(text_string, state->event_history_s[slot].Event_History_Items[0].text_message, 13) != 0)
fprintf (event_log_file, "%s \n", state->event_history_s[slot].Event_History_Items[0].text_message);
fflush (event_log_file);
fclose (event_log_file);
}
// run once per loop to check for and push and update event history
void watchdog_event_history (dsd_opts * opts, dsd_state * state, uint8_t slot)
{
//create a pointer to the current slot event history
Event_History_I * event_struct = &state->event_history_s[slot];
//who is currently talking
uint32_t source_id = 0;
//last values pulled from the event history
uint32_t last_source_id = event_struct->Event_History_Items[0].source_id;
if (slot == 0)
source_id = state->lastsrc;
else
source_id = state->lastsrcR;
if (slot == 0) //BUGFIX: generic catch on FDMA systems so that we don't write duplicate data to slot 2 event history
{
//NXDN RID (TODO: Changeover to lastsrc later on)
if (state->lastsynctype == 28 || state->lastsynctype == 29)
source_id = state->nxdn_last_rid;
if (state->lastsynctype == 30 || state->lastsynctype == 30) //YSF Fusion
{
source_id = 0;
for (uint8_t i = 0; i < 11; i++)
source_id += state->ysf_src[i]; //convert to sum value to make a distinct enough src value
}
if (state->lastsynctype == 16 || state->lastsynctype == 17) //M17 STR
{
source_id = 0;
for (uint8_t i = 0; i < 9; i++)
source_id += state->m17_src_csd[i]; //convert to sum value to make a distinct enough src value
}
if (state->lastsynctype == 6 || state->lastsynctype == 7 || state->lastsynctype == 18 || state->lastsynctype == 19) //DSTAR
{
source_id = 0;
for (uint8_t i = 0; i < 12; i++)
source_id += state->dstar_src[i]; //convert to sum value to make a distinct enough src value
//need a strncmp here for 8 spaces in this field first so we don't blip a blank into the event history
if (strncmp(state->dstar_src, " ", 8) == 0)
source_id = 0;
}
if (state->lastsynctype == 16 || state->lastsynctype == 17 || state->lastsynctype == 20 || state->lastsynctype == 24 || state->lastsynctype == 21 || state->lastsynctype == 25 || state->lastsynctype == 22 || state->lastsynctype == 26 || state->lastsynctype == 23 || state->lastsynctype == 27) //dPMR
{
source_id = 0;
for (uint8_t i = 0; i < 20; i++)
source_id += state->dpmr_caller_id[i]; //convert to sum value to make a distinct enough src value
//need a strncmp here for 8 spaces in this field first so we don't blip a blank into the event history
if (strncmp(state->dpmr_caller_id, " ", 6) == 0)
source_id = 0;
}
if (state->lastsynctype == 14 || state->lastsynctype == 15 || state->lastsynctype == 37 || state->lastsynctype == 38) //EDACS Calls
{
source_id = 0;
if (opts->p25_is_tuned == 1)
source_id = state->lastsrc;
}
}
if (source_id != last_source_id && last_source_id != 0) //test without != 0 if we want to constantly update the current event
{
if (opts->event_out_file[0] != 0)
write_event_to_log_file(opts, state, event_struct->Event_History_Items[0].event_string);
push_event_history (event_struct);
init_event_history (event_struct, 0, 1);
}
}
//similar to above, but constantly testing and checking the most recent event only
//this will hopefully be more useful when dealing with an ongoing event with
//features that update over time with embedded signalling, etc
void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot)
{
//create a pointer to the current slot event history
Event_History_I * event_struct = &state->event_history_s[slot];
//TODO: Flesh out more later on.
uint32_t source_id = 0;
uint32_t target_id = 0;
uint16_t svc_opts = 0;
uint8_t subtype = 0;
uint8_t enc = 0;
uint8_t alg_id = 0;
uint16_t key_id = 0;
unsigned long long int mi;
if (slot == 0)
{
source_id = state->lastsrc;
target_id = state->lasttg;
subtype = state->dmrburstL;
svc_opts = state->dmr_so;
enc = (svc_opts >> 6) & 1;
alg_id = state->payload_algid;
key_id = (uint16_t)state->payload_keyid;
mi = state->payload_mi;
}
else
{
source_id = state->lastsrcR;
target_id = state->lasttgR;
subtype = state->dmrburstR;
svc_opts = state->dmr_soR;
enc = (svc_opts >> 6) & 1;
alg_id = state->payload_algidR;
key_id = (uint16_t)state->payload_keyidR;
mi = state->payload_miR;
}
if (slot == 0) //BUGFIX: generic catch on FDMA systems so that we don't write duplicate data to slot 2 event history
{
//NXDN RID (TODO: Changeover to lastsrc and lasttg later on)
if (state->lastsynctype == 28 || state->lastsynctype == 29)
{
source_id = state->nxdn_last_rid;
target_id = state->nxdn_last_tg;
if (state->nxdn_cipher_type != 0)
enc = 1;
alg_id = state->nxdn_cipher_type;
}
if (state->lastsynctype == 30 || state->lastsynctype == 30) //YSF Fusion
{
source_id = 0;
for (uint8_t i = 0; i < 11; i++)
source_id += state->ysf_src[i]; //convert to sum value to make a distinct enough src value
//TODO: Add src and dst as aliases?
}
if (state->lastsynctype == 16 || state->lastsynctype == 17) //M17 STR
{
source_id = 0;
for (uint8_t i = 0; i < 9; i++)
source_id += state->m17_src_csd[i]; //convert to sum value to make a distinct enough src value
}
if (state->lastsynctype == 6 || state->lastsynctype == 7 || state->lastsynctype == 18 || state->lastsynctype == 19) //DSTAR
{
source_id = 0;
for (uint8_t i = 0; i < 12; i++)
source_id += state->dstar_src[i]; //convert to sum value to make a distinct enough src value
//need a strncmp here for 8 spaces in this field first so we don't blip a blank into the event history
if (strncmp(state->dstar_src, " ", 8) == 0)
source_id = 0;
}
if (state->lastsynctype == 16 || state->lastsynctype == 17 || state->lastsynctype == 20 || state->lastsynctype == 24 || state->lastsynctype == 21 || state->lastsynctype == 25 || state->lastsynctype == 22 || state->lastsynctype == 26 || state->lastsynctype == 23 || state->lastsynctype == 27) //dPMR
{
source_id = 0;
for (uint8_t i = 0; i < 20; i++)
source_id += state->dpmr_caller_id[i]; //convert to sum value to make a distinct enough src value
//need a strncmp here for 8 spaces in this field first so we don't blip a blank into the event history
if (strncmp(state->dpmr_caller_id, " ", 6) == 0)
source_id = 0;
}
if (state->lastsynctype == 14 || state->lastsynctype == 15 || state->lastsynctype == 37 || state->lastsynctype == 38) //EDACS Calls
{
source_id = 0;
if (opts->p25_is_tuned == 1)
source_id = state->lastsrc;
}
}
//system type string (P25, DMR, etc)
char * sys_string = SyncTypes[state->lastsynctype];
//date and time strings
char * timestr = getTimeN(time(NULL));
char * datestr = getDateN(time(NULL));
if (source_id != 0)
{
event_struct->Event_History_Items[0].write = 1; //TODO: Write a 1 here after written to a log
if (state->lastsynctype != -1)
event_struct->Event_History_Items[0].systype = state->lastsynctype;
else event_struct->Event_History_Items[0].systype = 39; //generic digital call
event_struct->Event_History_Items[0].subtype = subtype; //voice
event_struct->Event_History_Items[0].gi = state->gi[slot]; //need this add this to link control messages
event_struct->Event_History_Items[0].enc = enc;
event_struct->Event_History_Items[0].enc_alg = alg_id;
event_struct->Event_History_Items[0].enc_key = key_id;
event_struct->Event_History_Items[0].mi = mi;
event_struct->Event_History_Items[0].svc = svc_opts;
event_struct->Event_History_Items[0].source_id = source_id;
event_struct->Event_History_Items[0].target_id = target_id;
event_struct->Event_History_Items[0].channel = 0; //need to add this to trunking messages, if tuned from call grant
event_struct->Event_History_Items[0].event_time = time(NULL);
}
//Craft an event string for ncurses event history, and a more complex string for logging
char event_string[200]; memset(event_string, 0, sizeof(event_string));
//WIP: Seperate Voice Call Event Strings when SRC/TGT values are numerical,
//and a seperate one for when they are string values (M17, YSF, DSTAR, and dPMR, or use special formatting)
if (state->lastsynctype == 30 || state->lastsynctype == 30) //YSF Fusion (may need to use uplink instead of src, unsure for this)
{
//TODO: See if we can add some decoded data as well in the future to an event string
sprintf (event_string, "%s %s %s Voice TGT: %s SRC: %s ", datestr, timestr, sys_string, state->ysf_tgt, state->ysf_src);
}
else if (state->lastsynctype == 16 || state->lastsynctype == 17) //M17
{
//TODO: See if we can add some decoded data as well in the future to an event string
sprintf (event_string, "%s %s %s Voice TGT: %s SRC: %s ", datestr, timestr, sys_string, state->m17_dst_str, state->m17_src_str);
}
else if (state->lastsynctype == 6 || state->lastsynctype == 7 || state->lastsynctype == 18 || state->lastsynctype == 19) //DSTAR
{
//TODO: See if we can add some decoded data as well in the future to an event string
sprintf (event_string, "%s %s %s Voice TGT: %s SRC: %s ", datestr, timestr, sys_string, state->dstar_dst, state->dstar_src);
}
else if (state->lastsynctype == 16 || state->lastsynctype == 17 || state->lastsynctype == 20 || state->lastsynctype == 24 || state->lastsynctype == 21 || state->lastsynctype == 25 || state->lastsynctype == 22 || state->lastsynctype == 26 || state->lastsynctype == 23 || state->lastsynctype == 27) //dPMR
{
//TODO: See if we can add some decoded data as well in the future to an event string
sprintf (event_string, "%s %s %s Voice TGT: %s SRC: %s ", datestr, timestr, sys_string, state->dpmr_target_id, state->dpmr_caller_id);
}
//TODO: Find out why EDACS is also placing items into Slot 2 Event History with valid src, but invalid tg (not a problem, just odd)
else if (state->lastsynctype == 14 || state->lastsynctype == 15 || state->lastsynctype == 37 || state->lastsynctype == 38) //EDACS Calls
{
//is this AFS format, or EA format, also, need to re-add Ilya's other decoded call elements into this somehow
if (state->ea_mode == 1)
{
sprintf (event_string, "%s %s %s Voice TGT: %05d; SRC: %05d; ", datestr, timestr, sys_string, target_id, source_id);
}
else
{
//TODO: Have EDACS decoder write a nicer string for us to use in this instance
// Compute AFS for display purposes only
int a = (state->tg_hold >> state->edacs_a_shift) & state->edacs_a_mask;
int f = (state->tg_hold >> state->edacs_f_shift) & state->edacs_f_mask;
int s = state->tg_hold & state->edacs_s_mask;
char afs_str[8];
getAfsString(state, afs_str, a, f, s);
sprintf (event_string, "%s %s %s Voice AFS: %s ", datestr, timestr, sys_string, afs_str);
}
}
else //any numerical based src and tgt values
{
sprintf (event_string, "%s %s %s Voice TGT: %08d; SRC: %08d; ", datestr, timestr, sys_string, target_id, source_id);
if (enc)
strcat(event_string, "ENC; ");
if (alg_id != 0 && alg_id != 0x80)
{
char ess_str[30];
sprintf (ess_str, "ALG: %02X; KID: %04X;", alg_id, key_id); //KID overflow?
strcat(event_string, ess_str);
}
}
sprintf (event_struct->Event_History_Items[0].event_string, "%s", event_string);
if (timestr != NULL)
{
free (timestr);
timestr = NULL;
}
if (datestr != NULL)
{
free (datestr);
datestr = NULL;
}
}
void watchdog_event_datacall (dsd_opts * opts, dsd_state * state, uint32_t src, uint32_t dst, char * data_string, uint8_t slot)
{
UNUSED(opts);
state->event_history_s[slot].Event_History_Items[0].write = 1; //TODO: Write a 1 here when written to a log
state->event_history_s[slot].Event_History_Items[0].systype = state->lastsynctype;
state->event_history_s[slot].Event_History_Items[0].subtype = 6; //data
state->event_history_s[slot].Event_History_Items[0].gi = state->gi[slot];
state->event_history_s[slot].Event_History_Items[0].enc = 0;
state->event_history_s[slot].Event_History_Items[0].enc_alg = 0;
state->event_history_s[slot].Event_History_Items[0].enc_key = 0;
state->event_history_s[slot].Event_History_Items[0].mi = 0;
state->event_history_s[slot].Event_History_Items[0].svc = 0;
state->event_history_s[slot].Event_History_Items[0].source_id = src;
state->event_history_s[slot].Event_History_Items[0].target_id = dst;
state->event_history_s[slot].Event_History_Items[0].channel = 0;
state->event_history_s[slot].Event_History_Items[0].event_time = time(NULL);
//date and time strings //getTimeN(time(NULL)); //getDateN(time(NULL));
char * timestr = getTimeN(time(NULL));
char * datestr = getDateN(time(NULL));
char event_string[2000]; memset (event_string, 0, sizeof(event_string));
sprintf (event_string, "%s %s ", datestr, timestr);
strcat (event_string, data_string); //may need to check for potential overflow of this
sprintf (state->event_history_s[slot].Event_History_Items[0].event_string, "%s", event_string); //could change this to a strncpy to prevent potential overflow
if (timestr != NULL)
{
free (timestr);
timestr = NULL;
}
if (datestr != NULL)
{
free (datestr);
datestr = NULL;
}
}

View File

@@ -503,6 +503,8 @@ void return_to_cc (dsd_opts * opts, dsd_state * state)
state->lasttgR = 0; state->lasttgR = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->lastsrcR = 0; state->lastsrcR = 0;
state->gi[0] = 0;
state->gi[1] = 0;
state->payload_algid = 0; state->payload_algid = 0;
state->payload_algidR = 0; state->payload_algidR = 0;
state->payload_keyid = 0; state->payload_keyid = 0;

View File

@@ -49,6 +49,10 @@ void processDSTAR(dsd_opts * opts, dsd_state * state)
if (opts->use_ncurses_terminal == 1) if (opts->use_ncurses_terminal == 1)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
} }
fprintf (stderr, "\n"); fprintf (stderr, "\n");

View File

@@ -374,6 +374,10 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
if (opts->use_ncurses_terminal == 1) if (opts->use_ncurses_terminal == 1)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//write to wav file if opened //write to wav file if opened
if (opts->wav_out_f != NULL) if (opts->wav_out_f != NULL)
{ {
@@ -455,6 +459,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
edacs_bit[i] = getDibit (opts, state); //getDibit returns binary 0 or 1 on GFSK signal (Edacs and PV) edacs_bit[i] = getDibit (opts, state); //getDibit returns binary 0 or 1 on GFSK signal (Edacs and PV)
} }
//if we have executed a tune to a channel, then we will forego decoding any more edacs until we return from the voice channel
//this is a simple quick and dirty solution to fix setting the lastsrc value to something that we don't want in event history
if (opts->p25_is_tuned == 1)
goto EDACS_END;
//Each EDACS outbound frame consists of two 40-bit (28-bit data, 12-bit BCH) messages. Each message is sent three //Each EDACS outbound frame consists of two 40-bit (28-bit data, 12-bit BCH) messages. Each message is sent three
//times, with the middle message bitwise-inverted. We use unsigned long long int here to be safe in 32-bit cygwin (not //times, with the middle message bitwise-inverted. We use unsigned long long int here to be safe in 32-bit cygwin (not
//sure if this was actually an issue). //sure if this was actually an issue).
@@ -2135,6 +2144,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
} }
EDACS_END:
if (timestr != NULL) if (timestr != NULL)
{ {

View File

@@ -2466,6 +2466,10 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
if (opts->use_ncurses_terminal == 1) if (opts->use_ncurses_terminal == 1)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
} }
//SEND EOTX to reflector //SEND EOTX to reflector
@@ -3826,6 +3830,10 @@ void processM17IPF(dsd_opts * opts, dsd_state * state)
if (opts->use_ncurses_terminal == 1) if (opts->use_ncurses_terminal == 1)
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//clear frame //clear frame
memset (ip_frame, 0, sizeof(ip_frame)); memset (ip_frame, 0, sizeof(ip_frame));

View File

@@ -1075,10 +1075,10 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
state->payload_keyid = 0; state->payload_keyid = 0;
state->payload_algidR = 0; state->payload_algidR = 0;
state->payload_keyidR = 0; state->payload_keyidR = 0;
state->lastsrc = 0; // state->lastsrc = 0; //disable?
state->lastsrcR = 0; // state->lastsrcR = 0; //disable?
state->lasttg = 0; // state->lasttg = 0; //disable?
state->lasttgR = 0; // state->lasttgR = 0; //disable?
state->p2_is_lcch = 0; state->p2_is_lcch = 0;
state->fourv_counter[0] = 0; state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0; state->fourv_counter[1] = 0;
@@ -1092,6 +1092,15 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
{ {
ncursesPrinter(opts, state); ncursesPrinter(opts, state);
} }
//slot 1
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//slot 2 for TDMA systems
watchdog_event_history(opts, state, 1);
watchdog_event_current(opts, state, 1);
//add 360 bits to each counter //add 360 bits to each counter
vc_counter = vc_counter + 360; vc_counter = vc_counter + 360;

View File

@@ -127,12 +127,15 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
state->dmrburstL = 20; state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - "); fprintf (stderr, "\n VCH 0 - ");
//check that src is not zero first, some harris and other patch systems may do this,
state->lastsrc = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15]; //but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
if (src != 0)
state->lastsrc = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
state->lasttg = (SMAC[16] << 8) | SMAC[17]; state->lasttg = (SMAC[16] << 8) | SMAC[17];
fprintf (stderr, "TG %d ", state->lasttg); fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", state->lastsrc); fprintf (stderr, "SRC %d ", src);
/* /*
When the talker radio is initiating an individual call (unit to unit or telephone interconnect), the reserved group ID of zero When the talker radio is initiating an individual call (unit to unit or telephone interconnect), the reserved group ID of zero
@@ -195,12 +198,15 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
state->dmrburstR = 20; state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - "); fprintf (stderr, "\n VCH 1 - ");
//check that src is not zero first, some harris and other patch systems may do this,
state->lastsrcR = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15]; //but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
if (src != 0)
state->lastsrcR = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
state->lasttgR = (SMAC[16] << 8) | SMAC[17]; state->lasttgR = (SMAC[16] << 8) | SMAC[17];
fprintf (stderr, "TG %d ", state->lasttgR); fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", state->lastsrcR); fprintf (stderr, "SRC %d ", src);
// if (state->lastsrcR == 0) fprintf (stderr, "External "); // if (state->lastsrcR == 0) fprintf (stderr, "External ");
@@ -576,12 +582,15 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->dmrburstL = 20; state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - "); fprintf (stderr, "\n VCH 0 - ");
//check that src is not zero first, some harris and other patch systems may do this,
state->lastsrc = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15]; //but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
if (src != 0)
state->lastsrc = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
state->lasttg = (FMAC[16] << 8) | FMAC[17]; state->lasttg = (FMAC[16] << 8) | FMAC[17];
fprintf (stderr, "TG %d ", state->lasttg); fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", state->lastsrc); fprintf (stderr, "SRC %d ", src);
// if (state->lastsrc == 0) fprintf (stderr, "External "); // if (state->lastsrc == 0) fprintf (stderr, "External ");
@@ -634,12 +643,15 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->dmrburstR = 20; state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - "); fprintf (stderr, "\n VCH 1 - ");
//check that src is not zero first, some harris and other patch systems may do this,
state->lastsrcR = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15]; //but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
if (src != 0)
state->lastsrcR = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
state->lasttgR = (FMAC[16] << 8) | FMAC[17]; state->lasttgR = (FMAC[16] << 8) | FMAC[17];
fprintf (stderr, "TG %d ", state->lasttgR); fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", state->lastsrcR); fprintf (stderr, "SRC %d ", src);
// if (state->lastsrcR == 0) fprintf (stderr, "External "); // if (state->lastsrcR == 0) fprintf (stderr, "External ");