/*************************************************************************** * msr_writemseed: * * Pack MSRecord data into Mini-SEED record(s) by calling msr_pack() and * write to a specified file. * * Returns the number of records written on success and -1 on error. ***************************************************************************/ int msr_writemseed (MSRecord *msr, const char *msfile, flag overwrite, int reclen, flag encoding, flag byteorder, flag verbose) { FILE *ofp; char srcname[50]; char *perms = (overwrite) ? "wb" : "ab"; int packedrecords = 0; if (!msr || !msfile) return -1; /* Open output file or use stdout */ if (strcmp (msfile, "-") == 0) { ofp = stdout; } else if ((ofp = fopen (msfile, perms)) == NULL) { ms_log (1, "Cannot open output file %s: %s\n", msfile, strerror (errno)); return -1; } /* Pack the MSRecord */ if (msr->numsamples > 0) { msr->encoding = encoding; msr->reclen = reclen; msr->byteorder = byteorder; packedrecords = msr_pack (msr, &ms_record_handler_int, ofp, NULL, 1, verbose - 1); if (packedrecords < 0) { msr_srcname (msr, srcname, 1); ms_log (1, "Cannot write Mini-SEED for %s\n", srcname); } } /* Close file and return record count */ fclose (ofp); return (packedrecords >= 0) ? packedrecords : -1; } /* End of msr_writemseed() */
bool MSeedWriter::write(IntegerMSeedRecord::SharedPtr_t sampleRange) { // наполнения хедера mseed MSRecord* msr = msr_init(NULL); // общие для записей данные strcpy(msr->network, sampleRange->network().toLatin1().constData()); strcpy(msr->station, sampleRange->station().toLatin1().constData()); strcpy(msr->location, sampleRange->location().toLatin1().constData()); strcpy(msr->channel, sampleRange->channelName().toLatin1().constData()); msr->samprate = sampleRange->samplingRateHz(); msr->reclen = _recordLength; msr->record = NULL; msr->encoding = _encoding; // compression msr->byteorder = 1; // big endian byte order BTime btime = dateTimeToBTime(sampleRange->startTime()); msr->starttime = ms_btime2hptime(&btime); msr->sampletype = 'i'; // declare type to be 32-bit integers msr->datasamples = sampleRange->data().data(); msr->numsamples = sampleRange->data().size(); flag verbose = _verbose; _packedSamples = 0; _packedRecords = msr_pack(msr, &binaryStreamRecorder, _binaryStream.get(), &_packedSamples, 1, verbose); if (_packedRecords == -1) { return false; } msr->datasamples = NULL; msr_free(&msr); ms_log(0, "Packed %d samples into %d records\n", _packedSamples, _packedRecords); return true; }
int main (int argc, char **argv) { MSRecord *msr = 0; MSTraceGroup *mstg = 0; MSTrace *mst; int retcode; int totalrecs = 0; int totalsamps = 0; int packedsamples; int packedrecords; int lastrecord; int iseqnum = 1; #ifndef WIN32 /* Signal handling, use POSIX calls with standardized semantics */ struct sigaction sa; sa.sa_flags = SA_RESTART; sigemptyset (&sa.sa_mask); sa.sa_handler = term_handler; sigaction (SIGINT, &sa, NULL); sigaction (SIGQUIT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGHUP, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); #endif /* Process given parameters (command line and parameter file) */ if (parameter_proc (argc, argv) < 0) return -1; /* Setup input encoding format if specified */ if ( encodingstr ) { int inputencoding = strtoul (encodingstr, NULL, 10); if ( inputencoding == 0 && errno == EINVAL ) { ms_log (2, "Error parsing input encoding format: %s\n", encodingstr); return -1; } MS_UNPACKENCODINGFORMAT (inputencoding); } /* Init MSTraceGroup */ mstg = mst_initgroup (mstg); /* Loop over the input file */ while ( (retcode = ms_readmsr (&msr, inputfile, reclen, NULL, &lastrecord, 1, 1, verbose)) == MS_NOERROR ) { totalrecs++; totalsamps += msr->samplecnt; msr_print (msr, ppackets); if ( packreclen >= 0 ) msr->reclen = packreclen; else packreclen = msr->reclen; if ( packencoding >= 0 ) msr->encoding = packencoding; else packencoding = msr->encoding; if ( byteorder >= 0 ) msr->byteorder = byteorder; else byteorder = msr->byteorder; /* After unpacking the record, the start time in msr->starttime is a potentially corrected start time, if correction has been applied make sure the correction bit flag is set as it will be used as a packing template. */ if ( msr->fsdh->time_correct && ! (msr->fsdh->act_flags & 0x02) ) { ms_log (1, "Setting time correction applied flag for %s_%s_%s_%s\n", msr->network, msr->station, msr->location, msr->channel); msr->fsdh->act_flags |= 0x02; } /* If no samples in the record just pack the header */ if ( outfile && msr->numsamples == 0 ) { msr_pack_header (msr, 1, verbose); record_handler (msr->record, msr->reclen, NULL); } /* Pack each record individually */ else if ( outfile && ! tracepack ) { msr->sequence_number = iseqnum; packedrecords = msr_pack (msr, &record_handler, NULL, &packedsamples, 1, verbose); if ( packedrecords == -1 ) ms_log (2, "Cannot pack records\n"); else ms_log (1, "Packed %d records\n", packedrecords); iseqnum = msr->sequence_number; } /* Pack records from a MSTraceGroup */ else if ( outfile && tracepack ) { mst = mst_addmsrtogroup (mstg, msr, 0, -1.0, -1.0); if ( ! mst ) { ms_log (2, "Error adding MSRecord to MStrace!\n"); break; } /* Reset sequence number and free previous template */ if ( mst->prvtptr ) { MSRecord *tmsr = (MSRecord *) mst->prvtptr; /* Retain sequence number from previous template */ msr->sequence_number = tmsr->sequence_number; msr_free (&tmsr); } else { msr->sequence_number = 1; } /* Copy MSRecord and store as template */ mst->prvtptr = msr_duplicate (msr, 0); if ( ! mst->prvtptr ) { ms_log (2, "Error duplicating MSRecord for template!\n"); break; } /* Pack traces based on selected method */ packedrecords = 0; if ( tracepack == 1 ) { mst = mstg->traces; while ( mst ) { packedrecords += mst_pack (mst, &record_handler, NULL, packreclen, packencoding, byteorder, &packedsamples, lastrecord, verbose, (MSRecord *)mst->prvtptr); mst = mst->next; } ms_log (1, "Packed %d records\n", packedrecords); } if ( tracepack == 2 && lastrecord ) { mst = mstg->traces; while ( mst ) { packedrecords += mst_pack (mst, &record_handler, NULL, packreclen, packencoding, byteorder, &packedsamples, lastrecord, verbose, (MSRecord *)mst->prvtptr); mst = mst->next; } ms_log (1, "Packed %d records\n", packedrecords); } } } if ( retcode != MS_ENDOFFILE ) ms_log (2, "Error reading %s: %s\n", inputfile, ms_errorstr(retcode)); /* Make sure everything is cleaned up */ ms_readmsr (&msr, NULL, 0, NULL, NULL, 0, 0, 0); mst_freegroup (&mstg); if ( outfile ) fclose (outfile); getchar(); return 0; } /* End of main() */
/*************************************************************************** * collect_and_write: * * Attempt to connect to a device, slows down the loop checking * after 20 attempts with a larger delay to reduce pointless * work being done. * * Returns 0 on success and -1 otherwise. ***************************************************************************/ int collect_and_write() { int32_t idata[2000]; // enough space for data of 2 records hptime_t hptime; hptime_t start_hptime_est = 0; hptime_t last_hptime; DOUBLE dt, dt_est, sample_rate_est; DOUBLE start_hptime_current, record_window_current, record_window_est; DOUBLE prev_start_hptime_est = -1; int n_start_hptime_est; // debug hptime_t start_hptime_nominal = 0; hptime_t prev_start_next_hptime_est = 0; double diff_end, diff_end_cumul = 0.0; char seedtimestr[64]; // decay constant depends on required decay time and sample rate //double decay_minutes = 60.0; // 1 hour double decay_minutes = 1.0; double decay_consant = 1.0 / (decay_minutes * 60.0 * (double) nominal_sample_rate); // initialize last_hptime to current time last_hptime = current_utc_hptime(); // initialize dt_est based on nominal sample rate dt_est = (nominal_sample_rate == 80) ? 1.0 / SAMP_PER_SEC_80 : (nominal_sample_rate == 40) ? 1.0 / SAMP_PER_SEC_40 : 1.0 / SAMP_PER_SEC_20; // ‘a’: 20.032 SPS // ‘b’: 39.860 SPS // ‘c’: 79.719 SPS // initialize record_window_est based on nominal sample rate and record length record_window_est = dt_est * num_samples_in_record; if (DEBUG) { logprintf(MSG_FLAG, "Initialize: last_hptime=%lld, dt_est=%lld, dt=%lf, dt_end=%lf, dt_end_cumul=%lf)\n", last_hptime, dt_est, record_window_est); } int first = 1; MSRecord *pmsrecord = msr_init(NULL); strcpy(pmsrecord->network, station_network); strcpy(pmsrecord->station, station_name); strcpy(pmsrecord->location, ""); sprintf(pmsrecord->channel, "%s%s", channel_prefix, component); pmsrecord->samprate = 1.0; pmsrecord->reclen = SLRECSIZE; pmsrecord->encoding = mswrite_data_encoding_type_code; pmsrecord->byteorder = 1; pmsrecord->datasamples = idata; pmsrecord->numsamples = 0; pmsrecord->sampletype = 'i'; while (1) { // load data up to SLRECSIZE long ivalue; int nsamp = 0; start_hptime_current = 0; n_start_hptime_est = 0; while (nsamp < num_samples_in_record) { ivalue = read_next_value(&hptime, TIMEOUT_LARGE); if (ivalue == READ_ERROR || ivalue < MIN_DATA || ivalue > MAX_DATA) { logprintf(MSG_FLAG, "READ_ERROR: port=%s, nsamp=%d, ivalue=%ld\n", port_path, nsamp, ivalue); pmsrecord->datasamples = NULL; msr_free(&pmsrecord); return (-1); } if (DEBUG && nsamp == 0) { start_hptime_nominal = hptime; } idata[pmsrecord->numsamples + nsamp] = (int32_t) ivalue; dt = (DOUBLE) (hptime - last_hptime) / (DOUBLE) HPTMODULUS; last_hptime = hptime; if (verbose > 3) { logprintf(MSG_FLAG, "%d %ld %s (dt=%lf)\n", nsamp, ivalue, ms_hptime2seedtimestr(hptime, seedtimestr, 1), (double) dt); } // estimate start time and dt // use only later samples in record since writing previous record may delay reading of first samples of this record if (nsamp >= num_samples_in_record / 2) { // 20131107 AJL - use all samples, may give better start time estimate, since buffering should compensate for any delay of first samples //if (1) { // start time estimate is timestamp of current data minus dt_est*nsamp start_hptime_current += (hptime - (hptime_t) ((DOUBLE) 0.5 + dt_est * (DOUBLE) HPTMODULUS * (DOUBLE) nsamp)); n_start_hptime_est++; // accumulate dt_est using low-pass filter //dt_est = dt_est + (DOUBLE) decay_consant * (dt - dt_est); } nsamp++; } start_hptime_current /= n_start_hptime_est; if (prev_start_hptime_est > 0) { record_window_current = (DOUBLE) (start_hptime_current - prev_start_hptime_est) / (DOUBLE) HPTMODULUS; } else { record_window_current = record_window_est; } // accumulate record_window_est using low-pass filter record_window_est = record_window_est + (DOUBLE) decay_consant * (record_window_current - record_window_est); if (prev_start_hptime_est > 0) { start_hptime_est = prev_start_hptime_est + (hptime_t) ((DOUBLE) 0.5 + record_window_est * (DOUBLE) HPTMODULUS); } else { start_hptime_est = start_hptime_current; } prev_start_hptime_est = start_hptime_est; // test - truncate dt to 1/10000 s to match precision of miniseed btime //logprintf(MSG_FLAG, "0 sample_rate_est=%lf (dt=%lfs)\n", (double) ((DOUBLE) 1.0 / dt_est), (double) dt_est); dt_est = record_window_est / (DOUBLE) num_samples_in_record; sample_rate_est = (DOUBLE) 1.0 / dt_est; if (DEBUG) { diff_end = (double) (start_hptime_est - prev_start_next_hptime_est) / (double) HPTMODULUS; if (!first) diff_end_cumul += diff_end; logprintf(MSG_FLAG, "sample_rate_est=%lf (dt=%lfs)\n", (double) sample_rate_est, (double) dt_est); logprintf(MSG_FLAG, "start_hptime_est=%lld, start_hptime_nominal=%lld, dt=%lf, dt_end=%lf, dt_end_cumul=%lf)\n", start_hptime_est, start_hptime_nominal, (double) ((DOUBLE) (start_hptime_est - start_hptime_nominal) / (DOUBLE) HPTMODULUS), diff_end, diff_end_cumul); prev_start_next_hptime_est = start_hptime_est + (hptime_t) ((DOUBLE) 0.5 + dt_est * (DOUBLE) HPTMODULUS * (DOUBLE) nsamp); } pmsrecord->starttime = start_hptime_est - (DOUBLE) HPTMODULUS * pmsrecord->numsamples / pmsrecord->samprate; pmsrecord->samprate = mswrite_header_sample_rate > 0.0 ? mswrite_header_sample_rate : sample_rate_est; pmsrecord->numsamples += nsamp; int64_t npackedsamples = 0; if (msr_pack(pmsrecord, record_handler, NULL, &npackedsamples, 0, verbose) < 0) { logprintf(ERROR_FLAG, "Error encoding data!\n"); exit(1); } pmsrecord->numsamples -= npackedsamples; memmove(&idata[0], &idata[npackedsamples], pmsrecord->numsamples * 4); } return (0); }