From 8b72323dd11233b4d2fb57973b6a1ec87eefbf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Wed, 30 Nov 2016 12:21:53 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/pip@284 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- FindPIP.cmake | 5 +- src/io/pibinarylog.cpp | 8 +-- src/io/pibinarylog.h | 17 +++--- src/io/piconnection.cpp | 28 +-------- src/io/piconnection.h | 2 - src/io/piethernet.cpp | 10 ++-- src/io/piethernet.h | 19 ++----- src/io/pifile.cpp | 10 ++-- src/io/pifile.h | 16 ++---- src/io/piiobytearray.cpp | 4 +- src/io/piiobytearray.h | 9 ++- src/io/piiodevice.cpp | 78 ++++++++++++++++++++++++-- src/io/piiodevice.h | 76 ++++++++++++++++++------- src/io/piiostring.cpp | 4 +- src/io/piiostring.h | 7 +-- src/io/pipacketextractor.cpp | 4 +- src/io/pipacketextractor.h | 11 +--- src/io/pipeer.cpp | 10 ++-- src/io/pipeer.h | 10 ++-- src/io/piserial.cpp | 106 ++++++++++++++--------------------- src/io/piserial.h | 24 +++----- src/io/pisharedmemory.h | 2 + src/io/piusb.cpp | 10 ++-- src/io/piusb.h | 9 ++- src/piversion.h | 2 +- 25 files changed, 254 insertions(+), 227 deletions(-) diff --git a/FindPIP.cmake b/FindPIP.cmake index 71eda5fd..03a8fb97 100644 --- a/FindPIP.cmake +++ b/FindPIP.cmake @@ -37,7 +37,7 @@ macro (pip_code_model SRC RESULT) foreach (_A ${ARGN}) #message(STATUS ${_A}) if (_IS_OPT) - set (OPTS ${_A}) + list (APPEND OPTS ${_A}) else () if ("${_A}" STREQUAL "OPTIONS") set(_IS_OPT true) @@ -73,7 +73,8 @@ macro (pip_code_model SRC RESULT) if (NEED_PARSE) message(STATUS "Creating code model based on \"${SRC}\", please wait ... ") #message(STATUS "exec \"-qP ${OPTS} -o ${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${SRC}\"") - execute_process(COMMAND ${PIP_CMG} -qP ${OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC} OUTPUT_VARIABLE CMG_OUT) + #message(STATUS "exec ${PIP_CMG} -P ${OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC}") + execute_process(OUTPUT_VARIABLE CMG_OUT COMMAND ${PIP_CMG} -qP ${OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_ccm -I${PIP_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC}) message(STATUS "Creating code model done, to use it include \"${PROJECT_NAME}_ccm.h\"") string(REPLACE "\n" ";" CMG_LIST "${CMG_OUT}") string(REPLACE "\n" " " CMG_LIST_S "${CMG_OUT}") diff --git a/src/io/pibinarylog.cpp b/src/io/pibinarylog.cpp index 75de3c2c..120d1dea 100644 --- a/src/io/pibinarylog.cpp +++ b/src/io/pibinarylog.cpp @@ -334,7 +334,7 @@ int PIBinaryLog::readBinLog(int id, void *read_to, int max_size, PISystemTime * } -int PIBinaryLog::read(void *read_to, int max_size) { +int PIBinaryLog::readDevice(void *read_to, int max_size) { if (lastrecord.id == -1 || isEnd()) return 0; if(!is_thread_ok && lastrecord.id > 0) return lastrecord.data.size(); if (!canRead()) return -1; @@ -531,8 +531,8 @@ PIBinaryLog::BinLogInfo PIBinaryLog::getLogInfo(const PIString & path) { } -PIString PIBinaryLog::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); +PIString PIBinaryLog::constructFullPathDevice() const { + PIString ret; ret << logDir() << ":" << filePrefix() << ":" << defaultID() << ":"; switch (play_mode) { case PlayRealTime: @@ -609,7 +609,7 @@ bool PIBinaryLog::seek(llong filepos) { } -void PIBinaryLog::configureFromFullPath(const PIString & full_path) { +void PIBinaryLog::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); diff --git a/src/io/pibinarylog.h b/src/io/pibinarylog.h index 04c24fb0..6ed9109f 100644 --- a/src/io/pibinarylog.h +++ b/src/io/pibinarylog.h @@ -200,22 +200,20 @@ public: //! Returns if BinLog file is empty int lastReadedID() const {return lastrecord.id;} - - //! Set position in file to reading/playing +#ifdef DOXYGEN //! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty int read(void *read_to, int max_size); //! Write one record to BinLog file, with ID = "defaultID" - int write(const void * data, int size) {return writeBinLog(default_id, data, size);} - + int write(const void * data, int size); +#endif + //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead PIVector filterID; //! Go to begin of BinLog file void restart(); - - PIString constructFullPath() const; //! Get binlog info \a BinLogInfo BinLogInfo logInfo() const {if (is_indexed) return binfo; return getLogInfo(path());} @@ -231,6 +229,8 @@ public: //! Go to nearest record bool seek(const PISystemTime & time); + + //! Set position in file to reading/playing bool seek(llong filepos); //! Get current record index (position record in file) @@ -269,7 +269,10 @@ public: protected: PIString fullPathPrefix() const {return "binlog";} - void configureFromFullPath(const PIString & full_path); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString & full_path); + int readDevice(void *read_to, int max_size); + int writeDevice(const void * data, int size) {return writeBinLog(default_id, data, size);} bool openDevice(); bool closeDevice(); void propertyChanged(const PIString &); diff --git a/src/io/piconnection.cpp b/src/io/piconnection.cpp index 58c79de9..806607f0 100755 --- a/src/io/piconnection.cpp +++ b/src/io/piconnection.cpp @@ -136,7 +136,7 @@ bool PIConnection::configure(PIConfig & conf, const PIString & name_) { if (fn.isEmpty()) continue; PIString & n(name_list[i]); PIIODevice::DeviceMode dm = PIIODevice::ReadWrite; - splitFullPathWithMode(fn, &fn, &dm); + PIIODevice::splitFullPath(fn, &fn, &dm); //piCout << fn; PIIODevice * dev = addDevice(fn, dm); if (!dev) continue; @@ -253,10 +253,7 @@ PIString PIConnection::makeConfig() const { PIStringList dnl(deviceNames(d)); if (dnl.isEmpty()) dnl << PIString::fromNumber(++dn); piForeachC (PIString & dname, dnl) { - ret << "device." << dname << " = " << d->constructFullPath(); - if (d->mode() == PIIODevice::ReadOnly) ret << " (ro)"; - if (d->mode() == PIIODevice::WriteOnly) ret << " (wo)"; - ret << " #s\n"; + ret << "device." << dname << " = " << d->constructFullPath() << " #s\n"; PIDiagnostics * diag = diags_.value(const_cast(d), 0); if (diag != 0) ret << "device." << dname << ".disconnectTimeout = " << diag->disconnectTimeout() << " #f\n"; @@ -840,10 +837,7 @@ PIDiagnostics * PIConnection::diagnostic(const PIString & full_path_name) const int PIConnection::writeByFullPath(const PIString & full_path, const PIByteArray & data) { - PIString fp(full_path); - if (fp.endsWith(")")) - splitFullPathWithMode(fp, &fp, 0); - fp = PIIODevice::normalizeFullPath(fp); + PIString fp = PIIODevice::normalizeFullPath(full_path); PIIODevice * dev = __device_pool__->device(fp); //piCout << "SEND" << full_path << fp; return write(dev, data); @@ -1091,22 +1085,6 @@ void PIConnection::DevicePool::deviceReaded(PIConnection::DevicePool::DeviceData } -void PIConnection::splitFullPathWithMode(PIString fpwm, PIString * full_path, PIIODevice::DeviceMode * mode) { - PIIODevice::DeviceMode dm = PIIODevice::ReadWrite; - if (fpwm.find("(") > 0 && fpwm.find(")") > 0) { - PIString dms(fpwm.right(fpwm.length() - fpwm.find("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" ")); - //piCout << dms; - if (dms == "r" || dms == "ro" || dms == "read" || dms == "readonly") - dm = PIIODevice::ReadOnly; - if (dms == "w" || dms == "wo" || dms == "write" || dms == "writeonly") - dm = PIIODevice::WriteOnly; - fpwm.cutRight(fpwm.length() - fpwm.find("(")).trim(); - } - if (full_path) *full_path = fpwm; - if (mode) *mode = dm; -} - - bool PIConnection::filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size) { PIPair * p((PIPair * )c); return p->first->filterValidateHeader(p->second, src, rec, size); diff --git a/src/io/piconnection.h b/src/io/piconnection.h index 9b516fb3..f3e1df03 100755 --- a/src/io/piconnection.h +++ b/src/io/piconnection.h @@ -321,8 +321,6 @@ public: EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data) EVENT3(qualityChanged, const PIIODevice * , dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality) - static void splitFullPathWithMode(PIString fpwm, PIString * full_path, PIIODevice::DeviceMode * mode); - //! \events //! \{ diff --git a/src/io/piethernet.cpp b/src/io/piethernet.cpp index 2d288f83..b8c162ba 100755 --- a/src/io/piethernet.cpp +++ b/src/io/piethernet.cpp @@ -495,7 +495,7 @@ bool PIEthernet::listen(bool threaded) { } //#include -int PIEthernet::read(void * read_to, int max_size) { +int PIEthernet::readDevice(void * read_to, int max_size) { //piCout << "read" << sock; if (sock == -1) init(); if (sock == -1 || read_to == 0) return -1; @@ -598,7 +598,7 @@ int PIEthernet::read(void * read_to, int max_size) { } -int PIEthernet::write(const void * data, int max_size) { +int PIEthernet::writeDevice(const void * data, int max_size) { if (sock == -1) init(); if (sock == -1 || !isWriteable()) { //piCoutObj << "Can`t send to uninitialized socket"; @@ -740,8 +740,8 @@ void PIEthernet::propertyChanged(const PIString & name) { } -PIString PIEthernet::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); +PIString PIEthernet::constructFullPathDevice() const { + PIString ret; ret << (type() == PIEthernet::UDP ? "UDP" : "TCP") << ":" << readIP() << ":" << readPort(); if (type() == PIEthernet::UDP) { ret << ":" << sendIP() << ":" << sendPort(); @@ -752,7 +752,7 @@ PIString PIEthernet::constructFullPath() const { } -void PIEthernet::configureFromFullPath(const PIString & full_path) { +void PIEthernet::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); bool mcast = false; for (int i = 0; i < pl.size_s(); ++i) { diff --git a/src/io/piethernet.h b/src/io/piethernet.h index 0f2fbee4..a330b0dd 100755 --- a/src/io/piethernet.h +++ b/src/io/piethernet.h @@ -218,21 +218,9 @@ public: //! Send data "data" to address "ip_port" for UDP bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());} - - - //! Wait for some data and read it to "read_to" - int read(void * read_to, int max_size); - - //! Send data "read_to" with size "max_size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - int write(const void * data, int max_size); - - //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client - int write(const PIByteArray & data) {return write(data.data(), data.size_s());} virtual bool canWrite() const {return mode() & WriteOnly;} - PIString constructFullPath() const; - EVENT1(newConnection, PIEthernet * , client) EVENT0(connected) EVENT1(disconnected, bool, withError) @@ -383,9 +371,12 @@ protected: void propertyChanged(const PIString & name); PIString fullPathPrefix() const {return PIStringAscii("eth");} - void configureFromFullPath(const PIString & full_path); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); - + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int max_size); + //! Executes when any read function was successful. Default implementation does nothing virtual void received(const void * data, int size) {;} diff --git a/src/io/pifile.cpp b/src/io/pifile.cpp index 2de28efd..682f98f3 100755 --- a/src/io/pifile.cpp +++ b/src/io/pifile.cpp @@ -281,12 +281,12 @@ bool PIFile::remove(const PIString & path) { } -PIString PIFile::constructFullPath() const { - return fullPathPrefix() + "://" + path(); +PIString PIFile::constructFullPathDevice() const { + return path(); } -void PIFile::configureFromFullPath(const PIString & full_path) { +void PIFile::configureFromFullPathDevice(const PIString & full_path) { setPath(full_path); } @@ -365,13 +365,13 @@ void PIFile::setPrecision(int prec) { } -int PIFile::read(void * read_to, int max_size) { +int PIFile::readDevice(void * read_to, int max_size) { if (!canRead() || fd == 0) return -1; return fread(read_to, 1, max_size, fd); } -int PIFile::write(const void * data, int max_size) { +int PIFile::writeDevice(const void * data, int max_size) { if (!canWrite() || fd == 0) return -1; return fwrite(data, 1, max_size, fd); } diff --git a/src/io/pifile.h b/src/io/pifile.h index 5a414d61..b1fbd120 100755 --- a/src/io/pifile.h +++ b/src/io/pifile.h @@ -148,15 +148,6 @@ public: void setPrecision(int prec); - //! Read from file to "read_to" no more than "max_size" and return readed bytes count - int read(void * read_to, int max_size); - - //! Write to file "data" with size "max_size" and return written bytes count - int write(const void * data, int max_size); - - //! Write "data" to device - int write(const PIByteArray & data) {return write(data.data(), data.size_s());} - PIFile & writeToBinLog(ushort id, const void * data, int size); /// DEPRECATED @@ -243,8 +234,6 @@ public: //! Read from file text representation of "v" PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;} - PIString constructFullPath() const; - EVENT_HANDLER(void, clear); EVENT_HANDLER(void, remove); EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} @@ -301,7 +290,10 @@ public: protected: PIString fullPathPrefix() const {return "file";} - void configureFromFullPath(const PIString & full_path); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString & full_path); + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int max_size); bool openDevice(); bool closeDevice(); diff --git a/src/io/piiobytearray.cpp b/src/io/piiobytearray.cpp index a8e047a4..01f0f52e 100644 --- a/src/io/piiobytearray.cpp +++ b/src/io/piiobytearray.cpp @@ -54,7 +54,7 @@ bool PIIOByteArray::open(const PIByteArray &buffer) { } -int PIIOByteArray::read(void * read_to, int size) { +int PIIOByteArray::readDevice(void * read_to, int size) { // piCout << "PIIOByteArray::read" << data_ << size << canRead(); if (!canRead() || !data_) return -1; int ret = piMini(size, data_->size_s() - pos); @@ -67,7 +67,7 @@ int PIIOByteArray::read(void * read_to, int size) { } -int PIIOByteArray::write(const void * data, int size) { +int PIIOByteArray::writeDevice(const void * data, int size) { // piCout << "PIIOByteArray::write" << data << size << canWrite(); if (!canWrite() || !data) return -1; //piCout << "write" << data; diff --git a/src/io/piiobytearray.h b/src/io/piiobytearray.h index afc1d426..975b92ba 100644 --- a/src/io/piiobytearray.h +++ b/src/io/piiobytearray.h @@ -3,7 +3,7 @@ */ /* PIP - Platform Independent Primitives - PIIODevice wrapper around PIString + PIIODevice wrapper around PIByteArray Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify @@ -65,15 +65,14 @@ public: void seekToEnd() {if (data_) pos = data_->size_s();} - int read(void * read_to, int size); - int write(const void * data_, int size); - //! Insert data \"ba\" into content at current position int writeByteArray(const PIByteArray & ba); protected: bool openDevice(); - + int readDevice(void * read_to, int size); + int writeDevice(const void * data_, int size); + ssize_t pos; PIByteArray * data_; diff --git a/src/io/piiodevice.cpp b/src/io/piiodevice.cpp index eb31cc62..f6ecebc2 100755 --- a/src/io/piiodevice.cpp +++ b/src/io/piiodevice.cpp @@ -140,12 +140,27 @@ PIIODevice::~PIIODevice() { } +void PIIODevice::setOptions(PIIODevice::DeviceOptions o) { + options_ = o; + optionsChanged(); +} + + +bool PIIODevice::setOption(PIIODevice::DeviceOption o, bool yes) { + bool ret = isOptionSet(o); + options_.setFlag(o, yes); + optionsChanged(); + return ret; +} + + void PIIODevice::_init() { opened_ = init_ = thread_started_ = false; raise_threaded_read_ = true; ret_func_ = 0; ret_data_ = 0; tri = 0; + setOptions(0); setReopenEnabled(true); setReopenTimeout(1000); setThreadedReadBufferSize(4096); @@ -284,6 +299,62 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio } +PIString PIIODevice::constructFullPath() const { + return fullPathPrefix() + "://" + constructFullPathDevice() + fullPathOptions(); +} + + +void PIIODevice::configureFromFullPath(const PIString & full_path) { + PIString fp; + DeviceMode dm = ReadWrite; + DeviceOptions op = 0; + splitFullPath(full_path, &fp, &dm, &op); + setMode(dm); + setOptions(op); + configureFromFullPathDevice(fp); +} + + +void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode, DeviceOptions * opts) { + int dm = 0; + DeviceOptions op = 0; + if (fpwm.find("(") > 0 && fpwm.find(")") > 0) { + PIString dms(fpwm.right(fpwm.length() - fpwm.findLast("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" ")); + PIStringList opts(dms.split(",")); + piForeachC (PIString & o, opts) { + //piCout << dms; + if (o == "r" || o == "ro" || o == "read" || o == "readonly") + dm |= ReadOnly; + if (o == "w" || o == "wo" || o == "write" || o == "writeonly") + dm |= WriteOnly; + if (o == "br" || o == "blockr" || o == "blockread" || o == "blockingread") + op |= BlockingRead; + if (o == "bw" || o == "blockw" || o == "blockwrite" || o == "blockingwrite") + op |= BlockingRead; + if (o == "brw" || o == "bwr" || o == "blockrw" || o == "blockwr" || o == "blockreadrite" || o == "blockingreadwrite") + op |= BlockingRead | BlockingWrite; + } + fpwm.cutRight(fpwm.length() - fpwm.findLast("(")).trim(); + } + if (dm == 0) dm = ReadWrite; + if (full_path) *full_path = fpwm; + if (mode) *mode = (DeviceMode)dm; + if (opts) *opts = op; +} + + +PIString PIIODevice::fullPathOptions() const { + if (mode_ == ReadWrite && options_ == 0) return PIString(); + PIString ret(" ("); + bool f = true; + if (mode_ == ReadOnly) {if (!f) ret += ","; f = false; ret += "ro";} + if (mode_ == WriteOnly) {if (!f) ret += ","; f = false; ret += "wo";} + if (options_[BlockingRead]) {if (!f) ret += ","; f = false; ret += "br";} + if (options_[BlockingWrite]) {if (!f) ret += ","; f = false; ret += "bw";} + return ret + ")"; +} + + PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) { PIString prefix = full_path.left(full_path.find(":")); if (prefix.isEmpty()) return 0; @@ -306,15 +377,10 @@ PIString PIIODevice::normalizeFullPath(const PIString & full_path) { PIString ret = nfp_cache.value(full_path); if (!ret.isEmpty()) return ret; - //piCout << "normalizeFullPath" << full_path; - PIString fp; PIIODevice::DeviceMode md; - PIConnection::splitFullPathWithMode(full_path, &fp, &md); - PIIODevice * d = createFromFullPath(fp); + PIIODevice * d = createFromFullPath(full_path); //piCout << "normalizeFullPath" << d; if (d == 0) return PIString(); ret = d->constructFullPath(); - if (md == PIIODevice::ReadOnly) ret += " (ro)"; - if (md == PIIODevice::WriteOnly) ret += " (wo)"; delete d; nfp_cache[full_path] = ret; return ret; diff --git a/src/io/piiodevice.h b/src/io/piiodevice.h index 9bc75944..af2da378 100755 --- a/src/io/piiodevice.h +++ b/src/io/piiodevice.h @@ -63,6 +63,14 @@ public: ReadWrite /*! Device can both read and write */ = 0x03 }; + //! \brief Options for PIIODevice, works with some devices + enum DeviceOption { + BlockingRead /*! \a read block until data is received, default off */ = 0x01, + BlockingWrite /*! \a write block until data is sent, default off */ = 0x02 + }; + + typedef PIFlags DeviceOptions; + PIIODevice(const PIString & path, DeviceMode mode = ReadWrite); virtual ~PIIODevice(); @@ -71,7 +79,19 @@ public: //! Set open mode of device void setMode(DeviceMode m) {mode_ = m;} - + + //! Current device options + DeviceOptions options() const {return options_;} + + //! Current device option "o" state + bool isOptionSet(DeviceOption o) const {return options_[o];} + + //! Set device options + void setOptions(DeviceOptions o); + + //! Set device option "o" to "yes" and return previous state + bool setOption(DeviceOption o, bool yes = true); + //! Current path of device PIString path() const {return property(PIStringAscii("path")).toString();} @@ -168,22 +188,22 @@ public: void stop(bool wait = false) {stopThreadedRead(); stopThreadedWrite(); if (wait) while (write_thread.isRunning() || isRunning()) msleep(1);} - //! Reimplement this function to read from your device - virtual int read(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;} + //! Read from device maximum "max_size" bytes to "read_to" + int read(void * read_to, int max_size) {return readDevice(read_to, max_size);} - //! Reimplement this function to write to your device - virtual int write(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;} - - //! Read from device maximum "max_size" bytes and return them as PIByteArray - PIByteArray read(int max_size) {buffer_in.resize(max_size); int ret = read(buffer_in.data(), max_size); if (ret < 0) return PIByteArray(); return buffer_in.resized(ret);} + PIByteArray read(int max_size) {buffer_in.resize(max_size); int ret = readDevice(buffer_in.data(), max_size); if (ret < 0) return PIByteArray(); return buffer_in.resized(ret);} + + //! Write maximum "max_size" bytes of "data" to device + int write(const void * data, int max_size) {return writeDevice(data, max_size);} + + //! Write "data" to device + int write(const PIByteArray & data) {return writeDevice(data.data(), data.size_s());} + //! Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray. Timeout should to be greater than 0 PIByteArray readForTime(double timeout_ms); - //! Write "data" to device - int write(const PIByteArray & data) {return write(data.data(), data.size_s());} - //! Add task to threaded write queue and return task ID ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));} @@ -200,15 +220,20 @@ public: virtual PIString fullPathPrefix() const {return PIString();} //! Reimplement to construct full unambiguous string, describes this device, default returns \a fullPathPrefix() + "://" + \a path() - virtual PIString constructFullPath() const {return fullPathPrefix() + "://" + path();} - + PIString constructFullPath() const; + + //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing + void configureFromFullPath(const PIString & full_path); + //! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. //! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". //! See \ref PIIODevice_sec7 static PIIODevice * createFromFullPath(const PIString & full_path); static PIString normalizeFullPath(const PIString & full_path); - + + static void splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode = 0, DeviceOptions * opts = 0); + EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} @@ -262,7 +287,7 @@ public: //! \brief Raise if read thread succesfull read some data //! \fn void threadedWriteEvent(ullong id, int written_size) - //! \brief Raise if write thread succesfull write some data of task with ID "id" + //! \brief Raise if write thread successfull write some data of task with ID "id" //! \} //! \ioparams @@ -292,19 +317,31 @@ protected: //! Reimplement to close device, inverse return value will be set to "opened_" variable virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables - + + //! Reimplement this function to read from your device + virtual int readDevice(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;} + + //! Reimplement this function to write to your device + virtual int writeDevice(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;} + //! Function executed when thread read some data, default implementation execute external slot "ret_func_" virtual bool threadedRead(uchar * readed, int size); - + //! Reimplement to construct full unambiguous string, describes this device. Default implementation returns \a path() + virtual PIString constructFullPathDevice() const {return path();} + //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing - virtual void configureFromFullPath(const PIString & full_path) {;} - + virtual void configureFromFullPathDevice(const PIString & full_path) {;} + + //! Reimplement to apply new device options + virtual void optionsChanged() {;} + void terminate(); DeviceMode mode_; + DeviceOptions options_; ReadRetFunc ret_func_; bool opened_; void * ret_data_; @@ -314,6 +351,7 @@ private: EVENT_HANDLER(void, write_func); virtual PIIODevice * copy() const {return 0;} + PIString fullPathOptions() const; void _init(); void begin(); void run(); diff --git a/src/io/piiostring.cpp b/src/io/piiostring.cpp index fce16fdd..1a1937ea 100644 --- a/src/io/piiostring.cpp +++ b/src/io/piiostring.cpp @@ -64,7 +64,7 @@ PIString PIIOString::readLine() { } -int PIIOString::read(void * read_to, int max_size) { +int PIIOString::readDevice(void * read_to, int max_size) { if (!canRead() || !str) return -1; PIString rs = str->mid(pos, max_size); pos += max_size; @@ -75,7 +75,7 @@ int PIIOString::read(void * read_to, int max_size) { } -int PIIOString::write(const void * data, int max_size) { +int PIIOString::writeDevice(const void * data, int max_size) { if (!canWrite() || !str) return -1; //piCout << "write" << data; if (pos > str->size_s()) pos = str->size_s(); diff --git a/src/io/piiostring.h b/src/io/piiostring.h index 7181d595..78d3886d 100644 --- a/src/io/piiostring.h +++ b/src/io/piiostring.h @@ -68,15 +68,14 @@ public: //! Read one text line and return it PIString readLine(); - int read(void * read_to, int max_size); - int write(const void * data, int max_size); - //! Insert string \"string\" into content at current position int writeString(const PIString & string); protected: bool openDevice(); - + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int max_size); + ssize_t pos; PIString * str; diff --git a/src/io/pipacketextractor.cpp b/src/io/pipacketextractor.cpp index 217ef5db..6ab9d421 100755 --- a/src/io/pipacketextractor.cpp +++ b/src/io/pipacketextractor.cpp @@ -296,6 +296,6 @@ bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { } -PIString PIPacketExtractor::constructFullPath() const { - return fullPathPrefix() + "://"; +PIString PIPacketExtractor::constructFullPathDevice() const { + return ""; } diff --git a/src/io/pipacketextractor.h b/src/io/pipacketextractor.h index c8760786..07ec78b9 100755 --- a/src/io/pipacketextractor.h +++ b/src/io/pipacketextractor.h @@ -119,14 +119,6 @@ public: // //! Returns pointer to \a missedPackets() count. Useful for output to PIConsole const ullong * missedPackets_ptr() const {return &missed_packets;} - //! Directly call \a read() function of child %device - int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);} - - //! Directly call \a write() function of child %device - int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} - - PIString constructFullPath() const; - EVENT2(packetReceived, uchar * , data, int, size) //! \events @@ -162,8 +154,11 @@ protected: private: void construct(); void propertyChanged(const PIString & ); + int readDevice(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);} + int writeDevice(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} bool threadedRead(uchar * readed, int size); PIString fullPathPrefix() const {return "pckext";} + PIString constructFullPathDevice() const; bool openDevice() {if (dev == 0) return false; return dev->open();} PIIODevice * dev; diff --git a/src/io/pipeer.cpp b/src/io/pipeer.cpp index d09a8f75..03b42cb4 100755 --- a/src/io/pipeer.cpp +++ b/src/io/pipeer.cpp @@ -907,14 +907,14 @@ void PIPeer::changeName(const PIString &new_name) { } -PIString PIPeer::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); +PIString PIPeer::constructFullPathDevice() const { + PIString ret; ret << self_info.name << ":" << trustPeerName(); return ret; } -int PIPeer::read(void *read_to, int max_size) { +int PIPeer::readDevice(void *read_to, int max_size) { read_buffer_mutex.lock(); bool empty = read_buffer.isEmpty(); read_buffer_mutex.unlock(); @@ -937,7 +937,7 @@ int PIPeer::read(void *read_to, int max_size) { } -int PIPeer::write(const void *data, int size) { +int PIPeer::writeDevice(const void *data, int size) { if (trust_peer.isEmpty()) { sendToAll(data, size); return size; @@ -956,7 +956,7 @@ void PIPeer::newTcpClient(PIEthernet *client) { } -void PIPeer::configureFromFullPath(const PIString & full_path) { +void PIPeer::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); diff --git a/src/io/pipeer.h b/src/io/pipeer.h index f0a53d7b..989f15d0 100755 --- a/src/io/pipeer.h +++ b/src/io/pipeer.h @@ -135,9 +135,6 @@ public: const PIString & trustPeerName() const {return trust_peer;} void setTrustPeerName(const PIString & peer_name) {trust_peer = peer_name;} void setTcpServerIP(const PIString & ip) {server_ip = ip; tcpClientReconnect();} - PIString constructFullPath() const; - int read(void * read_to, int max_size); - int write(const void * data, int size); EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data) @@ -148,7 +145,7 @@ protected: virtual void dataReceived(const PIString & from, const PIByteArray & data) {;} virtual void peerConnected(const PIString & name) {;} virtual void peerDisconnected(const PIString & name) {;} - + EVENT_HANDLER2(bool, dataRead, uchar *, readed, int, size); EVENT_HANDLER2(bool, mbcastRead, uchar *, readed, int, size); @@ -184,7 +181,10 @@ private: bool openDevice(); bool closeDevice(); PIString fullPathPrefix() const {return "peer";} - void configureFromFullPath(const PIString &full_path); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString &full_path); + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int size); PeerInfo * quickestPeer(const PIString & to); diff --git a/src/io/piserial.cpp b/src/io/piserial.cpp index e279260b..c1570832 100755 --- a/src/io/piserial.cpp +++ b/src/io/piserial.cpp @@ -165,8 +165,6 @@ void PISerial::construct() { fd = -1; piMonitor.serials++; setPriority(piHigh); - block_read = false; - block_write = true; vtime = 10; sending = false; setParameters(0); @@ -358,23 +356,25 @@ bool PISerial::read(void * data, int size, double timeout_ms) { if (data == 0 || size <= 0) return false; int ret, all = 0; if (timeout_ms > 0.) { - setReadIsBlocking(false); - all = read(data, 1); + bool br = setOption(BlockingRead, false); + all = readDevice(data, 1); tm_.reset(); while (all < size && tm_.elapsed_m() < timeout_ms) { - ret = read(&((uchar * )data)[all], size - all); + ret = readDevice(&((uchar * )data)[all], size - all); if (ret > 0) all += ret; else msleep(1); } + setOption(BlockingRead, br); received(data, all); return (all == size); } else { - setReadIsBlocking(true); - all = read(data, 1); + bool br = setOption(BlockingRead, true); + all = readDevice(data, 1); while (all < size) { - ret = read(&((uchar * )data)[all], size - all); + ret = readDevice(&((uchar * )data)[all], size - all); if (ret > 0) all += ret; } + setOption(BlockingRead, br); received(data, all); return (all == size); } @@ -396,17 +396,17 @@ PIString PISerial::read(int size, double timeout_ms) { int ret, all = 0; uchar td[1024]; if (timeout_ms > 0.) { - setReadIsBlocking(false); + bool br = setOption(BlockingRead, false); tm_.reset(); if (size <= 0) { while (tm_.elapsed_m() < timeout_ms) { - ret = read(td, 1024); + ret = readDevice(td, 1024); if (ret <= 0) msleep(1); else str << PIString((char*)td, ret); } } else { while (all < size && tm_.elapsed_m() < timeout_ms) { - ret = read(td, size - all); + ret = readDevice(td, size - all); if (ret <= 0) msleep(1); else { str << PIString((char*)td, ret); @@ -414,18 +414,20 @@ PIString PISerial::read(int size, double timeout_ms) { } } } + setOption(BlockingRead, br); } else { - setReadIsBlocking(true); - all = read(td, 1); + bool br = setOption(BlockingRead, true); + all = readDevice(td, 1); str << PIString((char*)td, all); while (all < size) { - ret = read(td, size - all); + ret = readDevice(td, size - all); if (ret <= 0) msleep(1); else { str << PIString((char*)td, ret); all += ret; } } + setOption(BlockingRead, br); } received(str.data(), str.size_s()); return str; @@ -446,17 +448,17 @@ PIByteArray PISerial::readData(int size, double timeout_ms) { int ret, all = 0; uchar td[1024]; if (timeout_ms > 0.) { - setReadIsBlocking(false); + bool br = setOption(BlockingRead, false); tm_.reset(); if (size <= 0) { while (tm_.elapsed_m() < timeout_ms) { - ret = read(td, 1024); + ret = readDevice(td, 1024); if (ret <= 0) msleep(1); else str.append(td, ret); } } else { while (all < size && tm_.elapsed_m() < timeout_ms) { - ret = read(td, size - all); + ret = readDevice(td, size - all); if (ret <= 0) msleep(1); else { str.append(td, ret); @@ -464,18 +466,20 @@ PIByteArray PISerial::readData(int size, double timeout_ms) { } } } + setOption(BlockingRead, br); } else { - setReadIsBlocking(true); - all = read(td, 1); + bool br = setOption(BlockingRead, true); + all = readDevice(td, 1); str.append(td, all); while (all < size) { - ret = read(td, size - all); + ret = readDevice(td, size - all); if (ret <= 0) msleep(1); else { str.append(td, ret); all += ret; } } + setOption(BlockingRead, br); } received(str.data(), str.size_s()); return str; @@ -594,36 +598,25 @@ void PISerial::applySettings() { void PISerial::setTimeouts() { #ifdef WINDOWS COMMTIMEOUTS times; - times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD; - times.ReadTotalTimeoutConstant = block_read ? 0 : 1; - times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD; - times.WriteTotalTimeoutConstant = block_write ? 0 : 1; + times.ReadIntervalTimeout = isOptionSet(BlockingRead) ? vtime : MAXDWORD; + times.ReadTotalTimeoutConstant = isOptionSet(BlockingRead) ? 0 : 1; + times.ReadTotalTimeoutMultiplier = isOptionSet(BlockingRead) ? 0 : MAXDWORD; + times.WriteTotalTimeoutConstant = isOptionSet(BlockingWrite) ? 0 : 1; times.WriteTotalTimeoutMultiplier = 0; if (SetCommTimeouts(PRIVATE->hCom, ×) == -1) piCoutObj << "Unable to set timeouts for \"" << path() << "\""; #else - fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK); + fcntl(fd, F_SETFL, isOptionSet(BlockingRead) ? 0 : O_NONBLOCK); #endif } -void PISerial::setReadIsBlocking(bool yes) { - block_read = yes; - if (isOpened()) setTimeouts(); -} - -void PISerial::setWriteIsBlocking(bool yes) { - block_write = yes; - if (isOpened()) setTimeouts(); -} - - /** \brief Basic read function * \details Read to pointer "read_to" no more than "max_size". If read is * set to blocking this function will be wait at least one byte. * \returns Readed bytes count * \sa \a readData() */ -int PISerial::read(void * read_to, int max_size) { +int PISerial::readDevice(void * read_to, int max_size) { #ifdef WINDOWS if (!canRead()) return -1; if (sending) return -1; @@ -640,7 +633,7 @@ int PISerial::read(void * read_to, int max_size) { } -int PISerial::write(const void * data, int max_size) { +int PISerial::writeDevice(const void * data, int max_size) { if (fd == -1 || !canWrite()) { //piCoutObj << "Can`t write to uninitialized COM"; return -1; @@ -661,7 +654,7 @@ int PISerial::write(const void * data, int max_size) { #else int wrote; wrote = ::write(fd, data, max_size); - if (block_write) tcdrain(fd); + if (isOptionSet(BlockingWrite)) tcdrain(fd); #endif return (int)wrote; //piCoutObj << "Error while sending"; @@ -681,8 +674,8 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) { } -PIString PISerial::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); +PIString PISerial::constructFullPathDevice() const { + PIString ret; ret << path() << ":" << int(inSpeed()) << ":" << dataBitsCount(); if (parameters()[ParityControl]) { if (parameters()[ParityOdd]) ret << ":O"; @@ -690,19 +683,16 @@ PIString PISerial::constructFullPath() const { } else ret << ":N"; if (parameters()[TwoStopBits]) ret << ":2"; else ret << ":1"; - ret << ":block"; - if (block_read) ret << "R"; - if (block_write) ret << "W"; return ret; } -void PISerial::configureFromFullPath(const PIString & full_path) { +void PISerial::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); switch (i) { - case 0: setProperty(PIStringAscii("path"), p); break; + case 0: setProperty("path", p); break; case 1: setProperty("outSpeed", p.toInt()); setProperty("inSpeed", p.toInt()); break; case 2: setProperty("dataBitsCount", p.toInt()); break; case 3: @@ -711,25 +701,6 @@ void PISerial::configureFromFullPath(const PIString & full_path) { if (p == "o") setParameter(ParityOdd); break; case 4: if (p.toInt() == 2) setParameter(TwoStopBits); break; - case 5: - p = p.toLowerCase(); - PIString bs = "block"; - if (bs == p.mid(0, bs.length())) { - block_write = false; - block_read = false; - p = p.mid(bs.length()); - if (p == "r") { - block_read = true; - } - if (p == "w") { - block_write = true; - } - if (p == "rw" || p == "wr") { - block_read = true; - block_write = true; - } - } - break; } } applySettings(); @@ -847,3 +818,8 @@ PIStringList PISerial::availableDevices(bool test) { } return dl; } + + +void PISerial::optionsChanged() { + if (isOpened()) setTimeouts(); +} diff --git a/src/io/piserial.h b/src/io/piserial.h index 41bd9949..aca32f4d 100755 --- a/src/io/piserial.h +++ b/src/io/piserial.h @@ -138,12 +138,6 @@ public: void setVTime(int t) {vtime = t; applySettings();} - - //! Set read is blocking for function \a read - void setReadIsBlocking(bool yes); - - //! Set write is blocking for functions \a write and \a send - void setWriteIsBlocking(bool yes); //! Returns device name @@ -162,16 +156,12 @@ public: void flush(); - int read(void * read_to, int max_size); + int read(void * read_to, int max_size) {return readDevice(read_to, max_size);} bool read(void * read_to, int max_size, double timeout_ms); PIString read(int size = -1, double timeout_ms = 1000.); PIByteArray readData(int size = -1, double timeout_ms = 1000.); - //! \brief Write to device data "data" with maximum size "max_size" and wait for data written if "wait" is \b true. - //! \returns sended bytes count - int write(const void * data, int max_size); - //! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true. //! \returns \b true if sended bytes count = "size" bool send(const void * data, int size) {return (write(data, size) == size);} @@ -184,9 +174,6 @@ public: //! \brief Write to device byte array "data" and wait for data written if "wait" is \b true. //! \returns \b true if sended bytes count = size of string bool send(const PIByteArray & data) {return (write(data.data(), data.size_s()) == data.size_s());} - - PIString constructFullPath() const; - //! \brief Returns all available speeds for serial devices static PIVector availableSpeeds(); @@ -219,9 +206,12 @@ public: protected: PIString fullPathPrefix() const {return "ser";} - void configureFromFullPath(const PIString & full_path); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); -// int write(const void * data, int max_size) {return write(data, max_size);} + void optionsChanged(); + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int max_size); //! Executes when any read function was successful. Default implementation does nothing virtual void received(const void * data, int size) {;} @@ -238,7 +228,7 @@ protected: PRIVATE_DECLARATION int fd, vtime; - bool block_read, block_write, sending; + bool sending; PITimeMeasurer tm_; }; diff --git a/src/io/pisharedmemory.h b/src/io/pisharedmemory.h index d64e46c5..43e74ebc 100644 --- a/src/io/pisharedmemory.h +++ b/src/io/pisharedmemory.h @@ -71,6 +71,8 @@ public: protected: bool openDevice(); bool closeDevice(); + int readDevice(void * read_to, int max_size) {return read(read_to, max_size, 0);} + int writeDevice(const void * data, int max_size) {return write(data, max_size, 0);} private: void initPrivate(); diff --git a/src/io/piusb.cpp b/src/io/piusb.cpp index 4f96b8a9..5b75a890 100755 --- a/src/io/piusb.cpp +++ b/src/io/piusb.cpp @@ -295,7 +295,7 @@ bool PIUSB::closeDevice() { } -int PIUSB::read(void * read_to, int max_size) { +int PIUSB::readDevice(void * read_to, int max_size) { #ifdef PIP_USB if (isClosed() || ep_read.isNull()) return -1; switch (ep_read.transfer_type) { @@ -310,7 +310,7 @@ int PIUSB::read(void * read_to, int max_size) { } -int PIUSB::write(const void * data, int max_size) { +int PIUSB::writeDevice(const void * data, int max_size) { #ifdef PIP_USB if (isClosed() || ep_write.isNull()) return -1; switch (ep_read.transfer_type) { @@ -387,14 +387,14 @@ PICout operator<<(PICout s, const PIUSB::Endpoint & v) { } -PIString PIUSB::constructFullPath() const { - PIString ret(fullPathPrefix() + "://"); +PIString PIUSB::constructFullPathDevice() const { + PIString ret; ret << PIString::fromNumber(vendorID(), 16).toLowerCase() << ":" << PIString::fromNumber(productID(), 16).toLowerCase() << ":" << deviceNumber() << ":" << endpointRead().address << ":" << endpointWrite().address; return ret; } -void PIUSB::configureFromFullPath(const PIString & full_path) { +void PIUSB::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); diff --git a/src/io/piusb.h b/src/io/piusb.h index 4a94c61b..8b1169d5 100755 --- a/src/io/piusb.h +++ b/src/io/piusb.h @@ -121,18 +121,17 @@ public: void setTimeoutRead(int t) {setProperty("timeoutRead", t);} void setTimeoutWrite(int t) {setProperty("timeoutWrite", t);} - int read(void * read_to, int max_size); - int write(const void * data, int max_size); int controlWrite(const void * data, int max_size); void flush(); - PIString constructFullPath() const; - protected: PIString fullPathPrefix() const {return "usb";} - void configureFromFullPath(const PIString & full_path); bool configureDevice(const void * e_main, const void * e_parent = 0); + PIString constructFullPathDevice() const; + void configureFromFullPathDevice(const PIString & full_path); + int readDevice(void * read_to, int max_size); + int writeDevice(const void * data, int max_size); //bool init(); bool openDevice(); bool closeDevice(); diff --git a/src/piversion.h b/src/piversion.h index 18535a93..35e63398 100644 --- a/src/piversion.h +++ b/src/piversion.h @@ -3,7 +3,7 @@ #define PIVERSION_H #define PIP_VERSION_MAJOR 0 -#define PIP_VERSION_MINOR 6 +#define PIP_VERSION_MINOR 7 #define PIP_VERSION_REVISION 0 #define PIP_VERSION_SUFFIX ""