#pragma once #ifndef ASYNCSERIAL_H #define ASYNCSERIAL_H #include // for size_t #include "../main/Noncopyable.h" #include // for serial_port_base #include //for exception printing namespace boost { namespace system { class error_code; } // namespace system } // namespace boost /** * Used internally (pimpl) */ class AsyncSerialImpl; /** * Asynchronous serial class. * Intended to be a base class. */ class AsyncSerial : private domoticz::noncopyable { public: AsyncSerial(); /** * Constructor. Creates and opens a serial device. * \param devname serial device name, example "/dev/ttyS0" or "COM1" * \param baud_rate serial baud rate * \param opt_parity serial parity, default none * \param opt_csize serial character size, default 8bit * \param opt_flow serial flow control, default none * \param opt_stop serial stop bits, default 1 * \throws boost::system::system_error if cannot open the * serial device */ AsyncSerial(const std::string &devname, unsigned int baud_rate, boost::asio::serial_port_base::parity opt_parity = boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none), boost::asio::serial_port_base::character_size opt_csize = boost::asio::serial_port_base::character_size(8), boost::asio::serial_port_base::flow_control opt_flow = boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none), boost::asio::serial_port_base::stop_bits opt_stop = boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); /** * Opens a serial device. * \param devname serial device name, example "/dev/ttyS0" or "COM1" * \param baud_rate serial baud rate * \param opt_parity serial parity, default none * \param opt_csize serial character size, default 8bit * \param opt_flow serial flow control, default none * \param opt_stop serial stop bits, default 1 * \throws boost::system::system_error if cannot open the * serial device */ void open(const std::string &devname, unsigned int baud_rate, boost::asio::serial_port_base::parity opt_parity = boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none), boost::asio::serial_port_base::character_size opt_csize = boost::asio::serial_port_base::character_size(8), boost::asio::serial_port_base::flow_control opt_flow = boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none), boost::asio::serial_port_base::stop_bits opt_stop = boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); void openOnlyBaud(const std::string &devname, unsigned int baud_rate, boost::asio::serial_port_base::parity opt_parity = boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none), boost::asio::serial_port_base::character_size opt_csize = boost::asio::serial_port_base::character_size(8), boost::asio::serial_port_base::flow_control opt_flow = boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none), boost::asio::serial_port_base::stop_bits opt_stop = boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); /** * \return true if serial device is open */ bool isOpen() const; /** * \return true if error were found */ bool errorStatus() const; /** * Close the serial device * \throws boost::system::system_error if any error */ void close(); /** * Write data asynchronously. Returns immediately. * \param data array of char to be sent through the serial device * \param size array size */ void write(const char *data, size_t size); /** * Write data asynchronously. Returns immediately. * \param data to be sent through the serial device */ void write(const std::vector &data); /** * Write data asynchronously. Returns immediately. * \param string to be sent through the serial device */ void write(const std::string &data); /** * Write a string asynchronously. Returns immediately. * Can be used to send ASCII data to the serial device. * To send binary data, use write() * \param s string to send */ void writeString(const std::string &s); /** * Destructor. If necessary it silently removes the read callback and close the serial port. */ ~AsyncSerial(); private: /** * Callback to close serial port */ void doClose(); /** * Callback called to start an asynchronous read operation. * This callback is called by the io_service in the spawned thread. */ void doRead(); /** * Callback called at the end of the asynchronous operation. * This callback is called by the io_service in the spawned thread. */ void readEnd(const boost::system::error_code &error, size_t bytes_transferred); /** * Callback called to start an asynchronous write operation. * If it is already in progress, does nothing. * This callback is called by the io_service in the spawned thread. */ void doWrite(); /** * Callback called at the end of an asynchronuous write operation, * if there is more data to write, restarts a new write operation. * This callback is called by the io_service in the spawned thread. */ void writeEnd(const boost::system::error_code &error); std::shared_ptr pimpl; /** * To allow derived classes to report errors * \param e error status */ void setErrorStatus(bool e); protected: /** * To allow derived classes to set a read callback */ void setReadCallback(const std::function &callback); /** * Unregister the read callback. */ void clearReadCallback(); /** * Process a clean close by unregistering the read callback and closing the port. * Once this method has been called, you have to open the port and register the read callback again. */ void terminate(bool silent = true); }; #endif // ASYNCSERIAL_H