From 13739b18aad839b4909aedcf99cb66696a56c7aa Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Fri, 9 May 2025 02:20:09 -0400 Subject: [PATCH] Event History Setup: #287 Expand Event History for EDACS to Include More Call Information; Misc Tweaks regarding; Add watchdog and wav file closure to EOT_CC when returning from EDACS Analog or Digital Calls; Fix local event_string size in watchdog_event_current; Add watchdog to cleanupAndExit to catch any calls in progress when closing and push them out to event_history log; --- src/dsd_main.c | 12 +++++++++ src/dsd_ncurses.c | 64 +++++++++++++++++++++++++++++++++++++++-------- src/edacs-fme.c | 33 +++++++++++------------- 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/src/dsd_main.c b/src/dsd_main.c index a6d9f38..f772cc6 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1723,9 +1723,21 @@ codec2_destroy(state->codec2_1600); codec2_destroy(state->codec2_3200); #endif + + //watchdog event at this point + watchdog_event_history(opts, state, 0); + watchdog_event_current(opts, state, 0); + watchdog_event_history(opts, state, 1); + watchdog_event_current(opts, state, 1); noCarrier (opts, state); + //watchdog event at this point + watchdog_event_history(opts, state, 0); + watchdog_event_current(opts, state, 0); + watchdog_event_history(opts, state, 1); + watchdog_event_current(opts, state, 1); + if (opts->wav_out_f != NULL) opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); if (opts->wav_out_fR != NULL) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 015abe4..eb34794 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2046,6 +2046,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //may be displayed if we miss an initial call channel assignment. if (state->ea_mode == 1 || (state->lastsrc != 0 || edacs_channel_tree[state->edacs_vc_lcn][4] != state->edacs_vc_call_type)) edacs_channel_tree[state->edacs_vc_lcn][3] = state->lastsrc; + if (state->ea_mode == 0 && state->lastsrc == 0x800) //this was from a grant update, so set this to 0 + edacs_channel_tree[state->edacs_vc_lcn][3] = 0; edacs_channel_tree[state->edacs_vc_lcn][4] = state->edacs_vc_call_type; edacs_channel_tree[state->edacs_vc_lcn][5] = time(NULL); } @@ -4927,6 +4929,19 @@ void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot) sprintf (sysid_string, "EDACS_SITE_%03d", sys_id1); strcat (sysid_string, sup_str); + + if (state->ea_mode == 0) + { + int afs = state->lasttg; + sprintf(src_str, "%s", ""); sprintf(tgt_str, "%s", ""); + int a = (afs >> state->edacs_a_shift) & state->edacs_a_mask; + int f = (afs >> state->edacs_f_shift) & state->edacs_f_mask; + int s = afs & state->edacs_s_mask; + sprintf (tgt_str, "%03d_AFS_%02d_%02d%01d", afs, a, f, s); + if (state->lastsrc != 0x800 && state->lastsrc != 0) + sprintf (src_str, "LID_%d", state->lastsrc); + else sprintf (src_str, "LID_UNK"); + } } @@ -5007,7 +5022,7 @@ void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot) } //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)); + char event_string[2000]; 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) @@ -5036,24 +5051,53 @@ void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot) if (state->dPMRVoiceFS2Frame.Version[0] == 3) strcat (event_string, "Scrambler Enc; "); } - //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 + svc_opts = state->edacs_vc_call_type; + char sup_str[200]; memset (sup_str, 0, sizeof(sup_str)); + sprintf (sup_str, "%s", ""); + if (svc_opts & 0x02) + strcat (sup_str, "Digital "); + else strcat (sup_str, "Analog "); + if (svc_opts & 0x04) + strcat (sup_str, "Emergency "); + if (svc_opts & 0x08) + strcat (sup_str, "Group "); + if (svc_opts & 0x10) + strcat (sup_str, "I "); + if (svc_opts & 0x20) + strcat (sup_str, "ALL "); + if (svc_opts & 0x40) + strcat (sup_str, "INTER "); + if (svc_opts & 0x80) + strcat (sup_str, "TEST "); + if (svc_opts & 0x100) + strcat (sup_str, "AGENCY "); + if (svc_opts & 0x200) + strcat (sup_str, "FLEET "); + if (svc_opts & 0x01) + strcat (sup_str, "Voice "); + strcat (sup_str, "Call"); + if (state->ea_mode == 1) { - sprintf (event_string, "%s %s %s TGT: %07d; SRC: %07d; LCN: %02d; SITE: %d:%d.%04X; ", datestr, timestr, sys_string, target_id, source_id, channel, sys_id1, sys_id2, sys_id3); + sprintf (event_string, "%s %s %s TGT: %07d; SRC: %07d; LCN: %02d; SITE: %d:%d.%04X; %s;", datestr, timestr, sys_string, target_id, source_id, channel, sys_id1, sys_id2, sys_id3, sup_str); } 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; + int afs = state->lasttg; + int a = (afs >> state->edacs_a_shift) & state->edacs_a_mask; + int f = (afs >> state->edacs_f_shift) & state->edacs_f_mask; + int s = afs & 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); + char lid_str[20]; memset(lid_str, 0, sizeof(lid_str)); + sprintf(lid_str, "%s", ""); + if (state->lastsrc != 0 && state->lastsrc != 0x800) + sprintf (lid_str, "LID: %05d;", state->lastsrc); + else sprintf (lid_str, "LID: __UNK;"); + + sprintf (event_string, "%s %s %s AFS: %s (%04d); %s LCN: %02d; Site: %d; %s; ", datestr, timestr, sys_string, afs_str, afs, lid_str, channel, sys_id1, sup_str); } } else if (state->lastsynctype == 10 || state->lastsynctype == 11 || state->lastsynctype == 12 || state->lastsynctype == 13 || diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 3bef92e..0fa406c 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -73,22 +73,6 @@ unsigned long long int edacsVoteFr(unsigned long long int fr_1_4, unsigned long return msg_result & 0xFFFFFFFFFF; } -void openWavOutFile48k (dsd_opts * opts, dsd_state * state) -{ - UNUSED(state); - SF_INFO info; - info.samplerate = 48000; //48k for analog output (has to match input) - info.channels = 1; - info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE; - opts->wav_out_f = sf_open (opts->wav_out_file, SFM_RDWR, &info); - - if (opts->wav_out_f == NULL) - { - fprintf (stderr,"Error - could not open wav output file %s\n", opts->wav_out_file); - return; - } -} - //listening to and playing back analog audio void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn) { @@ -1455,7 +1439,7 @@ void edacs(dsd_opts * opts, dsd_state * state) //Call info for state if (lcn != 0){state->edacs_vc_lcn = lcn;} state->lasttg = target; - state->lastsrc = 0; + state->lastsrc = 0x800; //Call type for state if (is_individual_call == 0) state->edacs_vc_call_type = EDACS_IS_GROUP; @@ -1589,7 +1573,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (lcn != 0){state->edacs_vc_lcn = lcn;} state->lasttg = target; //Alas, EDACS standard does not provide a source LID on channel updates - try to work around this on the display end instead - state->lastsrc = 0; + state->lastsrc = 0x800; //Call type for state state->edacs_vc_call_type = EDACS_IS_VOICE; @@ -2184,6 +2168,19 @@ void eot_cc(dsd_opts * opts, dsd_state * state) fprintf (stderr, "EOT; \n"); + //watchdog event at this point + state->lastsynctype = 38; + watchdog_event_history(opts, state, 0); + watchdog_event_current(opts, state, 0); + + //close and rename wav file here, then open a new one + if (opts->dmr_stereo_wav == 1) + { + if (opts->wav_out_f != NULL) + opts->wav_out_f = close_and_rename_wav_file(opts->wav_out_f, opts->wav_out_file, opts->wav_out_dir, &state->event_history_s[0]); + opts->wav_out_f = open_wav_file(opts->wav_out_dir, opts->wav_out_file, 8000, 0); + } + //set here so that when returning to the CC, it doesn't go into an immediate hunt if not immediately acquired state->last_cc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);