#include "adccluster_device.h" ADCCluster_device::ADCCluster_device(QObject *parent) : gtl::hw::device(parent), _slavesADC(new QList()), _adcs(new QMap), _config(new QJsonObject()), _state(ADCCluster_ns::clusterState::IDLE), _rrdStack(new RRDStack()), _isMasterAllreadyInited(false), _currentSingleStack(new singleStack(0, ADC_ns::bitDepth::BIT16, new QList(), 0)), _singleQueue(new QQueue()), _clusterQueue(new QQueue()), _singleMode(true), _initError(false) { } ADCCluster_device::~ADCCluster_device() { #ifdef CLUSTER_DEBUG qDebug() << "cluster desctructor"; #endif stop(); } void ADCCluster_device::restart() { } ADC *ADCCluster_device::_initMasterADC(QList * adcSNs) { int __masterSN = adcSNs->at(0); ADC * __masterADC = new ADC(__masterSN); QObject::connect(__masterADC, &ADC::ADC_connected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "master adc connected" << __masterSN; #endif }); QObject::connect(__masterADC, &ADC::ADC_disconnected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "master adc disconnected" << __masterSN; #endif _destroySlaves(); // hw _device->set_name("ADCCluster [MASTER DISCONNECTED]"); // hw _state = ADCCluster_ns::clusterState::CONFIG; }); QObject::connect(__masterADC, &ADC::ADC_started, [=]() { _rrdStack = new RRDStack(); _state = ADCCluster_ns::clusterState::RUNNING; __masterADC->setDataCounter(0); _device->set_name("ADCCluster [RUNNING]"); }); QObject::connect(__masterADC, &ADC::ADC_configReadingFinished, [=]() { #ifdef CLUSTER_DEBUG _debugPrintADCParams(__masterADC); #endif if (__masterADC->getModelID() == 0) { // TODO критериии некорректной инициализации #ifdef CLUSTER_DEBUG qDebug() << "init failed"; #endif return; } for (int __slaveID = 1; __slaveID < adcSNs->count(); __slaveID++) { ADC * __slave = _initSlaveADC(adcSNs->at(__slaveID), __slaveID); _slavesADC->append(__slave); __slave->start(); } // hw _device->set_name("ADCCluster [WAITING SLAVES]"); // hw for (int __i=0; __i<_slavesADC->count(); __i++) { ADC * __slave = _slavesADC->at(__i); QObject::connect(__slave, &ADC::ADC_disconnected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "slave adc disconnected" << __slave->getSN(); #endif // hw _device->set_name("ADCCluster [SLAVE DISONNECTED]"); // hw _state = ADCCluster_ns::clusterState::CONFIG; if (__masterADC->getADCState() == ADC_ns::ADCState::RUNNING) { __masterADC->stopADC(); } _stopSlaves(); }); QObject::connect(__slave, &ADC::ADC_started, [=]{ bool __allReady = true; for (int __i = 0; __i < _slavesADC->count(); __i++) { if (_slavesADC->at(__i)->getADCState() != ADC_ns::ADCState::RUNNING) { __allReady = false; } if (_slavesADC->at(__i)->getADCState() == ADC_ns::ADCState::WAITING_COMMAND) { _slavesADC->at(__i)->startADC(ADC_ns::SYNCMode::SLAVE); } if (_slavesADC->at(__i)->getModelID() != __masterADC->getModelID()) { __allReady = false; _state = ADCCluster_ns::clusterState::CONFIG; _device->set_name("ADCCluster [SLAVES INCOMPATIBILITY]"); } } if (__allReady) { if (!_isMasterAllreadyInited) { // hw api _rate = __masterADC->getFreq(); _device->set_rate(__masterADC->getFreq()); _device->set_id("ADCCluster"); _device->set_name("ADCCluster [STARTING CLUSTER]"); _count_ai = (_slavesADC->count() + 1) * (__masterADC->getChannelsCount() + __masterADC->getIsTachoSignal()); set_ai(); for (int __i = 0; __i < _count_ai; __i++) { int __adcNo = __i / (__masterADC->getChannelsCount() + __masterADC->getIsTachoSignal()); int __channelNo = __i % (__masterADC->getChannelsCount() + __masterADC->getIsTachoSignal()); int __adcSN = 0; if (__adcNo == 0) { __adcSN = __masterADC->getSN(); } else { __adcSN = _slavesADC->at(__adcNo - 1)->getSN(); } QString __prefix = QString::number(__adcSN); if (__channelNo == __masterADC->getChannelsCount()) { ai(__i)->set_name(__prefix + " [ pulse ]"); } else { ai(__i)->set_name(__prefix + " [ " + QString::number(__channelNo) + " ]"); } } // hw api _isMasterAllreadyInited = true; } __masterADC->startADC(ADC_ns::SYNCMode::MASTER); } }); } }); QObject::connect(__masterADC, &ADC::ADC_dataPacketReceived, [=](QByteArray packet) { trans_ns::bytes2long __num; __num.bytes.LL = packet[0]; __num.bytes.LH = packet[1]; __num.bytes.HL = packet[2]; __num.bytes.HH = packet[3]; if (_masterADC->getDataCounter() != __num.twinWord) { #ifdef CLUSTER_DEBUG qDebug() << "propusk: " << _masterADC->getSN() << _masterADC->getDataCounter() << " : " << __num.twinWord << " packets lost = " << __num.twinWord - _masterADC->getDataCounter(); #endif _masterADC->setDataCounter(__num.twinWord); } _masterADC->incDataCounter(); clusterStack * __currentStack = _rrdStack->getStackByPacketNumber(__num.twinWord); if (__currentStack == nullptr) { __currentStack = new clusterStack(45 * (int)(__num.twinWord / 45), _masterADC->getBitDeph(), _masterADC->getChannelsConfig(), _masterADC->getSamplesCount(), _slavesADC); _clusterQueue->enqueue(_rrdStack->pushStack(__currentStack)); } int __packetIndex = __num.twinWord - __currentStack->getFirstPacketIndex(); __currentStack->insert(0, __packetIndex, packet); }); return __masterADC; } void ADCCluster_device::_stopSlaves() { foreach(ADC * __slave, *_slavesADC) { if (__slave->getADCState() == ADC_ns::ADCState::RUNNING){ __slave->stopADC(); } } } void ADCCluster_device::_destroySlaves() { while (!_slavesADC->isEmpty()) { ADC * __slave = _slavesADC->takeAt(0); __slave->stop(); delete __slave; } } ADC * ADCCluster_device::_initSlaveADC(uint16_t sn, int adcNo) { ADC * __slaveADC = new ADC(sn); QObject::connect(__slaveADC, &ADC::ADC_connected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "slave adc connected" << sn; #endif }); QObject::connect(__slaveADC, &ADC::ADC_configReadingFinished, [=]() { #ifdef CLUSTER_DEBUG _debugPrintADCParams(__slaveADC); #endif if (__slaveADC->getModelID() == 0) { // TODO критериии некорректной инициализации #ifdef CLUSTER_DEBUG qDebug() << "init failed"; #endif //emit status_changed(fail); return; } __slaveADC->startADC(ADC_ns::SYNCMode::SLAVE); }); QObject::connect(__slaveADC, &ADC::ADC_dataPacketReceived, [=](QByteArray packet) { trans_ns::bytes2long __num; __num.bytes.LL = packet[0]; __num.bytes.LH = packet[1]; __num.bytes.HL = packet[2]; __num.bytes.HH = packet[3]; if (__slaveADC->getDataCounter() != __num.twinWord) { #ifdef CLUSTER_DEBUG qDebug() << "propusk: " << __slaveADC->getSN() << __slaveADC->getDataCounter() << " : " << __num.twinWord << " packets lost = " << __num.twinWord - __slaveADC->getDataCounter(); #endif __slaveADC->setDataCounter(__num.twinWord); } __slaveADC->incDataCounter(); clusterStack * __currentStack = _rrdStack->getStackByPacketNumber(__num.twinWord); if (__currentStack == nullptr) { __currentStack = new clusterStack(45 * (int)(__num.twinWord / 45), _masterADC->getBitDeph(), _masterADC->getChannelsConfig(), _masterADC->getSamplesCount(), _slavesADC); _clusterQueue->enqueue(_rrdStack->pushStack(__currentStack)); } int __packetIndex = __num.twinWord - __currentStack->getFirstPacketIndex(); __currentStack->insert(adcNo, __packetIndex, packet); }); return __slaveADC; } void ADCCluster_device::_runSingleMode() { int __samplesCount = _singleADC->getSamplesCount(); int __clusterPacketSize = 45; int __outputChannelsCount = _singleADC->getChannelsCount() + (int)_singleADC->getIsTachoSignal(); int __tachoCannelIndex = _singleADC->getChannelsCount(); int __oneBufferSize = __clusterPacketSize * __samplesCount * __outputChannelsCount; QQueue __temp; while (!_singleQueue->isEmpty()) { __temp.enqueue(_singleQueue->dequeue()); } if (__temp.count() == 0) return; _buffer_read.resize(__oneBufferSize * __temp.count()); for (int __i = 0; __i < __oneBufferSize * __temp.count(); __i++) { _buffer_read[__i] = 0; } int __counter = 0; while (!__temp.isEmpty()) { singleStack * __clusterPacket = __temp.dequeue(); for (int __packetNo = 0; __packetNo < __clusterPacketSize; __packetNo++) { for (int __sampleNo = 0; __sampleNo < __samplesCount; __sampleNo++) { // номер пакета * количество отсчетов * количество каналов + количество каналов * номер отсчета int __samplePosition = __outputChannelsCount * (__packetNo * __samplesCount + __sampleNo); for (int __channelIndex = 0; __channelIndex < _singleADC->getChannelsCount(); __channelIndex++) { // количество отсчетов * номер канала + порядковый номер отсчета _buffer_read[__oneBufferSize * __counter + __samplePosition + __channelIndex] = __clusterPacket->getValue(__packetNo, __channelIndex, __sampleNo); } if (_singleADC->getIsTachoSignal()) { _buffer_read[__oneBufferSize * __counter + __samplePosition + __tachoCannelIndex] = __clusterPacket->getTachoValue(__packetNo, __sampleNo) ? 1.0 : 0.0; } } } delete __clusterPacket; __counter++; } send_data(); } void ADCCluster_device::_runClusterMode() { int __adcCount = _slavesADC->count() + 1; // '1' это мастер int __aiCount = _masterADC->getChannelsCount(); //int __samplesCount = 333; int __samplesCount = _masterADC->getSamplesCount(); int __clusterPacketSize = 45; int __outputChannelsCount = (_masterADC->getChannelsCount() + _masterADC->getIsTachoSignal()) * (_slavesADC->count() + 1); int __oneBufferSize = __clusterPacketSize * __samplesCount * __outputChannelsCount; QQueue __snapshotQueue; while (!_clusterQueue->isEmpty()) { clusterStack * __stackTemp = _clusterQueue->dequeue(); if (__stackTemp!=nullptr) __snapshotQueue.enqueue(__stackTemp); } if (__snapshotQueue.count() == 0) return; _buffer_read.resize(__oneBufferSize * __snapshotQueue.count()); for (int __i = 0; __i < __oneBufferSize * __snapshotQueue.count(); __i++) { _buffer_read[__i] = 0; } int __counter = 0; while (!__snapshotQueue.isEmpty()) { clusterStack * __clusterPacket = __snapshotQueue.dequeue(); for (int __packetNo = 0; __packetNo < __clusterPacketSize; __packetNo++) { for (int __sampleNo = 0; __sampleNo < __samplesCount; __sampleNo++) { // номер пакета * количество отсчетов * количество каналов + количество каналов * номер отсчета int __samplePosition = __outputChannelsCount * (__packetNo * __samplesCount + __sampleNo); int __offset = 0; for (int __adcNo = 0; __adcNo < __adcCount; __adcNo++) { for (int __channelIndex = 0; __channelIndex < __aiCount; __channelIndex++) { // количество отсчетов * номер канала + порядковый номер отсчета if (__oneBufferSize * __counter + __samplePosition + __offset > _buffer_read.size()) { qDebug() << __oneBufferSize * __counter + __samplePosition + __offset; } _buffer_read[__oneBufferSize * __counter + __samplePosition + __offset] = __clusterPacket->getValue(__adcNo, __packetNo, __channelIndex, __sampleNo); __offset++; } if (_masterADC->getIsTachoSignal()) { _buffer_read[__oneBufferSize * __counter + __samplePosition + __offset] = __clusterPacket->getTachoValue(__adcNo, __packetNo, __sampleNo) ? 1.0 : 0.0; // TODO tacho __offset++; } } } } delete __clusterPacket; __counter++; } send_data(); } void ADCCluster_device::_debugPrintADCParams(ADC *adc) { qDebug() << "Model id: " << adc->getModelID(); qDebug() << "Device sn: " << adc->getSN(); qDebug() << "DHCP mode: " << adc->getIsDHCPMode(); qDebug() << "MAC address: " << adc->getMacAddress().toHex('-'); qDebug() << "Default address: " << adc->getDefaultIP().toString(); qDebug() << "Default gate: " << adc->getDefaultGate().toString(); qDebug() << "Default mask: " << adc->getDefaultMask().toString(); qDebug() << "Static address: " << adc->getStaticIP().toString(); qDebug() << "Static gate: " << adc->getStaticGate().toString(); qDebug() << "Static mask: " << adc->getStaticMask().toString(); qDebug() << "Channels count: " << adc->getChannelsCount(); qDebug() << "Bit depth: " << (adc->getBitDeph() == ADC_ns::bitDepth::BIT16 ? "16" : "24"); for (int i=0; i< adc->getChannelsConfig()->count(); i++) { qDebug() << "Channel " << i << " Factor: " << adc->getChannelsConfig()->at(i)->getFactor(); } qDebug() << "Is tacho signal: " << adc->getIsTachoSignal(); qDebug() << "Is gen: " << adc->getIsGen(); qDebug() << "ADC freq: " << adc->getFreq(); } void ADCCluster_device::_stateChanged(gtl::hw::device::ADCState state) { emit status_changed(state); } void ADCCluster_device::ai_iepe_changed() { if (_singleMode) { for (int __i = 0; __i < _count_ai; __i++) { if (ai(__i) == sender()) { #ifdef CLUSTER_DEBUG qDebug() << "single mode: iepe changed: channel: " << __i << "to:" << ai(__i)->is_iepe(); #endif _singleADC->setChannelIEPE(__i, ai(__i)->is_iepe()); } } } else { for (int __i = 0; __i < _count_ai; __i++) { if (ai(__i) == sender()) { int __adcIndex = __i / (_masterADC->getChannelsCount() + _masterADC->getIsTachoSignal()); int __channelIndex = __i % (_masterADC->getChannelsCount() + _masterADC->getIsTachoSignal()); bool __IPEPEnable = ai(__i)->is_iepe(); if (__adcIndex == 0) { // master #ifdef CLUSTER_DEBUG qDebug() << "cluster iepe changed: master"; qDebug() << "cluster iepe changed: ADC SN: " << _masterADC->getSN(); qDebug() << "cluster iepe changed: channel: " << __channelIndex; qDebug() << "cluster iepe changed: " << __IPEPEnable; #endif _masterADC->setChannelIEPE(__channelIndex, __IPEPEnable); } else { // slave __adcIndex = __adcIndex - 1; #ifdef CLUSTER_DEBUG qDebug() << "cluster iepe changed: slave index: " << __adcIndex; qDebug() << "cluster iepe changed: ADC SN: " << _slavesADC->at(__adcIndex)->getSN(); qDebug() << "cluster iepe changed: channel: " << __channelIndex; qDebug() << "cluster iepe changed: " << __IPEPEnable; #endif _slavesADC->at(__adcIndex)->setChannelIEPE(__channelIndex, __IPEPEnable); } } } } } void ADCCluster_device::ai_coupling_changed() { if (_singleMode) { for (int __i = 0; __i < _count_ai; __i++) { if (ai(__i) == sender()) { #ifdef CLUSTER_DEBUG qDebug() << "single mode: channel coupling changed: channel: " << __i << "to:" << ai(__i)->is_coupling(); #endif if (ai(__i)->is_coupling()) { _singleADC->setChannelMODE(__i, ADC_ns::channelMode::AC); } else { _singleADC->setChannelMODE(__i, ADC_ns::channelMode::ACDC); } } } } else { for (int __i = 0; __i < _count_ai; __i++) { if (ai(__i) == sender()) { int __adcIndex = __i / (_masterADC->getChannelsCount() + _masterADC->getIsTachoSignal()); int __channelIndex = __i % (_masterADC->getChannelsCount() + _masterADC->getIsTachoSignal()); bool __couplingEnable = ai(__i)->is_coupling(); if (__adcIndex == 0) { // master #ifdef CLUSTER_DEBUG qDebug() << "cluster coupling changed: master"; qDebug() << "cluster coupling changed: ADC SN: " << _masterADC->getSN(); qDebug() << "cluster coupling changed: channel: " << __channelIndex; qDebug() << "cluster coupling changed: " << __couplingEnable; #endif if (ai(__i)->is_coupling()) { _masterADC->setChannelMODE(__channelIndex, ADC_ns::channelMode::AC); } else { _masterADC->setChannelMODE(__channelIndex, ADC_ns::channelMode::ACDC); } } else { // slave __adcIndex = __adcIndex - 1; #ifdef CLUSTER_DEBUG qDebug() << "cluster coupling changed: slave index: " << __adcIndex; qDebug() << "cluster coupling changed: ADC SN: " << _slavesADC->at(__adcIndex)->getSN(); qDebug() << "cluster coupling changed: channel: " << __channelIndex; qDebug() << "cluster coupling changed: " << __couplingEnable; #endif if (ai(__i)->is_coupling()) { _slavesADC->at(__adcIndex)->setChannelMODE(__channelIndex, ADC_ns::channelMode::AC); } else { _slavesADC->at(__adcIndex)->setChannelMODE(__channelIndex, ADC_ns::channelMode::ACDC); } } } } } } ADC *ADCCluster_device::_initSingleADC(uint16_t sn) { ADC * __singleADC = new ADC(sn); QObject::connect(__singleADC, &ADC::ADC_connected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "single adc connected" << sn; #endif }); QObject::connect(__singleADC, &ADC::ADC_disconnected, [=]() { #ifdef CLUSTER_DEBUG qDebug() << QTime::currentTime().toString() << "single adc disconnected"; #endif // hw api _count_ai = 0; set_ai(); _stateChanged(gtl::hw::device::ADCState::FAILED); // hw api }); QObject::connect(__singleADC, &ADC::ADC_started, [=](){ _state = ADCCluster_ns::clusterState::RUNNING; _stateChanged(gtl::hw::device::ADCState::OK); }); QObject::connect(__singleADC, &ADC::ADC_configReadingFinished, [=]() { // TODO применить загруженные из XML настройки и как-то передать их в ADC // и вызвать ещё раз load - т.к. мы только сейчас знаем какие настойки #ifdef CLUSTER_DEBUG _debugPrintADCParams(__singleADC); #endif if (__singleADC->getModelID() == 0) { // TODO критериии некорректной инициализации #ifdef CLUSTER_DEBUG qDebug() << "init failed"; #endif _stateChanged(gtl::hw::device::ADCState::INIT_FAILED); return; } // hw api _rate = __singleADC->getFreq(); _device->set_rate(__singleADC->getFreq()); _count_ai = __singleADC->getChannelsCount() + (int)__singleADC->getIsTachoSignal(); set_ai(); for (int __i = 0; __i < __singleADC->getChannelsCount(); __i++) { ai(__i)->set_name("input [" + QString::number(__i) + "]"); } if (__singleADC->getIsTachoSignal()) ai(__singleADC->getChannelsCount())->set_name("pulse"); // hw api __singleADC->startADC(ADC_ns::SYNCMode::MASTER); }); QObject::connect(__singleADC, &ADC::ADC_dataPacketReceived, [=](QByteArray packet) { trans_ns::bytes2long __num; __num.bytes.LL = packet[0]; __num.bytes.LH = packet[1]; __num.bytes.HL = packet[2]; __num.bytes.HH = packet[3]; int __packetIndex = __num.twinWord - _currentSingleStack->getFirstPacketIndex(); if (__num.twinWord - _currentSingleStack->getFirstPacketIndex() > 44) { _singleQueue->enqueue(_currentSingleStack); _currentSingleStack = new singleStack(__num.twinWord, __singleADC->getBitDeph(), __singleADC->getChannelsConfig(), __singleADC->getSamplesCount()); _currentSingleStack->insert(__packetIndex % 45, packet); } else { _currentSingleStack->insert(__packetIndex, packet); } if (__singleADC->getDataCounter() != __num.twinWord) { #ifdef CLUSTER_DEBUG qDebug() << "propusk: " << __singleADC->getSN() << __singleADC->getDataCounter() << " : " << __num.twinWord << " packets lost = " << __num.twinWord - __singleADC->getDataCounter(); #endif __singleADC->setDataCounter(__num.twinWord); } __singleADC->incDataCounter(); }); // hw api _device->set_name("S_" + QString::number(sn)); _device->set_id(QString::number(sn)); _id = QString::number(sn); _stateChanged(gtl::hw::device::ADCState::INIT_IN_PROGRESS); // hw api return __singleADC; } bool ADCCluster_device::start(QString id, qreal rate) { #ifdef CLUSTER_DEBUG qDebug() << "external cluster start: " << id; #endif bool __idIsDigit; uint16_t __sn = id.toInt(&__idIsDigit); if (__idIsDigit) { // TODO вычитать настройки из XML и применить их _state = ADCCluster_ns::clusterState::CONFIG; _id = id; #ifdef CLUSTER_DEBUG qDebug() << "cluster in simple mode"; #endif _singleADC = _initSingleADC(__sn); _singleADC->start(); _singleMode = true; } else { _state = ADCCluster_ns::clusterState::CONFIG; _id = id; #ifdef CLUSTER_DEBUG qDebug() << "cluster in extended mode"; #endif _device->set_name("ADCCluster [starting...]"); QList * __SNs = new QList(); foreach(QString __subString, id.split(',')) { bool __snCheck; int __ADCsn = __subString.toInt(&__snCheck); if (__snCheck) __SNs->append(__ADCsn); } if (__SNs->count() == 0) { _initError = true; return false; } _masterADC = _initMasterADC(__SNs); _masterADC->start(); _singleMode = false; } QThread::start(QThread::HighestPriority); return true; } bool ADCCluster_device::stop() { if (_initError) return true; if (_state != ADCCluster_ns::clusterState::IDLE) { if (_singleMode) { _state = ADCCluster_ns::clusterState::IDLE; msleep(110); _singleADC->stop(); delete(_singleADC); } else { _state = ADCCluster_ns::clusterState::IDLE; _isMasterAllreadyInited = false; msleep(110); _masterADC->stop(); delete(_masterADC); while (_slavesADC->count() > 0) { ADC * __slave =_slavesADC->takeAt(0); __slave->stop(); msleep(110); delete(__slave); } } } return true; } void ADCCluster_device::run() { while (_state != ADCCluster_ns::clusterState::IDLE) { if (_state == ADCCluster_ns::clusterState::RUNNING) { if (_singleMode) { _runSingleMode(); } else { _runClusterMode(); } } msleep(150); } } void ADCCluster_device::send_data() { set_ai_data(&_buffer_read[0], (int)_buffer_read.size()); emit received_data(); }