diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1741d21..f2826b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,7 +44,7 @@ endif ()
include(SDKMacros.cmake)
set(PIP_LIBRARY pip)
-set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io" "console" "math" "code" "geo" "resources" "opencl" "crypt")
+set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io_devices" "io_utils" "console" "math" "code" "geo" "resources" "opencl" "crypt")
set(PIP_INCLUDES)
if (LIB)
diff --git a/kx_utils/CMakeLists.txt b/kx_utils/CMakeLists.txt
index 3af569c..cf3a787 100644
--- a/kx_utils/CMakeLists.txt
+++ b/kx_utils/CMakeLists.txt
@@ -18,8 +18,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
-set(CPPS_UTILS "kx_coeffs.cpp")
-set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h")
+set(CPPS_UTILS "kx_coeffs.cpp" "piprotocol.cpp")
+set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h" "piprotocol.h")
if (DEFINED ENV{QNX_HOST})
add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS})
else()
diff --git a/kx_utils/piprotocol.cpp b/kx_utils/piprotocol.cpp
new file mode 100644
index 0000000..8d0b09b
--- /dev/null
+++ b/kx_utils/piprotocol.cpp
@@ -0,0 +1,718 @@
+/*
+ PIP - Platform Independent Primitives
+ Protocol, input/output channel (COM, UDP)
+ Copyright (C) 2018 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
+
+ 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 .
+*/
+
+#include "piprotocol.h"
+
+/** \class PIProtocol
+ * \brief
+ * \details
+ * \section PIProtocol_sec0 Synopsis
+ *
+ *
+ *
+ * */
+
+ /// DEPRECATED
+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 << "Can`t open \"" << config << "\"!";
+ devReceiverState = devSenderState = "Config error";
+ return;
+ }
+ PIConfig::Entry & b(conf.getValue(name_)),
+ & rb(b.getValue("receiver")),
+ & sb(b.getValue("sender"));
+
+ init_receiver(b, rb, config);
+ init_sender(b, sb, config);
+
+ headerPtr = (uchar * )recHeaderPtr;
+ headerSize = recHeaderSize;
+ dataPtr = (uchar * )recDataPtr;
+ dataSize = recDataSize;
+ sendDataPtr = (uchar * )sendDataPtr_;
+ sendDataSize = sendDataSize_;
+ packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize));
+ packet_ext->setPayloadSize(recDataSize);
+ packet_ext->setPacketSize(recDataSize);
+ packet_ext->setSplitMode(PIPacketExtractor::Header);
+ bool null_h = (recHeaderPtr == 0 || recHeaderSize == 0), null_d = (recDataPtr == 0 || recDataSize == 0);
+ if (null_h && null_d) packet_ext->setSplitMode(PIPacketExtractor::None);
+ else {
+ if (null_h) packet_ext->setSplitMode(PIPacketExtractor::Size);
+ }
+}
+
+
+PIProtocol::~PIProtocol() {
+ delete diagTimer;
+ delete sendTimer;
+ delete secTimer;
+ delete packet_ext;
+ if (eth != 0) delete eth;
+ if (ser != 0) delete ser;
+}
+
+
+void PIProtocol::init() {
+ packet_ext = new PIPacketExtractor(0, PIPacketExtractor::None);
+ packet_ext->setThreadedReadData(this);
+ packet_ext->setThreadedReadSlot(receiveEvent);
+ packet_ext->setHeaderCheckSlot(headerValidateEvent);
+ packet_ext->setName("__S__PIProtocol::packet_ext");
+ work = new_mp_prot = false;
+ eth = 0;
+ ser = 0;
+ ret_func = 0;
+ mp_owner = 0;
+ net_diag = PIProtocol::Unknown;
+ cur_pckt = 0;
+ packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0;
+ diagTimer = 0;
+ timeout_ = 3.f;
+ sendTimer = new PITimer(sendEvent, this);
+ diagTimer = new PITimer(diagEvent, this);
+ secTimer = new PITimer(secEvent, this);
+ sendTimer->setName("__S__PIProtocol::sendTimer");
+ diagTimer->setName("__S__PIProtocol::diagTimer");
+ secTimer->setName("__S__PIProtocol::secTimer");
+ 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";
+ secTimer->start(1000.);
+ /*addEvent("receiver started");
+ addEvent("receiver stopped");
+ addEvent("sender started");
+ addEvent("sender stopped");
+ addEvent("received");
+ addEvent("quality changed");
+ addEventHandler(HANDLER(PIProtocol, startReceive));
+ addEventHandler(HANDLER(PIProtocol, startSend));
+ addEventHandler(HANDLER(PIProtocol, start));
+ addEventHandler(HANDLER(PIProtocol, stopReceive));
+ addEventHandler(HANDLER(PIProtocol, stopSend));
+ addEventHandler(HANDLER(PIProtocol, stop));*/
+}
+
+
+void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) {
+ int ps, gps;
+ bool ok, gok, flag, gflag, has_dev = false;
+ float freq, gfreq;
+ PIFlags pp(0);
+ PIString dev, gdev;
+
+ if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
+ piCoutObj << "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 << "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 << "Ambiguous send port in \"" << config << "\"!";
+ devSenderState = "Config error";
+ return;
+ }
+ type_send = PIProtocol::Ethernet;
+ if (eth == 0) eth = new PIEthernet();
+ eth->setName("__S__PIProtocol::eth");
+ 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 << "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 << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ eth->setReopenTimeout(freq * 1000);
+ }
+ /*if (sendDataPtr_ == 0)
+ piCoutObj << "Warning: null send data pointer!";
+ if (sendDataSize_ == 0)
+ piCoutObj << "Warning: null send data size!";*/
+ } else {
+ piCoutObj << "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 << "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 << "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 << "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 << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
+ devSenderState = "Config error";
+ return;
+ }
+ pp.setFlag(PISerial::TwoStopBits, flag);
+ }
+ } else {
+ piCoutObj << "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);
+ ser->setName("__S__PIProtocol::ser");
+ setSenderDevice(dev, (PISerial::Speed)ps);
+ ser->setOutSpeed((PISerial::Speed)ps);
+ ser->setParameters(pp);
+ has_dev = true;
+ /*if (sendDataPtr_ == 0)
+ piCoutObj << "Warning: null send data pointer!";
+ if (sendDataSize_ == 0)
+ piCoutObj << "Warning: null send data size!";*/
+ }
+ 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 << "Ambiguous sender frequency in \"" << config << "\"!";
+ devSenderState = "Config error";
+ return;
+ }
+ if (freq > 0.f && !has_dev)
+ piCoutObj << "Warning: no sender device and not null send frequency!";
+ setSenderFrequency(freq);
+}
+
+
+void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) {
+ int ps, gps;
+ bool ok, gok, flag, gflag, has_dev = false;
+ float freq, gfreq;
+ PIFlags pp(0);
+ PIString dev, gdev;
+
+ if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
+ piCoutObj << "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 << "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 << "Ambiguous receive port in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ type_rec = PIProtocol::Ethernet;
+ eth = new PIEthernet();
+ eth->setName("__S__PIProtocol::eth");
+ 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 << "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 << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ eth->setReopenTimeout(freq * 1000);
+ }
+ /*if (recDataPtr == 0)
+ piCoutObj << "Warning: null receive data pointer!";
+ if (recDataSize == 0)
+ piCoutObj << "Warning: null receive data size!";*/
+ } else {
+ piCoutObj << "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 << "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 << "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 << "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 << "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);
+ ser->setName("__S__PIProtocol::ser");
+ 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 << "Ambiguous receive \"vtime\" in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ ser->setVTime(ps);
+ }
+ has_dev = true;
+ /*if (recDataPtr == 0)
+ piCoutObj << "Warning: null receive data pointer!";
+ if (recDataSize == 0)
+ piCoutObj << "Warning: null receive data size!";*/
+ } else {
+ piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ }
+ 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 << "Ambiguous expected frequency in \"" << config << "\"!";
+ devReceiverState = "Config error";
+ return;
+ }
+ if (freq > 0.f && !has_dev)
+ piCoutObj << "Warning: no receiver device and not null expected frequency!";
+ float tm = b.getValue("disconnectTimeout", 3.f);
+ if (tm <= 0.f)
+ piCoutObj << "Warning: diconnect timeout <= 0 s!";
+ timeout_ = (tm < 0.f) ? 0.f : tm;
+ setExpectedFrequency(freq);
+}
+
+
+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();
+ ser->setName("__S__PIProtocol::ser");
+ 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();
+ eth->setName("__S__PIProtocol::eth");
+ 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();
+ ser->setName("__S__PIProtocol::ser");
+ }
+ 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();
+ eth->setName("__S__PIProtocol::eth");
+ }
+ 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();
+ eth->setName("__S__PIProtocol::eth");
+ }
+ 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(piRound(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);
+ diag_tm.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);
+ diag_tm.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()) {
+ p->received(true);
+ //p->unlock();
+ p->ifreq = p->diag_tm.elapsed_m();
+ if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq;
+ p->diag_tm.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 (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();
+ if (!aboutSend()) return;
+ if (sendDataPtr == 0 || sendDataSize == 0) return;
+ 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;
+ }
+}
diff --git a/kx_utils/piprotocol.h b/kx_utils/piprotocol.h
new file mode 100644
index 0000000..e5ebca8
--- /dev/null
+++ b/kx_utils/piprotocol.h
@@ -0,0 +1,238 @@
+/*! \file piprotocol.h
+ * \brief Highly configurable from file I/O channel
+*/
+/*
+ PIP - Platform Independent Primitives
+ Protocol, input/output channel (COM, UDP)
+ Copyright (C) 2018 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
+
+ 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 .
+*/
+
+#ifndef PIPROTOCOL_H
+#define PIPROTOCOL_H
+
+#include "piserial.h"
+#include "piethernet.h"
+#include "pipacketextractor.h"
+#include "pitimer.h"
+#include "piconfig.h"
+#include "pifile.h"
+
+class PIProtocol; /// DEPRECATED
+
+class PIP_EXPORT PIMultiProtocolBase: protected PIObject /// DEPRECATED
+{
+ PIOBJECT_SUBCLASS(PIMultiProtocolBase, PIObject)
+ friend class PIProtocol;
+public:
+ PIMultiProtocolBase() {;} /// DEPRECATED
+ virtual ~PIMultiProtocolBase() {;}
+
+protected:
+ virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;}
+
+private:
+ static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, uchar * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();}
+
+ PIMutex mutex_receive;
+
+};
+
+typedef void (*ReceiveFunc)(void * );
+
+/// events:
+/// void receiverStarted()
+/// void receiverStopped()
+/// void senderStarted()
+/// void senderStopped()
+/// void received(bool validate_is_ok)
+/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality)
+///
+/// handlers:
+/// void startReceive(float exp_frequency = -1.f)
+/// void stopReceive()
+/// void startSend(float frequency = -1.f)
+/// void stopSend()
+/// void start()
+/// void stop()
+/// void send()
+/// void send(const void * data, int size, bool direct = false)
+class PIP_EXPORT PIProtocol: public PIObject /// DEPRECATED
+{
+ PIOBJECT_SUBCLASS(PIProtocol, PIObject)
+ friend class PIMultiProtocolBase;
+ friend class PIMultiProtocol;
+ enum Type {None, Serial, Ethernet};
+public:
+
+ //! Contructs an empty unconfigured protocol
+ PIProtocol(): PIObject() {init();} /// DEPRECATED
+
+ //! Contructs protocol configured from file "config", config file section "name"
+ PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0,
+ void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config
+
+ virtual ~PIProtocol();
+
+ //! Connection quality
+ enum Quality {
+ Unknown /** Unknown, no one packet received yet */ = 1,
+ Failure /** No connection, no one correct packet received for last period */ = 2,
+ Bad /** Bad connection, correct packets received <= 20% */ = 3,
+ Average /** Average connection, correct packets received > 20% and <= 80% */ = 4,
+ Good /** Good connection, correct packets received > 80% */ = 5
+ };
+
+ EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);}
+ EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
+ EVENT_HANDLER0(void, stopReceive);
+ void setExpectedFrequency(float frequency); // for connection quality diagnostic
+ void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
+ void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);}
+ void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);}
+ void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
+ void setReceiverParameters(PIFlags parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
+ void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
+ float expectedFrequency() const {return exp_freq;}
+
+ EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
+ EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value
+ EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();}
+ void setSenderFrequency(float frequency) {send_freq = frequency;}
+ void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
+ void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;}
+ void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet
+ void setSenderIP(const PIString & ip, bool force = false); // for Ethernet
+ void setSenderPort(int port, bool force = false); // for Ethernet
+ void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
+ float senderFrequency() const {return send_freq;}
+
+ EVENT_HANDLER0(void, start) {startReceive(); startSend();}
+ EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();}
+ EVENT_HANDLER0(void, send);
+ EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);}
+ EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct);
+
+ void setName(const PIString & name) {protName = name; PIObject::setName(name);}
+ PIString name() const {return protName;}
+ void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();}
+ float disconnectTimeout() const {return timeout_;}
+ const float * disconnectTimeout_ptr() const {return &timeout_;}
+ float immediateFrequency() const {return immediate_freq;}
+ float integralFrequency() const {return integral_freq;}
+ const float * immediateFrequency_ptr() const {return &immediate_freq;}
+ const float * integralFrequency_ptr() const {return &integral_freq;}
+ ullong receiveCountPerSec() const {return packets_in_sec;}
+ const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;}
+ ullong sendCountPerSec() const {return packets_out_sec;}
+ const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;}
+ ullong receiveBytesPerSec() const {return bytes_in_sec;}
+ const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;}
+ ullong sendBytesPerSec() const {return bytes_out_sec;}
+ const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;}
+ ullong receiveCount() const {return receive_count;}
+ const ullong * receiveCount_ptr() const {return &receive_count;}
+ ullong wrongCount() const {return wrong_count;}
+ const ullong * wrongCount_ptr() const {return &wrong_count;}
+ ullong sendCount() const {return send_count;}
+ const ullong * sendCount_ptr() const {return &send_count;}
+ ullong missedCount() const {return missed_count;}
+ const ullong * missedCount_ptr() const {return &missed_count;}
+ PIProtocol::Quality quality() const {return net_diag;} // receive quality
+ const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer
+ PIString receiverDeviceName() const {return devReceiverName;}
+ PIString senderDeviceName() const {return devSenderName;}
+ PIString receiverDeviceState() const {return devReceiverState;}
+ const PIString * receiverDeviceState_ptr() const {return &devReceiverState;}
+ PIString senderDeviceState() const {return devSenderState;}
+ const PIString * senderDeviceState_ptr() const {return &devSenderState;}
+ PIString receiveSpeed() const {return speedIn;}
+ const PIString * receiveSpeed_ptr() const {return &speedIn;}
+ PIString sendSpeed() const {return speedOut;}
+ const PIString * sendSpeed_ptr() const {return &speedOut;}
+
+ void * receiveData() {return dataPtr;}
+ void * sendData() {return sendDataPtr;}
+
+ PIPacketExtractor * packetExtractor() {return packet_ext;}
+// PIByteArray lastHeader() {return packet_ext->lastHeader();}
+
+ EVENT0(receiverStarted)
+ EVENT0(receiverStopped)
+ EVENT0(senderStarted)
+ EVENT0(senderStopped)
+ EVENT1(received, bool, validate_is_ok)
+ EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality)
+
+protected:
+ virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return
+ virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct
+ virtual bool headerValidate(uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} // function for validate header (COM-port and headerSize > 0)
+ virtual uint checksum_i(void * data, int size) { // function for checksum (uint)
+ uint c = 0;
+ for (int i = 0; i < size; ++i)
+ c += ((uchar*)data)[i];
+ return ~(c + 1);
+ }
+ virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar)
+ uchar c = 0;
+ for (int i = 0; i < size; ++i)
+ c += ((uchar*)data)[i];
+ return ~(c + 1);
+ }
+ virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending
+
+ void init();
+ void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config);
+ void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config);
+ void check_state();
+ void calc_freq();
+ void calc_diag();
+
+ PISerial * ser;
+ PIEthernet * eth;
+ uint dataSize, headerSize, sendDataSize;
+ uchar * dataPtr, * headerPtr, * sendDataPtr;
+
+private:
+ static void sendEvent(void * e, int) {((PIProtocol * )e)->send();}
+ static bool receiveEvent(void * t, uchar * data, int size);
+ static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);}
+ static void diagEvent(void * t, int);
+ static void secEvent(void * t, int);
+
+ void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;}
+ PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;}
+ void changeDisconnectTimeout();
+
+ ReceiveFunc ret_func;
+ PIPacketExtractor * packet_ext;
+ PITimer * diagTimer, * sendTimer, * secTimer;
+ PITimeMeasurer diag_tm;
+ PIMultiProtocolBase * mp_owner;
+ PIProtocol::Type type_send, type_rec;
+ PIProtocol::Quality net_diag;
+ PIDeque last_freq;
+ PIDeque last_packets;
+ PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut;
+ bool work, new_mp_prot;
+ float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_;
+ int packets[2], pckt_cnt, pckt_cnt_max;
+ char cur_pckt;
+ ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec;
+
+};
+
+#endif // PIPROTOCOL_H
diff --git a/piqt_utils/CMakeLists.txt b/piqt_utils/CMakeLists.txt
index 1849460..c105be4 100644
--- a/piqt_utils/CMakeLists.txt
+++ b/piqt_utils/CMakeLists.txt
@@ -24,7 +24,7 @@ list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME})
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
include_directories(${PIP_INCLUDES} ${QAD_INCLUDES})
file(GLOB SRC "*.h" "*.cpp" "*.ui" "*.qrc" "lang/*.ts")
-pip_code_model(CCM "../pip/src_main/io/piiodevice.h" "../pip/src_main/io/pipacketextractor.h" OPTIONS "-DPIP_EXPORT" "-Es")
+pip_code_model(CCM "../pip/src_main/io_devices/piiodevice.h" "../pip/src_main/io_utils/pipacketextractor.h" OPTIONS "-DPIP_EXPORT" "-Es")
find_qt(${QtVersions} Core Gui)
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
qt_add_library(${PROJECT_NAME} ${LIBTYPE} out_CPP CCM)