#ifndef PIPROTOCOL_H #define PIPROTOCOL_H #include "piserial.h" #include "piethernet.h" #include "pitimer.h" #include "piconfig.h" #include "math.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 { friend class PIMultiProtocolBase; friend class PIMultiProtocol; enum Type {None, Serial, Ethernet}; enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5}; public: PIProtocol() {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(); void startReceive(float exp_frequency = -1.f); // if "frequency = -1" used last passed value 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 parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} void startSend(float frequency = -1.f); // if "frequency = -1" used last passed value void stopSend() {sendTimer->stop();} 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 parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void start() {startReceive(); startSend();} void stop() {stopReceive(); stopSend();} void send(); void send(const void * data, int size); void setName(const PIString & name) {protName = name;} PIString name() const {return protName;} float immediateFrequency() const {return immediateFreq;} float integralFrequency() const {return integralFreq;} float * immediateFrequency_ptr() {return &immediateFreq;} float * integralFrequency_ptr() {return &integralFreq;} 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 {cout << devSenderName << endl; return devSenderName;} PIString receiverDeviceState() const {return devReceiverState;} PIString * receiverDeviceState_ptr() {return &devReceiverState;} PIString senderDeviceState() const {return devSenderState;} PIString * senderDeviceState_ptr() {return &devSenderState;} protected: virtual bool receive(char * data, int size) {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) {((PIProtocol * )e)->send();} static bool receiveEvent(void * t, char * data, int size); static void diagEvent(void * t); void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} ReceiveFunc ret_func; PITimer * diagTimer, * sendTimer; 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; bool work, new_mp_prot; float exp_freq, send_freq, immediateFreq, integralFreq, tf; int packets[2]; uint pckt_cnt, pckt_cnt_max; char * packet, cur_pckt; ullong wrong_count, receive_count, send_count; }; #endif // PIPROTOCOL_H