745 lines
24 KiB
C++
745 lines
24 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Protocol, input/output channel (COM, UDP)
|
|
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piprotocol.h"
|
|
|
|
|
|
PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() {
|
|
init();
|
|
protName = name;
|
|
PIObject::setName(name);
|
|
PIConfig conf(config, PIIODevice::ReadOnly);
|
|
if (!conf.isOpened()) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!";
|
|
devReceiverState = devSenderState = "Config error";
|
|
return;
|
|
}
|
|
int ps, gps;
|
|
bool ok, gok, flag, gflag, has_dev = false;
|
|
float freq, gfreq;
|
|
PIFlags<PISerial::Parameters> pp(0);
|
|
PIConfig::Entry & b(conf.getValue(name)),
|
|
& rb(b.getValue("receiver")),
|
|
& sb(b.getValue("sender"));
|
|
PIString dev, gdev;
|
|
|
|
/// receiver section
|
|
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
dev = rb.getValue("ip", "", &ok);
|
|
gdev = b.getValue("ip", "", &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) dev = gdev;
|
|
if (gok && ok && (dev != gdev)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
ps = rb.getValue("port", 0, &ok);
|
|
gps = b.getValue("port", 0, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) ps = gps;
|
|
if (gok && ok && (ps != gps)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
type_rec = PIProtocol::Ethernet;
|
|
eth = new PIEthernet();
|
|
packet_ext->setDevice(eth);
|
|
//setSenderAddress(dev, ps);
|
|
setReceiverAddress(dev, ps);
|
|
has_dev = true;
|
|
flag = rb.getValue("reconnectEnabled", true, &ok);
|
|
gflag = b.getValue("reconnectEnabled", true, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
eth->setReopenEnabled(flag);
|
|
}
|
|
freq = rb.getValue("reconnectTimeout", 1., &ok);
|
|
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) freq = gfreq;
|
|
if (gok && ok && (freq != gfreq)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
eth->setReopenTimeout(freq * 1000);
|
|
}
|
|
if (recDataPtr == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
|
if (recDataSize == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
|
} else {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
}
|
|
dev = rb.getValue("device", "", &ok);
|
|
gdev = b.getValue("device", "", &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) dev = gdev;
|
|
if (gok && ok && (dev != gdev)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
ps = rb.getValue("speed", 0, &ok);
|
|
gps = b.getValue("speed", 0, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) ps = gps;
|
|
if (gok && ok && (ps != gps)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
flag = rb.getValue("parity", false, &ok);
|
|
gflag = b.getValue("parity", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
pp.setFlag(PISerial::ParityControl, flag);
|
|
}
|
|
flag = rb.getValue("twoStopBits", false, &ok);
|
|
gflag = b.getValue("twoStopBits", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
pp.setFlag(PISerial::TwoStopBits, flag);
|
|
}
|
|
type_rec = PIProtocol::Serial;
|
|
type_send = PIProtocol::Serial;
|
|
ser = new PISerial(dev);
|
|
packet_ext->setDevice(ser);
|
|
//setSenderDevice(dev, (PISerial::Speed)ps);
|
|
setReceiverDevice(dev, (PISerial::Speed)ps);
|
|
ser->setInSpeed((PISerial::Speed)ps);
|
|
ser->setParameters(pp);
|
|
ps = rb.getValue("vtime", 1, &ok);
|
|
gps = b.getValue("vtime", 1, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) ps = gps;
|
|
if (gok && ok && (ps != gps)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
ser->setVTime(ps);
|
|
}
|
|
has_dev = true;
|
|
if (recDataPtr == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
|
|
if (recDataSize == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
|
|
} else {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
}
|
|
history_write_rec = rb.getValue("writeHistory", false, &ok);
|
|
bool ghist = b.getValue("writeHistory", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) history_write_rec = ghist;
|
|
if (gok && ok && (history_write_rec != ghist)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
if (history_write_rec) {
|
|
history_path_rec = rb.getValue("historyFile", "./history_" + protName + "_rec_" +
|
|
date2string(currentDate(), "__dd_mm_yyyy_") +
|
|
time2string(currentTime(), "_hh_mm_ss_")).value();
|
|
history_id_rec = rb.getValue("historyID", 0, &ok);
|
|
if (!ok) {
|
|
history_id_rec = protName.toByteArray().checksumCRC16();
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec;
|
|
}
|
|
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);
|
|
}
|
|
}
|
|
freq = rb.getValue("frequency", -1.f, &ok);
|
|
gfreq = b.getValue("frequency", -1.f, &gok);
|
|
if (gok && !ok) freq = gfreq;
|
|
if (gok && ok && (freq != gfreq)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
if (freq > 0.f && !has_dev)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!";
|
|
float tm = b.getValue("disconnectTimeout", 3.f);
|
|
if (tm <= 0.f)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!";
|
|
timeout_ = (tm < 0.f) ? 0.f : tm;
|
|
setExpectedFrequency(freq);
|
|
|
|
/// sender section
|
|
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
dev = sb.getValue("ip", "", &ok);
|
|
gdev = b.getValue("ip", "", &gok);
|
|
has_dev = false;
|
|
if (ok || gok) {
|
|
if (gok && !ok) dev = gdev;
|
|
if (gok && ok && (dev != gdev)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
ps = sb.getValue("port", 0, &ok);
|
|
gps = b.getValue("port", 0, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) ps = gps;
|
|
if (gok && ok && (ps != gps)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
type_send = PIProtocol::Ethernet;
|
|
if (eth == 0) eth = new PIEthernet();
|
|
setSenderAddress(dev, ps);
|
|
//setReceiverAddress(dev, ps);
|
|
has_dev = true;
|
|
flag = sb.getValue("reconnectEnabled", true, &ok);
|
|
gflag = b.getValue("reconnectEnabled", true, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
eth->setReopenEnabled(flag);
|
|
}
|
|
freq = sb.getValue("reconnectTimeout", 1., &ok);
|
|
gfreq = b.getValue("reconnectTimeout", 1., &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) freq = gfreq;
|
|
if (gok && ok && (freq != gfreq)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
|
|
devReceiverState = "Config error";
|
|
return;
|
|
}
|
|
eth->setReopenTimeout(freq * 1000);
|
|
}
|
|
if (sendDataPtr_ == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
|
if (sendDataSize_ == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
|
} else {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
}
|
|
dev = sb.getValue("device", "", &ok);
|
|
gdev = b.getValue("device", "", &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) dev = gdev;
|
|
if (gok && ok && (dev != gdev)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
ps = sb.getValue("speed", 0, &ok);
|
|
gps = b.getValue("speed", 0, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) ps = gps;
|
|
if (gok && ok && (ps != gps)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
flag = sb.getValue("parity", false, &ok);
|
|
gflag = b.getValue("parity", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
pp.setFlag(PISerial::ParityControl, flag);
|
|
}
|
|
flag = sb.getValue("twoStopBits", false, &ok);
|
|
gflag = b.getValue("twoStopBits", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) flag = gflag;
|
|
if (gok && ok && (flag != gflag)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
pp.setFlag(PISerial::TwoStopBits, flag);
|
|
}
|
|
} else {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
type_send = PIProtocol::Serial;
|
|
if (ser == 0) ser = new PISerial(dev);
|
|
setSenderDevice(dev, (PISerial::Speed)ps);
|
|
ser->setOutSpeed((PISerial::Speed)ps);
|
|
ser->setParameters(pp);
|
|
has_dev = true;
|
|
if (sendDataPtr_ == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
|
|
if (sendDataSize_ == 0)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
|
|
}
|
|
history_write_send = sb.getValue("writeHistory", false, &ok);
|
|
ghist = b.getValue("writeHistory", false, &gok);
|
|
if (ok || gok) {
|
|
if (gok && !ok) history_write_send = ghist;
|
|
if (gok && ok && (history_write_send != ghist)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
if (history_write_send) {
|
|
history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" +
|
|
date2string(currentDate(), "__dd_mm_yyyy_") +
|
|
time2string(currentTime(), "_hh_mm_ss_")).value();
|
|
history_id_send = sb.getValue("historyID", 0, &ok);
|
|
if (!ok) {
|
|
history_id_send = protName.toByteArray().checksumCRC16() + 1;
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send;
|
|
}
|
|
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
|
|
}
|
|
}
|
|
freq = sb.getValue("frequency", -1.f, &ok);
|
|
gfreq = b.getValue("frequency", -1.f, &gok);
|
|
if (gok && !ok) freq = gfreq;
|
|
if (gok && ok && (freq != gfreq)) {
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!";
|
|
devSenderState = "Config error";
|
|
return;
|
|
}
|
|
if (freq > 0.f && !has_dev)
|
|
piCoutObj << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!";
|
|
setSenderFrequency(freq);
|
|
|
|
headerPtr = (uchar * )recHeaderPtr;
|
|
headerSize = recHeaderSize;
|
|
dataPtr = (uchar * )recDataPtr;
|
|
dataSize = recDataSize;
|
|
sendDataPtr = (uchar * )sendDataPtr_;
|
|
sendDataSize = sendDataSize_;
|
|
packet_ext->setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
|
|
}
|
|
|
|
|
|
PIProtocol::~PIProtocol() {
|
|
//cout << "prot " << protName << " delete\n";
|
|
if (history_write_rec) {
|
|
if (history_file_rec.isEmpty()) {
|
|
history_file_rec.close();
|
|
history_file_rec.remove();
|
|
}
|
|
history_file_rec.close();
|
|
}
|
|
if (history_write_send) {
|
|
if (history_file_send.isEmpty()) {
|
|
history_file_send.close();
|
|
history_file_send.remove();
|
|
}
|
|
history_file_send.close();
|
|
}
|
|
delete diagTimer;
|
|
delete sendTimer;
|
|
delete secTimer;
|
|
if (eth != 0) delete eth;
|
|
if (ser != 0) delete ser;
|
|
delete packet_ext;
|
|
}
|
|
|
|
|
|
void PIProtocol::init() {
|
|
packet_ext = new PIPacketExtractor();
|
|
packet_ext->setThreadedReadData(this);
|
|
packet_ext->setThreadedReadSlot(receiveEvent);
|
|
packet_ext->setHeaderCheckSlot(headerValidateEvent);
|
|
work = new_mp_prot = history_write_rec = history_write_send = false;
|
|
eth = 0;
|
|
ser = 0;
|
|
ret_func = 0;
|
|
mp_owner = 0;
|
|
net_diag = PIProtocol::Unknown;
|
|
cur_pckt = 0;
|
|
diagTimer = 0;
|
|
timeout_ = 3.f;
|
|
sendTimer = new PITimer(sendEvent, this);
|
|
diagTimer = new PITimer(diagEvent, this);
|
|
secTimer = new PITimer(secEvent, this);
|
|
wrong_count = receive_count = send_count = missed_count = 0;
|
|
packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0;
|
|
immediate_freq = integral_freq = ifreq = 0.f;
|
|
headerPtr = dataPtr = sendDataPtr = 0;
|
|
headerSize = dataSize = sendDataSize = 0;
|
|
type_rec = type_send = PIProtocol::None;
|
|
devSenderState = devReceiverState = "Unknown";
|
|
devSenderName = devReceiverName = "no device";
|
|
history_rsize_rec = history_rsize_send = "no file";
|
|
secTimer->start(1000.);
|
|
/*addEvent("receiver started");
|
|
addEvent("receiver stopped");
|
|
addEvent("sender started");
|
|
addEvent("sender stopped");
|
|
addEvent<bool>("received");
|
|
addEvent<PIProtocol::Quality>("quality changed");
|
|
addEventHandler<float>(HANDLER(PIProtocol, startReceive));
|
|
addEventHandler<float>(HANDLER(PIProtocol, startSend));
|
|
addEventHandler(HANDLER(PIProtocol, start));
|
|
addEventHandler(HANDLER(PIProtocol, stopReceive));
|
|
addEventHandler(HANDLER(PIProtocol, stopSend));
|
|
addEventHandler(HANDLER(PIProtocol, stop));*/
|
|
}
|
|
|
|
|
|
void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) {
|
|
if (force) {
|
|
type_send = type_rec = PIProtocol::Serial;
|
|
if (ser == 0) {
|
|
ser = new PISerial();
|
|
packet_ext->setDevice(ser);
|
|
}
|
|
}
|
|
if (type_rec == PIProtocol::Serial && ser != 0) {
|
|
ser->setDevice(device);
|
|
ser->setSpeed(speed);
|
|
devReceiverName = device;
|
|
devSenderName = device;
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) {
|
|
if (force) {
|
|
type_rec = PIProtocol::Ethernet;
|
|
if (eth == 0) {
|
|
eth = new PIEthernet();
|
|
packet_ext->setDevice(eth);
|
|
}
|
|
}
|
|
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 = type_rec = PIProtocol::Serial;
|
|
if (ser == 0) ser = new PISerial();
|
|
}
|
|
if (type_send == PIProtocol::Serial && ser != 0) {
|
|
ser->setDevice(device);
|
|
ser->setSpeed(speed);
|
|
ser->open();
|
|
devSenderName = device;
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) {
|
|
if (force) {
|
|
type_send = PIProtocol::Ethernet;
|
|
if (eth == 0) eth = new PIEthernet();
|
|
}
|
|
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::setSenderIP(const PIString & ip, bool force) {
|
|
if (force) {
|
|
type_send = PIProtocol::Ethernet;
|
|
if (eth == 0) eth = new PIEthernet();
|
|
}
|
|
if (type_send == PIProtocol::Ethernet && eth != 0) {
|
|
eth->setSendIP(ip);
|
|
if (ip.isEmpty()) devSenderName = "no ip";
|
|
else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort());
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::setSenderPort(int port, bool force) {
|
|
if (force) {
|
|
type_send = PIProtocol::Ethernet;
|
|
if (eth == 0) eth = new PIEthernet();
|
|
}
|
|
if (type_send == PIProtocol::Ethernet && eth != 0) {
|
|
eth->setSendPort(port);
|
|
if (eth->sendIP().isEmpty()) devSenderName = "no ip";
|
|
else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port);
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::setExpectedFrequency(float frequency) {
|
|
exp_freq = frequency;
|
|
changeDisconnectTimeout();
|
|
}
|
|
|
|
|
|
void PIProtocol::changeDisconnectTimeout() {
|
|
pckt_cnt_max = int(round(timeout_ * exp_freq));
|
|
if (pckt_cnt_max < 3) pckt_cnt_max = 3;
|
|
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();
|
|
packet_ext->startThreadedRead();
|
|
msleep(1);
|
|
check_state();
|
|
if (exp_freq <= 0.f) return;
|
|
setExpectedFrequency(exp_freq);
|
|
diagTimer->start(1000. / exp_freq);
|
|
diagTimer->reset();
|
|
receiverStarted();
|
|
}
|
|
|
|
|
|
void PIProtocol::startSend(float frequency) {
|
|
//cout << "** start send " << send_freq << ", " << frequency << endl;
|
|
if (frequency > 0.f) send_freq = frequency;
|
|
msleep(1);
|
|
check_state();
|
|
if (send_freq <= 0.f) return;
|
|
sendTimer->start(1000. / send_freq);
|
|
diagTimer->reset();
|
|
senderStarted();
|
|
}
|
|
|
|
|
|
void PIProtocol::stopReceive() {
|
|
//if (type_rec == PIProtocol::Serial) ser->stop();
|
|
//if (type_rec == PIProtocol::Ethernet) eth->stop();
|
|
packet_ext->stop();
|
|
diagTimer->stop();
|
|
receiverStopped();
|
|
}
|
|
|
|
|
|
bool PIProtocol::receiveEvent(void * t, uchar * data, int size) {
|
|
PIProtocol * p = (PIProtocol * )t;
|
|
if (!p->receive(data, size)) return false;
|
|
p->work = true;
|
|
//p->lock();
|
|
if (p->validate()) {
|
|
if (p->history_write_rec) {
|
|
p->history_file_rec.writeToBinLog(p->history_id_rec, data, size);
|
|
p->history_rsize_rec.setReadableSize(p->history_file_rec.pos());
|
|
}
|
|
p->received(true);
|
|
//p->unlock();
|
|
p->ifreq = p->diagTimer->elapsed_m();
|
|
if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq;
|
|
p->diagTimer->reset();
|
|
p->receive_count++;
|
|
p->packets_in_sec++;
|
|
p->bytes_in_sec += size;
|
|
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->received(false);
|
|
//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();
|
|
if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets();
|
|
}
|
|
|
|
|
|
void PIProtocol::secEvent(void * t, int ) {
|
|
PIProtocol * p = (PIProtocol * )t;
|
|
p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s";
|
|
p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s";
|
|
p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0;
|
|
if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets();
|
|
}
|
|
|
|
|
|
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) {
|
|
qualityChanged(diag, net_diag);
|
|
net_diag = diag;
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::calc_freq() {
|
|
float tf;// = float(1000.f / diagTimer->elapsed_m());
|
|
tf = immediate_freq = ifreq;
|
|
ifreq = 0.f;
|
|
if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) 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];
|
|
integral_freq = tf / last_freq.size();
|
|
}
|
|
|
|
|
|
void PIProtocol::check_state() {
|
|
if (type_rec == PIProtocol::Serial) {
|
|
if (ser != 0) {
|
|
if (ser->isOpened()) devReceiverState = "Opened";
|
|
else devReceiverState = "Not opened";
|
|
}
|
|
else devReceiverState = "Not exists";
|
|
}
|
|
if (type_rec == PIProtocol::Ethernet) {
|
|
if (eth != 0) {
|
|
if (eth->isOpened()) devReceiverState = "Opened";
|
|
else devReceiverState = "Not opened";
|
|
}
|
|
else devReceiverState = "Not exists";
|
|
}
|
|
if (type_send == PIProtocol::Serial) {
|
|
if (ser != 0) {
|
|
if (ser->isOpened()) devSenderState = "Opened";
|
|
else devSenderState = "Not opened";
|
|
}
|
|
else devSenderState = "Not exists";
|
|
}
|
|
if (type_send == PIProtocol::Ethernet) {
|
|
if (eth != 0) {
|
|
if (eth->isOpened()) devSenderState = "Opened";
|
|
else devSenderState = "Not opened";
|
|
}
|
|
else devSenderState = "Not exists";
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::send(const void * data, int size, bool direct) {
|
|
if (!direct) {
|
|
if (data == 0 || size == 0) return;
|
|
if (!aboutSend()) return;
|
|
}
|
|
if (history_write_send) {
|
|
history_file_send.writeToBinLog(history_id_send, data, size);
|
|
history_rsize_send.setReadableSize(history_file_send.pos());
|
|
}
|
|
if (type_send == PIProtocol::Serial)
|
|
if (ser->send(data, size)) {
|
|
send_count++;
|
|
packets_out_sec++;
|
|
bytes_out_sec += size;
|
|
}
|
|
if (type_send == PIProtocol::Ethernet)
|
|
if (eth->send(data, size)) {
|
|
send_count++;
|
|
packets_out_sec++;
|
|
bytes_out_sec += size;
|
|
}
|
|
}
|
|
|
|
|
|
void PIProtocol::send() {
|
|
//lock();
|
|
//memcpy(packet, sendDataPtr, sendDataSize);
|
|
//unlock();
|
|
//cout << "**send" << endl;
|
|
if (!aboutSend()) return;
|
|
if (sendDataPtr == 0 || sendDataSize == 0) return;
|
|
if (history_write_send) {
|
|
history_file_send.writeToBinLog(history_id_send, sendDataPtr, sendDataSize);
|
|
history_rsize_send.setReadableSize(history_file_send.pos());
|
|
}
|
|
if (type_send == PIProtocol::Serial)
|
|
if (ser->send(sendDataPtr, sendDataSize)) {
|
|
send_count++;
|
|
packets_out_sec++;
|
|
bytes_out_sec += sendDataSize;
|
|
}
|
|
if (type_send == PIProtocol::Ethernet)
|
|
if (eth->send(sendDataPtr, sendDataSize)) {
|
|
send_count++;
|
|
packets_out_sec++;
|
|
bytes_out_sec += sendDataSize;
|
|
}
|
|
}
|