/* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) Copyright (C) 2011 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 . */ #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, 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 * ); 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; if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setReadData(headerPtr, headerSize, dataSize);} void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setReadData(headerPtr, headerSize, 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(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 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;} ullong missedCount() const {return missed_count;} ullong * missedCount_ptr() {return &missed_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();} 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]; 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, uchar * data, int size); static bool headerValidateEvent(void * t, uchar * src, uchar * rec, 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 last_freq; PIDeque 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, missed_count; }; #endif // PIPROTOCOL_H