#include "piprotocol.h" PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_) { init(); protName = name; PIConfig conf(config, PIFile::Read); if (!conf.isOpened()) { cout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl; devReceiverState = devSenderState = "Config error"; return; } int ps; bool ok; PIFlags pp; PIConfig::Entry b = conf.getValue(name), rb = b.getValue("receiver"), sb = b.getValue("sender"); PIString dev; /// receiver section if (rb.isEntryExists("ip") && rb.isEntryExists("device")) { cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl; devReceiverState = "Config error"; return; } dev = rb.getValue("ip", "", &ok); if (ok) { ps = rb.getValue("port", 0, &ok); if (!ok) { cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" in \"" << config << "\"!" << endl; devReceiverState = "Config error"; return; } type_rec = PIProtocol::Ethernet; eth = new PIEthernet(dev, ps, this, receiveEvent); setReceiverAddress(dev, ps); } dev = rb.getValue("device", "", &ok); if (ok) { ps = rb.getValue("speed", 0, &ok); if (!ok) { cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" in \"" << config << "\"!" << endl; devReceiverState = "Config error"; return; } if (rb.getValue("parity", false)) pp |= PISerial::ParityControl; if (rb.getValue("twoStopBits", false)) pp |= PISerial::TwoStopBits; type_rec = PIProtocol::Serial; type_send = PIProtocol::Serial; ser = new PISerial(dev, this, receiveEvent); setReceiverDevice(dev, (PISerial::Speed)ps); setSenderDevice(dev, (PISerial::Speed)ps); ser->setInSpeed((PISerial::Speed)ps); ser->setParameters(pp); ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize); } setExpectedFrequency(rb.getValue("frequency", -1.f)); /// sender section if (sb.isEntryExists("ip") && sb.isEntryExists("device")) { cout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl; devSenderState = "Config error"; return; } dev = sb.getValue("ip", "", &ok); if (ok) { ps = sb.getValue("port", 0, &ok); if (!ok) { cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" in \"" << config << "\"!" << endl; devSenderState = "Config error"; return; } type_send = PIProtocol::Ethernet; if (eth == 0) eth = new PIEthernet(dev, ps, this, receiveEvent); setSenderAddress(dev, ps); } dev = sb.getValue("device", "", &ok); if (ok) { ps = sb.getValue("speed", 0, &ok); if (!ok) { cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" in \"" << config << "\"!" << endl; devSenderState = "Config error"; return; } if (sb.getValue("parity", false)) pp |= PISerial::ParityControl; if (sb.getValue("twoStopBits", false)) pp |= PISerial::TwoStopBits; type_send = PIProtocol::Serial; if (ser == 0) ser = new PISerial(dev, this, receiveEvent); setSenderDevice(dev, (PISerial::Speed)ps); ser->setOutSpeed((PISerial::Speed)ps); ser->setParameters(pp); ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize); } setSenderFrequency(sb.getValue("frequency", -1.f)); headerPtr = (uchar * )recHeaderPtr; headerSize = recHeaderSize; dataPtr = (uchar * )recDataPtr; dataSize = recDataSize; sendDataPtr = (uchar * )sendDataPtr_; sendDataSize = sendDataSize_; if (type_rec == PIProtocol::Ethernet) { if (recHeaderPtr != 0) { dataPtr = (uchar * )recHeaderPtr; dataSize = recHeaderSize + recDataSize; if (dataSize > 0) packet = new char[dataSize]; } else if (recDataSize > 0) packet = new char[recDataSize]; } else if (recHeaderSize + recDataSize > 0) packet = new char[recHeaderSize + recDataSize]; } PIProtocol::~PIProtocol() { //cout << "prot " << protName << " delete\n"; delete diagTimer; delete sendTimer; if (packet != 0) delete packet; if (eth != 0) delete eth; if (ser != 0) delete ser; } void PIProtocol::init() { work = new_mp_prot = false; ret_func = 0; mp_owner = 0; net_diag = PIProtocol::Unknown; cur_pckt = 0; diagTimer = 0; packet = 0; sendTimer = new PITimer(sendEvent, this); diagTimer = new PITimer(diagEvent, this); wrong_count = receive_count = send_count = 0; immediateFreq = integralFreq = 0.f; headerPtr = dataPtr = sendDataPtr = 0; headerSize = dataSize = sendDataSize = 0; eth = 0; ser = 0; type_rec = type_send = PIProtocol::None; devSenderState = devReceiverState = "Unknown"; devSenderName = devReceiverName = "no device"; } void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) { if (force) { type_rec = PIProtocol::Serial; if (ser == 0) ser = new PISerial("", this, receiveEvent); } if (type_rec == PIProtocol::Serial && ser != 0) { ser->setDevice(device); ser->setSpeed(speed); devReceiverName = device; } } void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) { if (force) { type_rec = PIProtocol::Ethernet; if (eth == 0) eth = new PIEthernet("", 0, this, receiveEvent); } if (type_rec == PIProtocol::Ethernet && eth != 0) { eth->setReadAddress(ip, port); if (ip.trimmed().isEmpty()) devReceiverName = "no ip"; else devReceiverName = ip + ":" + PIString::fromNumber(port); } } void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) { if (force) { type_send = PIProtocol::Serial; if (ser == 0) ser = new PISerial("", this, receiveEvent); } if (type_send == PIProtocol::Serial && ser != 0) { ser->setDevice(device); ser->setSpeed(speed); devSenderName = device; } } void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) { if (force) { type_send = PIProtocol::Ethernet; if (eth == 0) eth = new PIEthernet("", 0, this, receiveEvent); } if (type_send == PIProtocol::Ethernet && eth != 0) { eth->setSendAddress(ip, port); if (ip.isEmpty()) devSenderName = "no ip"; else devSenderName = ip + ":" + PIString::fromNumber(port); } } void PIProtocol::setExpectedFrequency(float frequency) { exp_freq = frequency; if (exp_freq < 10.f / 3.f) pckt_cnt_max = 10; else pckt_cnt_max = uint(round(3.f * exp_freq)); last_packets.resize(pckt_cnt_max); } void PIProtocol::startReceive(float exp_frequency) { if (exp_frequency > 0.f) exp_freq = exp_frequency; if (type_rec == PIProtocol::Serial) ser->start(); if (type_rec == PIProtocol::Ethernet) eth->start(); if (exp_freq <= 0.f) return; setExpectedFrequency(exp_freq); diagTimer->start(1000. / exp_freq); diagTimer->reset(); } void PIProtocol::startSend(float frequency) { if (frequency > 0.f) send_freq = frequency; if (send_freq <= 0.f) return; sendTimer->start(1000. / send_freq); } void PIProtocol::stopReceive() { if (type_rec == PIProtocol::Serial) ser->stop(); if (type_rec == PIProtocol::Ethernet) eth->stop(); diagTimer->stop(); } bool PIProtocol::receiveEvent(void * t, char * data, int size) { PIProtocol * p = (PIProtocol * )t; if (!p->receive(data, size)) return false; p->work = true; //p->lock(); if (p->validate()) { //p->unlock(); p->receive_count++; p->cur_pckt = 1; if (p->ret_func != 0) p->ret_func(p); if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); return true; } //p->unlock(); p->wrong_count++; if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); return false; } void PIProtocol::diagEvent(void * t, int) { PIProtocol * p = (PIProtocol * )t; p->calc_freq(); p->calc_diag(); p->check_state(); } void PIProtocol::calc_diag() { PIProtocol::Quality diag; if (!work) { diag = PIProtocol::Unknown; return; } if (pckt_cnt < pckt_cnt_max) { last_packets[pckt_cnt] = cur_pckt; pckt_cnt++; } else { packets[(int)last_packets.back()]--; if (!last_packets.isEmpty()) last_packets.pop_back(); last_packets.push_front(cur_pckt); } packets[(int)cur_pckt]++; cur_pckt = 0; float good_percents; good_percents = (float)packets[1] / pckt_cnt * 100.f; if (good_percents == 0.f) diag = PIProtocol::Failure; else if (good_percents <= 20.f) diag = PIProtocol::Bad; else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average; else diag = PIProtocol::Good; if (diag != net_diag) net_diag = diag; } void PIProtocol::calc_freq() { tf = float(1000.f / diagTimer->elapsed_m()); diagTimer->reset(); if (cur_pckt != 1) tf = 0.f; immediateFreq = tf; if (last_freq.size() >= pckt_cnt_max) last_freq.pop_front(); last_freq.push_back(tf); tf = last_freq[0]; for (uint i = 1; i < last_freq.size(); ++i) tf += last_freq[i]; integralFreq = tf / last_freq.size(); } void PIProtocol::check_state() { if (type_rec == PIProtocol::Serial) { if (ser->initialized()) devReceiverState = "Initialized"; else devReceiverState = "Uninitialized"; } if (type_rec == PIProtocol::Ethernet) { if (eth->receiverInitialized()) devReceiverState = "Initialized"; else devReceiverState = "Uninitialized"; } if (type_send == PIProtocol::Serial) { if (ser->initialized()) devSenderState = "Initialized"; else devSenderState = "Uninitialized"; } if (type_send == PIProtocol::Ethernet) { if (eth->senderInitialized()) devSenderState = "Initialized"; else devSenderState = "Uninitialized"; } } void PIProtocol::send(const void * data, int size) { if (data == 0 || size == 0) return; if (!aboutSend()) return; if (type_send == PIProtocol::Serial) if (ser->send((char * )data, size)) send_count++; if (type_send == PIProtocol::Ethernet) if (eth->send((char * )data, size)) send_count++; } void PIProtocol::send() { //lock(); //memcpy(packet, sendDataPtr, sendDataSize); //unlock(); if (sendDataPtr == 0 || sendDataSize == 0) return; if (!aboutSend()) return; if (type_send == PIProtocol::Serial) if (ser->send((char * )sendDataPtr, sendDataSize)) send_count++; if (type_send == PIProtocol::Ethernet) if (eth->send((char * )sendDataPtr, sendDataSize)) send_count++; }