diff --git a/lib/imc_channel.hpp b/lib/imc_channel.hpp index dcb3a80..0683111 100644 --- a/lib/imc_channel.hpp +++ b/lib/imc_channel.hpp @@ -5,6 +5,7 @@ #include "imc_datatype.hpp" #include "imc_conversion.hpp" +#include "imc_block.hpp" #include #include #include @@ -20,34 +21,62 @@ namespace imc { + struct component_env + { + std::string uuid_; + // required channel components for CG channels only + std::string CCuuid_, CPuuid_; + // optional channel components for CG channels only + std::string CDuuid_, NTuuid_; + std::string Cbuuid_, CRuuid_; + + // reset all members + void reset() + { + uuid_.clear(); + CCuuid_.clear(); + CPuuid_.clear(); + CDuuid_.clear(); + Cbuuid_.clear(); + CRuuid_.clear(); + NTuuid_.clear(); + } + }; + // collect uuid's of blocks required for full channel reconstruction struct channel_env { // define unique identifer for channel_env std::string uuid_; + // collect common affiliate blocks for every channel + std::string NOuuid_, NLuuid_; // collect affiliate blocks for a single channel - std::string CBuuid_, CGuuid_, CCuuid_, CNuuid_; - std::string CDuuid_, CTuuid_, Cbuuid_, CPuuid_, CRuuid_, CSuuid_; - std::string NTuuid_, NOuuid_, NLuuid_; + // channel types + std::string CBuuid_, CGuuid_, CIuuid_, CTuuid_; + std::string CNuuid_, CDuuid_, NTuuid_; + std::string CSuuid_; + + component_env compenv1_; + component_env compenv2_; + // reset all members void reset() { uuid_.clear(); - CBuuid_.clear(); - CGuuid_.clear(); - CCuuid_.clear(); - CNuuid_.clear(); - CDuuid_.clear(); - CTuuid_.clear(); - Cbuuid_.clear(); - CPuuid_.clear(); - CRuuid_.clear(); - CSuuid_.clear(); - NTuuid_.clear(); NOuuid_.clear(); NLuuid_.clear(); + CBuuid_.clear(); + CGuuid_.clear(); + CIuuid_.clear(); + CTuuid_.clear(); + CNuuid_.clear(); + CDuuid_.clear(); + NTuuid_.clear(); + CSuuid_.clear(); + compenv1_.reset(); + compenv2_.reset(); } // get info @@ -55,21 +84,23 @@ namespace imc { std::stringstream ss; ss<* blocks, std::vector* buffer) + : compenv_(compenv) + { + if (blocks->count(compenv.CCuuid_) == 1) + { + CC_.parse(buffer, blocks->at(compenv.CCuuid_).get_parameters()); + } + if (blocks->count(compenv.CPuuid_) == 1) + { + CP_.parse(buffer, blocks->at(compenv.CPuuid_).get_parameters()); + } + if (blocks->count(compenv.CDuuid_) == 1) + { + CD_.parse(buffer, blocks->at(compenv.CDuuid_).get_parameters()); + } + if (blocks->count(compenv.Cbuuid_) == 1) + { + Cb_.parse(buffer, blocks->at(compenv.Cbuuid_).get_parameters()); + } + if (blocks->count(compenv.CRuuid_) == 1) + { + CR_.parse(buffer, blocks->at(compenv.CRuuid_).get_parameters()); + } + if (blocks->count(compenv.NTuuid_) == 1) + { + NT_.parse(buffer, blocks->at(compenv.NTuuid_).get_parameters()); + } + } + }; + + // channel struct channel { @@ -237,8 +313,15 @@ namespace imc std::map* blocks_; std::vector* buffer_; + imc::origin_data NO_; + + imc::text CT_; + imc::groupobj CB_; + imc::datafield CG_; + // collect meta-data of channels according to env, // just everything valueable in here + // TODO: is this necessary? std::string uuid_; std::string name_, comment_; std::string origin_, origin_comment_, text_; @@ -249,16 +332,17 @@ namespace imc std::string xname_, xunit_; double xstepwidth_, xoffset_; int xprec_; + int dimension_; // buffer and data - int signbits_, num_bytes_; + int xsignbits_, xnum_bytes_; + int ysignbits_, ynum_bytes_; // unsigned long int byte_offset_; - unsigned long int buffer_offset_, buffer_size_; + unsigned long int xbuffer_offset_, ybuffer_offset_; + unsigned long int xbuffer_size_, ybuffer_size_; long int addtime_; - int datatp_; - imc::datatype dattyp_; - std::vector ydata_; - std::vector xdata_; + imc::numtype xdatatp_, ydatatp_; + std::vector xdata_, ydata_; // range, factor and offset double factor_, offset_; @@ -274,127 +358,73 @@ namespace imc factor_(1.), offset_(0.), group_index_(-1) { - // declare list of block parameters - std::vector prms; - // use uuid from CN block uuid_ = chnenv_.CNuuid_; // extract associated CB data if ( blocks_->count(chnenv_.CBuuid_) == 1 ) { - prms = blocks_->at(chnenv_.CBuuid_).get_parameters(); - group_index_ = std::stoi(blocks_->at(chnenv_.CBuuid_).get_parameter(prms[2])); - group_name_ = blocks_->at(chnenv_.CBuuid_).get_parameter(prms[4]); - group_comment_ = blocks_->at(chnenv_.CBuuid_).get_parameter(prms[6]); + CB_.parse(buffer_, blocks_->at(chnenv_.CBuuid_).get_parameters()); } // extract associated CT data if ( blocks_->count(chnenv_.CTuuid_) == 1 ) { - prms = blocks_->at(chnenv_.CTuuid_).get_parameters(); - text_ = blocks_->at(chnenv_.CTuuid_).get_parameter(prms[4]) + std::string(" - ") - + blocks_->at(chnenv_.CTuuid_).get_parameter(prms[6]) + std::string(" - ") - + blocks_->at(chnenv_.CTuuid_).get_parameter(prms[8]); + CT_.parse(buffer_, blocks_->at(chnenv_.CTuuid_).get_parameters()); + text_ = CT_.name_ + std::string(" - ") + + CT_.text_ + std::string(" - ") + + CT_.comment_; } - // extract associated CD data - if ( blocks_->count(chnenv_.CDuuid_) == 1 ) + if ( !chnenv_.compenv1_.uuid_.empty() && chnenv_.compenv2_.uuid_.empty() ) { - prms = blocks_->at(chnenv_.CDuuid_).get_parameters(); - xstepwidth_ = std::stod(blocks_->at(chnenv_.CDuuid_).get_parameter(prms[2])); - xunit_ = blocks_->at(chnenv_.CDuuid_).get_parameter(prms[5]); - // TODO - // xname_ = std::string("time"); - - // find appropriate precision for "xdata_" by means of "xstepwidth_" - xprec_ = (xstepwidth_ > 0 ) ? (int)ceil(fabs(log10(xstepwidth_))) : 10; - } - - // extract associated CP data - if ( blocks_->count(chnenv_.CPuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.CPuuid_).get_parameters(); - num_bytes_ = std::stoi(blocks_->at(chnenv_.CPuuid_).get_parameter(prms[3])); - datatp_ = std::stoi(blocks_->at(chnenv_.CPuuid_).get_parameter(prms[4])); - signbits_ = std::stoi(blocks_->at(chnenv_.CPuuid_).get_parameter(prms[5])); - // byte_offset_ = std::stoul(blocks_->at(chnenv_.CPuuid_).get_parameter(prms[7])); - } - - // extract associated Cb data - if ( blocks_->count(chnenv_.Cbuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.Cbuuid_).get_parameters(); - buffer_offset_ = std::stoul(blocks_->at(chnenv_.Cbuuid_).get_parameter(prms[6])); - buffer_size_ = std::stoul(blocks_->at(chnenv_.Cbuuid_).get_parameter(prms[7])); - xoffset_ = std::stod(blocks_->at(chnenv_.Cbuuid_).get_parameter(prms[11])); - addtime_ = (long int)std::stod(blocks_->at(chnenv_.Cbuuid_).get_parameter(prms[12])); - } - - // extract associated CR data - if ( blocks_->count(chnenv_.CRuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.CRuuid_).get_parameters(); - factor_ = std::stod(blocks_->at(chnenv_.CRuuid_).get_parameter(prms[3])); - offset_ = std::stod(blocks_->at(chnenv_.CRuuid_).get_parameter(prms[4])); - yunit_ = blocks_->at(chnenv_.CRuuid_).get_parameter(prms[7]); - } - - // extract associated CN data - if ( blocks_->count(chnenv_.CNuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.CNuuid_).get_parameters(); - name_ = blocks_->at(chnenv_.CNuuid_).get_parameter(prms[6]); - yname_ = name_; - comment_ = blocks_->at(chnenv_.CNuuid_).get_parameter(prms[8]); - // group_index_ = std::stoi(blocks_->at(chnenv_.CNuuid_).get_parameter(prms[2])); - } - - // extract associated NO data - if ( blocks_->count(chnenv_.NOuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.NOuuid_).get_parameters(); - origin_ = blocks_->at(chnenv_.NOuuid_).get_parameter(prms[4]); - origin_comment_ = blocks_->at(chnenv_.NOuuid_).get_parameter(prms[6]); - } - - // extract associated NL data - // codepage: - // - http://www.iana.org/assignments/character-sets/character-sets.xhtml - // - https://de.wikipedia.org/wiki/Zeichensatztabelle - // language-code: - // - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c?redirectedfrom=MSDN - if ( blocks_->count(chnenv_.NLuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.NLuuid_).get_parameters(); - codepage_ = blocks_->at(chnenv_.NLuuid_).get_parameter(prms[2]); - language_code_ = blocks_->at(chnenv_.NLuuid_).get_parameter(prms[3]); - } - - // obtain NT data - // - https://en.cppreference.com/w/cpp/chrono/c/tm - // - https://en.cppreference.com/w/cpp/io/manip/put_time - if ( blocks_->count(chnenv_.NTuuid_) == 1 ) - { - prms = blocks_->at(chnenv_.NTuuid_).get_parameters(); - //std::tm tm{}; - std::tm tms = std::tm(); - tms.tm_mday = std::stoi(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[2])); - tms.tm_mon = std::stoi(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[3])) - 1; - tms.tm_year = std::stoi(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[4])) - 1900; - tms.tm_hour = std::stoi(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[5])); - tms.tm_min = std::stoi(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[6])); - long double secs = std::stold(blocks_->at(chnenv_.NTuuid_).get_parameter(prms[7])); - double secs_int; - trigger_time_frac_secs_ = modf((double)secs,&secs_int); - tms.tm_sec = (int)secs_int; - //tms.tm_isdst = -1; + // normal dataset (single component) + // comp_group1 contains y-data, x-data is based on xstepwidth_, xoffset_ and the length of y-data + component_group comp_group1(chnenv_.compenv1_, blocks_, buffer_); + dimension_ = 1; + xstepwidth_ = comp_group1.CD_.dx_; + xunit_ = comp_group1.CD_.unit_; + ybuffer_offset_ = comp_group1.Cb_.offset_buffer_; + ybuffer_size_ = comp_group1.Cb_.number_bytes_; + xoffset_ = comp_group1.Cb_.x0_; + addtime_ = static_cast(comp_group1.Cb_.add_time_); + factor_ = comp_group1.CR_.factor_; + offset_ = comp_group1.CR_.offset_; + yunit_ = comp_group1.CR_.unit_; + name_ = comp_group1.CN_.name_; + yname_ = comp_group1.CN_.name_; + comment_ = comp_group1.CN_.comment_; + ynum_bytes_ = comp_group1.CP_.bytes_; + ydatatp_ = comp_group1.CP_.numeric_type_; + ysignbits_ = comp_group1.CP_.signbits_; // generate std::chrono::system_clock::time_point type - // ( - https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html - // - https://man7.org/linux/man-pages/man3/tzset.3.html ) - std::time_t ts = timegm(&tms); //std::mktime(&tms); + std::time_t ts = timegm(&comp_group1.NT_.tms_); // std::mktime(&tms); trigger_time_ = std::chrono::system_clock::from_time_t(ts); + trigger_time_frac_secs_ = comp_group1.NT_.trigger_time_frac_secs_; + } + else if ( !chnenv_.compenv1_.uuid_.empty() && !chnenv_.compenv2_.uuid_.empty() ) + { + // XY dataset (two components) + // comp_group1 contains x-data, comp_group2 contains y-data + component_group comp_group1(chnenv_.compenv1_, blocks_, buffer_); + component_group comp_group2(chnenv_.compenv2_, blocks_, buffer_); + dimension_ = 2; + + xbuffer_offset_ = comp_group1.Cb_.offset_buffer_; + xbuffer_size_ = comp_group1.Cb_.number_bytes_; + ybuffer_offset_ = comp_group2.Cb_.offset_buffer_; + ybuffer_size_ = comp_group2.Cb_.number_bytes_; + factor_ = comp_group2.CR_.factor_; + offset_ = comp_group2.CR_.offset_; + xdatatp_ = comp_group1.CP_.numeric_type_; + xsignbits_ = comp_group1.CP_.signbits_; + ydatatp_ = comp_group2.CP_.numeric_type_; + ysignbits_ = comp_group2.CP_.signbits_; + } + else + { + // no datafield } // start converting binary buffer to imc::datatype @@ -419,77 +449,109 @@ namespace imc // extract (channel dependent) part of buffer unsigned long int buffstrt = prms[3].begin(); - std::vector CSbuffer( buffer_->begin()+buffstrt+buffer_offset_+1, - buffer_->begin()+buffstrt+buffer_offset_+buffer_size_+1 ); + std::vector yCSbuffer( buffer_->begin()+buffstrt+ybuffer_offset_+1, + buffer_->begin()+buffstrt+ybuffer_offset_+ybuffer_size_+1 ); // determine number of values in buffer - unsigned long int num_values = (unsigned long int)(CSbuffer.size()/(signbits_/8)); - if ( num_values*(signbits_/8) != CSbuffer.size() ) + unsigned long int ynum_values = (unsigned long int)(yCSbuffer.size()/(ysignbits_/8)); + if ( ynum_values*(ysignbits_/8) != yCSbuffer.size() ) { - throw std::runtime_error("CSbuffer and significant bits of datatype don't match"); + throw std::runtime_error("CSbuffer and significant bits of y datatype don't match"); } - // adjust size of ydata - ydata_.resize(num_values); - // distinguish numeric datatypes included in "imc_datatype" - if ( datatp_ == 1 ) + if (dimension_ == 1) { - imc::convert_data_to_type(CSbuffer,ydata_); + // process y-data + process_data(ydata_, ynum_values, ydatatp_, yCSbuffer); + + // find appropriate precision for "xdata_" by means of "xstepwidth_" + xprec_ = (xstepwidth_ > 0 ) ? (int)ceil(fabs(log10(xstepwidth_))) : 10; + + // fill xdata_ + for ( unsigned long int i = 0; i < ynum_values; i++ ) + { + xdata_.push_back(xoffset_+(double)i*xstepwidth_); + } } - else if ( datatp_ == 2 ) + else if (dimension_ == 2) { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 3 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 4 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 5 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 6 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 7 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - else if ( datatp_ == 8 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); - } - // ... - else if ( datatp_ == 11 ) - { - imc::convert_data_to_type(CSbuffer,ydata_); + // process x- and y-data + std::vector xCSbuffer( buffer_->begin()+buffstrt+xbuffer_offset_+1, + buffer_->begin()+buffstrt+xbuffer_offset_+xbuffer_size_+1 ); + + // determine number of values in buffer + unsigned long int xnum_values = (unsigned long int)(xCSbuffer.size()/(xsignbits_/8)); + if ( xnum_values*(xsignbits_/8) != xCSbuffer.size() ) + { + throw std::runtime_error("CSbuffer and significant bits of x datatype don't match"); + } + if ( xnum_values != ynum_values ) + { + throw std::runtime_error("x and y data have different number of values"); + } + + process_data(xdata_, xnum_values, xdatatp_, xCSbuffer); + process_data(ydata_, ynum_values, ydatatp_, yCSbuffer); } else { - throw std::runtime_error(std::string("unsupported/unknown datatype") + std::to_string(datatp_)); - } - - // fill xdata_ - for ( unsigned long int i = 0; i < num_values; i++ ) - { - xdata_.push_back(xoffset_+(double)i*xstepwidth_); + throw std::runtime_error("unsupported dimension"); } // employ data transformation - if ( factor_ != 1.0 || offset_ != 0.0 ) + if (factor_ != 1.0 || offset_ != 0.0) { - for ( imc::datatype& el: ydata_ ) - { - //std::cout<<"value:"<& data_, size_t num_values, numtype datatp_, std::vector& CSbuffer) + { + // adjust size of data + data_.resize(num_values); + + // handle data type conversion + switch (datatp_) + { + case numtype::unsigned_byte: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::signed_byte: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::unsigned_short: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::signed_short: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::unsigned_long: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::signed_long: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::ffloat: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::ddouble: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::two_byte_word_digital: + imc::convert_data_to_type(CSbuffer, data_); + break; + case numtype::six_byte_unsigned_long: + imc::convert_data_to_type(CSbuffer, data_); + break; + default: + throw std::runtime_error(std::string("unsupported/unknown datatype ") + std::to_string(datatp_)); } } @@ -540,10 +602,10 @@ namespace imc <(ydata_,6,9,true)<<"\n" - <(xdata_,6,xprec_,true)<<"\n"; + <(xdata_,6,xprec_,true)<<"\n"; // <(ydata_,0,9,true) - <<",\"xdata\":"<(xdata_,0,xprec_,true); + <<",\"xdata\":"<(xdata_,0,xprec_,true); } // ss<<"\",\"aff. blocks\":\""<... > "imc Devices Transitional Recording" // typedf "Timestamp Ascii" typedef char16_t imc_digital; - // typedef < > imc_sixbyte "6byte unsigned long" + // + typedef struct { + unsigned char bytes[6]; + } imc_sixbyte; + class datatype { @@ -44,13 +48,14 @@ namespace imc imc_float sfloat_; // 6 imc_double sdouble_; // 7 imc_digital sdigital_; // 10 - short int dtidx_; // \in \{0,...,7,10\} + imc_sixbyte sixbyte_; // 13 + short int dtidx_; // \in \{0,...,7,10,13\} public: datatype(): ubyte_(0), sbyte_(0), ushort_(0), sshort_(0), ulint_(0), slint_(0), sfloat_(0.0), sdouble_(0.0), - sdigital_(0), + sdigital_(0), sixbyte_({0}), dtidx_(0) { }; // every supported datatype gets its own constructor datatype(imc_Ubyte num): ubyte_(num), dtidx_(0) {}; @@ -62,10 +67,13 @@ namespace imc datatype(imc_float num): sfloat_(num), dtidx_(6) {}; datatype(imc_double num): ubyte_(0), sbyte_(0), ushort_(0), sshort_(0), ulint_(0), slint_(0), sfloat_(0.0), sdouble_(num), - sdigital_(0), dtidx_(7) {}; + sdigital_(0), sixbyte_({0}), dtidx_(7) {}; datatype(imc_digital num): ubyte_(0), sbyte_(0), ushort_(0), sshort_(0), - ulint_(0), slint_(0), sfloat_(0.0), sdouble_(num), - sdigital_(num), dtidx_(10) {}; + ulint_(0), slint_(0), sfloat_(0.0), sdouble_(0.0), + sdigital_(num), sixbyte_({0}), dtidx_(10) {}; + datatype(imc_sixbyte num): ubyte_(0), sbyte_(0), ushort_(0), sshort_(0), + ulint_(0), slint_(0), sfloat_(0.0), sdouble_(0.0), + sdigital_(0), sixbyte_(num), dtidx_(13) {}; // identify type short int& dtype() { return dtidx_; } @@ -82,6 +90,7 @@ namespace imc this->sfloat_ = num.sfloat_; this->sdouble_ = num.sdouble_; this->sdigital_ = num.sdigital_; + this->sixbyte_ = num.sixbyte_; this->dtidx_ = num.dtidx_; } @@ -99,6 +108,7 @@ namespace imc this->sfloat_ = num.sfloat_; this->sdouble_ = num.sdouble_; this->sdigital_ = num.sdigital_; + this->sixbyte_ = num.sixbyte_; this->dtidx_ = num.dtidx_; } @@ -160,6 +170,12 @@ namespace imc this->dtidx_ = 10; return *this; } + datatype& operator=(const imc_sixbyte &num) + { + this->sixbyte_ = num; + this->dtidx_ = 13; + return *this; + } // obtain number as double double as_double() @@ -174,6 +190,13 @@ namespace imc else if ( dtidx_ == 6 ) num = (double)sfloat_; else if ( dtidx_ == 7 ) num = (double)sdouble_; else if ( dtidx_ == 10 ) num = static_cast(sdigital_); + else if ( dtidx_ == 13 ) { + unsigned long long value = 0; + for (int i = 0; i < 6; ++i) { + value |= static_cast(sixbyte_.bytes[i]) << (8 * i); + } + num = static_cast(value); + } return num; } @@ -189,6 +212,13 @@ namespace imc else if ( num.dtidx_ == 6 ) out<(num.sdigital_); + else if ( num.dtidx_ == 13 ) { + unsigned long long value = 0; + for (int i = 0; i < 6; ++i) { + value |= static_cast(num.sixbyte_.bytes[i]) << (8 * i); + } + out<(value); + } return out; } diff --git a/lib/imc_object.hpp b/lib/imc_object.hpp index cbf6415..0429d31 100644 --- a/lib/imc_object.hpp +++ b/lib/imc_object.hpp @@ -4,6 +4,7 @@ #define IMCOBJECT #include +#include #include "imc_key.hpp" //---------------------------------------------------------------------------// @@ -245,7 +246,7 @@ namespace imc // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { - if ( parameters.size() < 4 ) throw std::runtime_error("invalid number of parameters in CD2"); + if ( parameters.size() < 4 ) throw std::runtime_error("invalid number of parameters in CC"); component_index_ = std::stoi(get_parameter(buffer,¶meters[2])); analog_digital_ = ( std::stoi(get_parameter(buffer,¶meters[3])) == 2 ); } @@ -272,7 +273,9 @@ namespace imc imc_devices_transitional_recording, timestamp_ascii, two_byte_word_digital, - six_byte_unsigned_long + eight_byte_unsigned_long, + six_byte_unsigned_long, + eight_byte_signed_long }; // packaging information of component (corresponds to key CP) @@ -292,8 +295,8 @@ namespace imc { if ( parameters.size() < 10 ) throw std::runtime_error("invalid number of parameters in CP"); buffer_reference_ = std::stoi(get_parameter(buffer,¶meters[2])); - numeric_type_ = (numtype)std::stoi(get_parameter(buffer,¶meters[3])); - bytes_ = std::stoi(get_parameter(buffer,¶meters[4])); + bytes_ = std::stoi(get_parameter(buffer,¶meters[3])); + numeric_type_ = (numtype)std::stoi(get_parameter(buffer,¶meters[4])); signbits_ = std::stoi(get_parameter(buffer,¶meters[5])); mask_ = std::stoi(get_parameter(buffer,¶meters[6])); offset_ = std::stoul(get_parameter(buffer,¶meters[7])); @@ -336,7 +339,7 @@ namespace imc // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { - if ( parameters.size() < 13 ) throw std::runtime_error("invalid number of parameters in CD2"); + if ( parameters.size() < 13 ) throw std::runtime_error("invalid number of parameters in Cb"); number_buffers_ = std::stoul(get_parameter(buffer,¶meters[2])); bytes_userinfo_ = std::stoul(get_parameter(buffer,¶meters[3])); buffer_reference_ = std::stoul(get_parameter(buffer,¶meters[4])); @@ -378,7 +381,7 @@ namespace imc // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { - if ( parameters.size() < 8 ) throw std::runtime_error("invalid number of parameters in CD2"); + if ( parameters.size() < 8 ) throw std::runtime_error("invalid number of parameters in CR"); transform_ = (get_parameter(buffer,¶meters[2]) == std::string("1")); factor_ = std::stod(get_parameter(buffer,¶meters[3])); offset_ = std::stod(get_parameter(buffer,¶meters[4])); @@ -410,7 +413,7 @@ namespace imc // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { - if ( parameters.size() < 9 ) throw std::runtime_error("invalid number of parameters in CD2"); + if ( parameters.size() < 9 ) throw std::runtime_error("invalid number of parameters in CN"); group_index_ = std::stoul(get_parameter(buffer,¶meters[2])); index_bit_ = (get_parameter(buffer,¶meters[4]) == std::string("1")); name_ = get_parameter(buffer,¶meters[6]); @@ -439,7 +442,7 @@ namespace imc // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { - if ( parameters.size() < 4 ) throw std::runtime_error("invalid number of parameters in CD2"); + if ( parameters.size() < 4 ) throw std::runtime_error("invalid number of parameters in CS"); index_ = std::stoul(get_parameter(buffer,¶meters[2])); } @@ -454,6 +457,21 @@ namespace imc } }; + // language (corresponds to key NL) + struct language + { + std::string codepage_; + std::string language_code_; + + // construct members by parsing particular parameters from buffer + void parse(const std::vector* buffer, const std::vector& parameters) + { + if (parameters.size() < 4) throw std::runtime_error("invalid number of parameters in NL"); + codepage_ = get_parameter(buffer, ¶meters[2]); + language_code_ = get_parameter(buffer, ¶meters[3]); + } + }; + // origin of data (corresponds to key NO) struct origin_data { @@ -484,45 +502,30 @@ namespace imc // trigger timestamp (corresponds to key NT1) struct triggertime { - int day_, month_, year_; - int hour_, minute_; - double second_; - std::string timestamp_; + std::tm tms_; + double trigger_time_frac_secs_; // construct members by parsing particular parameters from buffer void parse(const std::vector* buffer, const std::vector& parameters) { if ( parameters.size() < 8 ) throw std::runtime_error("invalid number of parameters in CD2"); - day_ = std::stoi( get_parameter(buffer,¶meters[2]) ); - month_ = std::stoi( get_parameter(buffer,¶meters[3]) ); - year_ = std::stoi( get_parameter(buffer,¶meters[4]) ); - hour_ = std::stoi( get_parameter(buffer,¶meters[5]) ); - minute_ = std::stoi( get_parameter(buffer,¶meters[6]) ); - second_ = std::stod( get_parameter(buffer,¶meters[7]) ); - - //time_t rawtime; - //struct tm ts; - //time(&rawtime); - //localtime_r(&rawtime,&ts); - //ts.tm_mday = day_; - //ts.tm_mon = month_-1; - //ts.tm_year = year_-1900; - //ts.tm_hour = hour_; - //ts.tm_min = minute_; - //ts.tm_sec = (int)second_; - //asctime_r(&ts,×tamp_[0]); - timestamp_ = std::to_string(year_) + std::string("-") + std::to_string(month_) - + std::string("-") + std::to_string(day_) - + std::string("T") + std::to_string(hour_) - + std::string(":") + std::to_string(minute_) - + std::string(":") + std::to_string(second_); + tms_ = std::tm(); + tms_.tm_mday = std::stoi( get_parameter(buffer,¶meters[2]) ); + tms_.tm_mon = std::stoi( get_parameter(buffer,¶meters[3]) ) - 1; + tms_.tm_year = std::stoi( get_parameter(buffer,¶meters[4]) ) - 1900; + tms_.tm_hour = std::stoi( get_parameter(buffer,¶meters[5]) ); + tms_.tm_min = std::stoi( get_parameter(buffer,¶meters[6]) ); + long double secs = std::stold( get_parameter(buffer,¶meters[7]) ); + double secs_int; + trigger_time_frac_secs_ = modf((double)secs,&secs_int); + tms_.tm_sec = (int)secs_int; } // get info string std::string get_info(int width = 20) { std::stringstream ss; - ss<CCuuid_ = blk.get_uuid(); + compenv_ptr->uuid_ = compenv_ptr->CCuuid_; + } + else if ( blk.get_key().name_ == "CD" ) + { + if (compenv_ptr == nullptr) chnenv.CDuuid_ = blk.get_uuid(); + else compenv_ptr->CDuuid_ = blk.get_uuid(); + } + else if ( blk.get_key().name_ == "NT" ) + { + if (compenv_ptr == nullptr) chnenv.NTuuid_ = blk.get_uuid(); + else compenv_ptr->NTuuid_ = blk.get_uuid(); + } + else if ( blk.get_key().name_ == "Cb" ) compenv_ptr->Cbuuid_ = blk.get_uuid(); + else if ( blk.get_key().name_ == "CP" ) compenv_ptr->CPuuid_ = blk.get_uuid(); + else if ( blk.get_key().name_ == "CR" ) compenv_ptr->CRuuid_ = blk.get_uuid(); + + // check for currently associated channel + // TODO: CNuuid is not unique for multichannel data if ( !chnenv.CNuuid_.empty() ) { - // any component/channel is closed by any of {CS, CC, CG, CB} - if ( blk.get_key().name_ == "CS" || blk.get_key().name_ == "CC" - || blk.get_key().name_ == "CG" || blk.get_key().name_ == "CB" ) + // at the moment only a single channel is supported + // any channel is closed by any of {CB, CG, CI, CT, CS} + if ( blk.get_key().name_ == "CB" || blk.get_key().name_ == "CG" + || blk.get_key().name_ == "CI" || blk.get_key().name_ == "CT" + || blk.get_key().name_ == "CS" ) { // provide UUID for channel + // for multi component channels exactly one CN is available chnenv.uuid_ = chnenv.CNuuid_; // for multichannel data there may be multiple channels referring to @@ -255,8 +287,15 @@ namespace imc ); // reset channel uuid - chnenv.reset(); - //chnenv.CNuuid_.clear(); + chnenv.CNuuid_.clear(); + + chnenv.CBuuid_.clear(); + chnenv.CGuuid_.clear(); + chnenv.CIuuid_.clear(); + chnenv.CTuuid_.clear(); + chnenv.CSuuid_.clear(); + + compenv_ptr = nullptr; } } @@ -264,7 +303,8 @@ namespace imc // already belong to NEXT component if ( blk.get_key().name_ == "CB" ) chnenv.CBuuid_ = blk.get_uuid(); else if ( blk.get_key().name_ == "CG" ) chnenv.CGuuid_ = blk.get_uuid(); - else if ( blk.get_key().name_ == "CC" ) chnenv.CCuuid_ = blk.get_uuid(); + else if ( blk.get_key().name_ == "CI" ) chnenv.CIuuid_ = blk.get_uuid(); + else if ( blk.get_key().name_ == "CT" ) chnenv.CTuuid_ = blk.get_uuid(); } } diff --git a/python/VERSION b/python/VERSION index d17d1f3..7ec1d6d 100644 --- a/python/VERSION +++ b/python/VERSION @@ -1 +1 @@ -2.0.20 +2.1.0