187 lines
8.1 KiB
C++
187 lines
8.1 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Protocol, input/output channel (COM, UDP)
|
|
Copyright (C) 2011 Ivan Pelipenko peri4@rambler.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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PIPROTOCOL_H
|
|
#define PIPROTOCOL_H
|
|
|
|
#include "piserial.h"
|
|
#include "piethernet.h"
|
|
#include "pitimer.h"
|
|
#include "piconfig.h"
|
|
#include "math.h"
|
|
#include "piobject.h"
|
|
|
|
class PIProtocol;
|
|
|
|
class PIMultiProtocolBase
|
|
{
|
|
friend class PIProtocol;
|
|
public:
|
|
PIMultiProtocolBase() {;}
|
|
~PIMultiProtocolBase() {;}
|
|
|
|
protected:
|
|
virtual void received(PIProtocol * prot, bool corrected, char * data, int size) {;}
|
|
|
|
private:
|
|
static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, char * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();}
|
|
|
|
PIMutex mutex_receive;
|
|
|
|
};
|
|
|
|
typedef void (*ReceiveFunc)(void * );
|
|
|
|
class PIProtocol: public PIObject
|
|
{
|
|
friend class PIMultiProtocolBase;
|
|
friend class PIMultiProtocol;
|
|
enum Type {None, Serial, Ethernet};
|
|
|
|
public:
|
|
PIProtocol(): PIObject() {init();}
|
|
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
|
|
~PIProtocol();
|
|
|
|
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
|
|
|
|
EVENT_HANDLER0(PIProtocol, void, startReceive) {startReceive(-1.f);}
|
|
EVENT_HANDLER1(PIProtocol, void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
|
|
EVENT_HANDLER0(PIProtocol, 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;}
|
|
void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
|
|
void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
|
|
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
|
|
float expectedFrequency() const {return exp_freq;}
|
|
|
|
EVENT_HANDLER0(PIProtocol, void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
|
|
EVENT_HANDLER1(PIProtocol, void, startSend, float, frequency); // if "frequency = -1" used last passed value
|
|
EVENT_HANDLER0(PIProtocol, void, stopSend) {sendTimer->stop(); raiseEvent(this, "sender stopped");}
|
|
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 setSenderParameters(PIFlags<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
|
|
float senderFrequency() const {return send_freq;}
|
|
|
|
EVENT_HANDLER0(PIProtocol, void, start) {startReceive(); startSend();}
|
|
EVENT_HANDLER0(PIProtocol, void, stop) {stopReceive(); stopSend();}
|
|
EVENT_HANDLER0(PIProtocol, void, send);
|
|
EVENT_HANDLER2(PIProtocol, void, send, const void *, data, int, size);
|
|
|
|
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_;}
|
|
float * disconnectTimeout_ptr() {return &timeout_;}
|
|
float immediateFrequency() const {return immediate_freq;}
|
|
float integralFrequency() const {return integral_freq;}
|
|
float * immediateFrequency_ptr() {return &immediate_freq;}
|
|
float * integralFrequency_ptr() {return &integral_freq;}
|
|
ullong receiveCount() const {return receive_count;}
|
|
ullong * receiveCount_ptr() {return &receive_count;}
|
|
ullong wrongCount() const {return wrong_count;}
|
|
ullong * wrongCount_ptr() {return &wrong_count;}
|
|
ullong sendCount() const {return send_count;}
|
|
ullong * sendCount_ptr() {return &send_count;}
|
|
PIProtocol::Quality quality() const {return net_diag;} // receive quality
|
|
int * quality_ptr() {return (int * )&net_diag;} // receive quality pointer
|
|
PIString receiverDeviceName() const {return devReceiverName;}
|
|
PIString senderDeviceName() const {return devSenderName;}
|
|
PIString receiverDeviceState() const {return devReceiverState;}
|
|
PIString * receiverDeviceState_ptr() {return &devReceiverState;}
|
|
PIString senderDeviceState() const {return devSenderState;}
|
|
PIString * senderDeviceState_ptr() {return &devSenderState;}
|
|
PIString receiverHistorySize() const {return history_rsize_rec;}
|
|
PIString * receiverHistorySize_ptr() {return &history_rsize_rec;}
|
|
PIString senderHistorySize() const {return history_rsize_send;}
|
|
PIString * senderHistorySize_ptr() {return &history_rsize_send;}
|
|
bool writeReceiverHistory() const {return history_write_rec;}
|
|
bool * writeReceiverHistory_ptr() {return &history_write_rec;}
|
|
bool writeSenderHistory() const {return history_write_send;}
|
|
bool * writeSenderHistory_ptr() {return &history_write_send;}
|
|
|
|
void * receiveData() {return dataPtr;}
|
|
void * sendData() {return sendDataPtr;}
|
|
|
|
PIByteArray lastHeader() {if (ser != 0) return ser->lastHeader(); return PIByteArray();}
|
|
PIByteArray internalBuffer() {if (ser != 0) return ser->internalBuffer(); return PIByteArray();}
|
|
|
|
protected:
|
|
virtual bool receive(char * 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 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];
|
|
c = ~(c + 1);
|
|
return c;
|
|
}
|
|
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];
|
|
c = ~(c + 1);
|
|
return c;
|
|
}
|
|
virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending
|
|
|
|
void init();
|
|
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, char * data, int size);
|
|
static void diagEvent(void * t, int);
|
|
|
|
void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;}
|
|
PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;}
|
|
void changeDisconnectTimeout();
|
|
|
|
ReceiveFunc ret_func;
|
|
PITimer * diagTimer, * sendTimer;
|
|
PIMultiProtocolBase * mp_owner;
|
|
PIProtocol::Type type_send, type_rec;
|
|
PIProtocol::Quality net_diag;
|
|
PIDeque<float> last_freq;
|
|
PIDeque<char> last_packets;
|
|
PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState;
|
|
PIString history_path_rec, history_path_send, history_rsize_rec, history_rsize_send;
|
|
PIFile history_file_rec, history_file_send;
|
|
ushort history_id_rec, history_id_send;
|
|
bool work, new_mp_prot, history_write_rec, history_write_send;
|
|
float exp_freq, send_freq, immediate_freq, integral_freq, timeout_;
|
|
int packets[2], pckt_cnt, pckt_cnt_max;
|
|
char * packet, cur_pckt;
|
|
ullong wrong_count, receive_count, send_count;
|
|
|
|
};
|
|
|
|
#endif // PIPROTOCOL_H
|