DoocsIfff.cc 6.49 KiB
#include "DoocsIfff.h"
#include "DoocsUpdater.h"
#include <ChimeraTK/Exception.h>
#include <ChimeraTK/OneDRegisterAccessor.h>
#include <ChimeraTK/ScalarRegisterAccessor.h>
#include <doocs/EventId.h>
namespace ChimeraTK {
DoocsIfff::DoocsIfff(EqFct* eqFct, std::string const& doocsPropertyName,
boost::shared_ptr<NDRegisterAccessor<int>> const& i1Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f1Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f2Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f3Value, DoocsUpdater& updater)
: D_ifff(eqFct, doocsPropertyName), _i1Value(i1Value), _f1Value(f1Value), _f2Value(f2Value), _f3Value(f3Value),
_updater(updater), _eqFct(eqFct), isWriteable(_i1Value->isWriteable() && _f1Value->isWriteable() &&
_f2Value->isWriteable() && _f3Value->isWriteable()) {
checkSourceConsistency();
registerIfffSources();
}
// Constructor without history
DoocsIfff::DoocsIfff(std::string const& doocsPropertyName, EqFct* eqFct,
boost::shared_ptr<NDRegisterAccessor<int>> const& i1Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f1Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f2Value,
boost::shared_ptr<NDRegisterAccessor<float>> const& f3Value, DoocsUpdater& updater)
: D_ifff(doocsPropertyName, eqFct), _i1Value(i1Value), _f1Value(f1Value), _f2Value(f2Value), _f3Value(f3Value),
_updater(updater), _eqFct(eqFct), isWriteable(_i1Value->isWriteable() && _f1Value->isWriteable() &&
_f2Value->isWriteable() && _f3Value->isWriteable()) {
checkSourceConsistency();
registerIfffSources();
}
void DoocsIfff::checkSourceConsistency() {
bool areAllSourcesReadable =
(_i1Value->isReadable() && _f1Value->isReadable() && _f2Value->isReadable() && _f3Value->isReadable());
if(not areAllSourcesReadable) {
ChimeraTK::logic_error("Doocs Adapter IFFF configuration Error: not all IFFF sources are readable");
}
bool areAllSourcesWritable =
(_i1Value->isWriteable() && _f1Value->isWriteable() && _f2Value->isWriteable() && _f3Value->isWriteable());
if(not areAllSourcesWritable) {
ChimeraTK::logic_error("Doocs Adapter IFFF configuration Error: not all IFFF sources are writable");
}
}
void DoocsIfff::registerIfffSources() {
registerVariable(OneDRegisterAccessor<int>(_i1Value));
registerVariable(OneDRegisterAccessor<float>(_f1Value));
registerVariable(OneDRegisterAccessor<float>(_f2Value));
registerVariable(OneDRegisterAccessor<float>(_f3Value));
}
void DoocsIfff::updateAppToDoocs(TransferElementID& elementId) {
if(!_consistencyGroup.update(elementId)) {
return;
}
if(_i1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
_f1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
_f2Value->dataValidity() != ChimeraTK::DataValidity::ok ||
_f3Value->dataValidity() != ChimeraTK::DataValidity::ok) {
this->d_error(stale_data);
}
else {
this->d_error(no_error);
}
IFFF ifff;
ifff.i1_data = _i1Value->accessData(0);
ifff.f1_data = _f1Value->accessData(0);
ifff.f2_data = _f2Value->accessData(0);
ifff.f3_data = _f3Value->accessData(0);
doocs::Timestamp timestamp(_i1Value->getVersionNumber().getTime());
// update global time stamp of DOOCS, but only if our time stamp is newer
if(get_global_timestamp() < timestamp) {
set_global_timestamp(timestamp);
}
if(this->get_histPointer()) {
/*
doocs::EventId eventId =
(_macroPulseNumberSource) ? doocs::EventId(_macroPulseNumberSource->accessData(0)) : doocs::EventId(0);
*/
/*FIXME: The archiver also has a status code. Set it correctly.*/
/*FIXME: This set_and_archive does not support the timestamp yet (only sec and msec, and I guess m is milli?)*/
/*FIXME: This set_and_archive does not support eventIDs yet */
this->set_and_archive(&ifff, ArchiveStatus::sts_ok, 0, 0 /*msec*/);
}
else {
this->set_value(&ifff);
}
auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch();
auto seconds = sinceEpoch.seconds;
auto microseconds = sinceEpoch.microseconds;
this->set_tmstmp(seconds, microseconds);
if(_macroPulseNumberSource) this->set_mpnum(_macroPulseNumberSource->accessData(0));
if(_publishZMQ) {
dmsg_info info;
memset(&info, 0, sizeof(info));
info.sec = seconds;
info.usec = microseconds;
if(_macroPulseNumberSource != nullptr) {
info.ident = _macroPulseNumberSource->accessData(0);
}
else {
info.ident = 0;
}
this->send(&info);
}
}
void DoocsIfff::set(EqAdr* eqAdr, EqData* data1, EqData* data2, EqFct* eqFct) {
D_ifff::set(eqAdr, data1, data2, eqFct); // inherited functionality fill the local doocs buffer
sendToApplication();
}
void DoocsIfff::auto_init(void) {
D_ifff::auto_init(); // inherited functionality fill the local doocs buffer
if(isWriteable) {
sendToApplication();
}
}
void DoocsIfff::sendToApplication() {
IFFF* ifff = value();
_i1Value->accessData(0) = ifff->i1_data;
_f1Value->accessData(0) = ifff->f1_data;
_f2Value->accessData(0) = ifff->f2_data;
_f3Value->accessData(0) = ifff->f3_data;
// write all with the same version number
VersionNumber v = {};
_i1Value->write(v);
_f1Value->write(v);
_f2Value->write(v);
_f3Value->write(v);
}
void DoocsIfff::setMacroPulseNumberSource(
boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource) {
// FIXME: Assuming macroPulseNumberSource is relavent only when all 4
// components are readable; correct behavior later if this assumption
// does not hold.
bool isIfffReadable =
(_i1Value->isReadable() && _f1Value->isReadable() && _f2Value->isReadable() && _f3Value->isReadable());
if(not isIfffReadable) {
return;
}
_macroPulseNumberSource = macroPulseNumberSource;
if(_consistencyGroup.getMatchingMode() != DataConsistencyGroup::MatchingMode::none) {
registerVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(_macroPulseNumberSource));
}
}
void DoocsIfff::registerVariable(const ChimeraTK::TransferElementAbstractor& var) {
if(var.isReadable()) {
_updater.addVariable(var, _eqFct, std::bind(&DoocsIfff::updateAppToDoocs, this, var.getId()));
_consistencyGroup.add(var);
}
}
} // namespace ChimeraTK