Files
pip/piprotocol.cpp
2011-10-09 22:23:52 +04:00

344 lines
10 KiB
C++

#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<PISerial::Parameters> 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 = 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) {
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 = 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++;
}