1 #pragma once
2 #ifndef ASYNCSERIAL_H
3 #define	ASYNCSERIAL_H
4 
5 #include <stddef.h>                              // for size_t
6 #include "../main/Noncopyable.h"
7 #include <boost/asio/serial_port_base.hpp>       // for serial_port_base
8 #include <boost/smart_ptr/shared_ptr.hpp>        // for shared_ptr
9 #include <boost/function/function_fwd.hpp>       // for function
10 #include <boost/exception/diagnostic_information.hpp> //for exception printing
11 namespace boost { namespace system { class error_code; } }
12 
13 /**
14  * Used internally (pimpl)
15  */
16 class AsyncSerialImpl;
17 
18 /**
19  * Asynchronous serial class.
20  * Intended to be a base class.
21  */
22 class AsyncSerial
23 	: private domoticz::noncopyable
24 {
25 public:
26     AsyncSerial();
27 
28     /**
29      * Constructor. Creates and opens a serial device.
30      * \param devname serial device name, example "/dev/ttyS0" or "COM1"
31      * \param baud_rate serial baud rate
32      * \param opt_parity serial parity, default none
33      * \param opt_csize serial character size, default 8bit
34      * \param opt_flow serial flow control, default none
35      * \param opt_stop serial stop bits, default 1
36      * \throws boost::system::system_error if cannot open the
37      * serial device
38      */
39     AsyncSerial(const std::string& devname, unsigned int baud_rate,
40         boost::asio::serial_port_base::parity opt_parity=
41             boost::asio::serial_port_base::parity(
42                 boost::asio::serial_port_base::parity::none),
43         boost::asio::serial_port_base::character_size opt_csize=
44             boost::asio::serial_port_base::character_size(8),
45         boost::asio::serial_port_base::flow_control opt_flow=
46             boost::asio::serial_port_base::flow_control(
47                 boost::asio::serial_port_base::flow_control::none),
48         boost::asio::serial_port_base::stop_bits opt_stop=
49             boost::asio::serial_port_base::stop_bits(
50                 boost::asio::serial_port_base::stop_bits::one));
51 
52     /**
53     * Opens a serial device.
54     * \param devname serial device name, example "/dev/ttyS0" or "COM1"
55     * \param baud_rate serial baud rate
56     * \param opt_parity serial parity, default none
57     * \param opt_csize serial character size, default 8bit
58     * \param opt_flow serial flow control, default none
59     * \param opt_stop serial stop bits, default 1
60     * \throws boost::system::system_error if cannot open the
61     * serial device
62     */
63     void open(const std::string& devname, unsigned int baud_rate,
64         boost::asio::serial_port_base::parity opt_parity=
65             boost::asio::serial_port_base::parity(
66                 boost::asio::serial_port_base::parity::none),
67         boost::asio::serial_port_base::character_size opt_csize=
68             boost::asio::serial_port_base::character_size(8),
69         boost::asio::serial_port_base::flow_control opt_flow=
70             boost::asio::serial_port_base::flow_control(
71                 boost::asio::serial_port_base::flow_control::none),
72         boost::asio::serial_port_base::stop_bits opt_stop=
73             boost::asio::serial_port_base::stop_bits(
74                 boost::asio::serial_port_base::stop_bits::one));
75 	void openOnlyBaud(const std::string& devname, unsigned int baud_rate,
76 		boost::asio::serial_port_base::parity opt_parity=
77 		boost::asio::serial_port_base::parity(
78 		boost::asio::serial_port_base::parity::none),
79 		boost::asio::serial_port_base::character_size opt_csize=
80 		boost::asio::serial_port_base::character_size(8),
81 		boost::asio::serial_port_base::flow_control opt_flow=
82 		boost::asio::serial_port_base::flow_control(
83 		boost::asio::serial_port_base::flow_control::none),
84 		boost::asio::serial_port_base::stop_bits opt_stop=
85 		boost::asio::serial_port_base::stop_bits(
86 		boost::asio::serial_port_base::stop_bits::one));
87 
88     /**
89      * \return true if serial device is open
90      */
91     bool isOpen() const;
92 
93     /**
94      * \return true if error were found
95      */
96     bool errorStatus() const;
97 
98     /**
99      * Close the serial device
100      * \throws boost::system::system_error if any error
101      */
102     void close();
103 
104     /**
105      * Write data asynchronously. Returns immediately.
106      * \param data array of char to be sent through the serial device
107      * \param size array size
108      */
109     void write(const char *data, size_t size);
110 
111      /**
112      * Write data asynchronously. Returns immediately.
113      * \param data to be sent through the serial device
114      */
115     void write(const std::vector<char>& data);
116 
117 	/**
118 	* Write data asynchronously. Returns immediately.
119 	* \param string to be sent through the serial device
120 	*/
121 	void write(const std::string &data);
122 
123     /**
124     * Write a string asynchronously. Returns immediately.
125     * Can be used to send ASCII data to the serial device.
126     * To send binary data, use write()
127     * \param s string to send
128     */
129     void writeString(const std::string& s);
130 
131 	/**
132 	 * Destructor. If necessary it silently removes the read callback and close the serial port.
133 	 */
134 	~AsyncSerial();
135 
136 private:
137     /**
138      * Callback to close serial port
139      */
140     void doClose();
141 
142     /**
143      * Callback called to start an asynchronous read operation.
144      * This callback is called by the io_service in the spawned thread.
145      */
146     void doRead();
147 
148     /**
149      * Callback called at the end of the asynchronous operation.
150      * This callback is called by the io_service in the spawned thread.
151      */
152     void readEnd(const boost::system::error_code& error,
153         size_t bytes_transferred);
154 
155     /**
156      * Callback called to start an asynchronous write operation.
157      * If it is already in progress, does nothing.
158      * This callback is called by the io_service in the spawned thread.
159      */
160     void doWrite();
161 
162     /**
163      * Callback called at the end of an asynchronuous write operation,
164      * if there is more data to write, restarts a new write operation.
165      * This callback is called by the io_service in the spawned thread.
166      */
167     void writeEnd(const boost::system::error_code& error);
168 
169 	std::shared_ptr<AsyncSerialImpl> pimpl;
170 
171     /**
172      * To allow derived classes to report errors
173      * \param e error status
174      */
175     void setErrorStatus(bool e);
176 
177 protected:
178 
179     /**
180      * To allow derived classes to set a read callback
181      */
182     void setReadCallback(const
183             boost::function<void (const char*, size_t)>& callback);
184 
185     /**
186      * Unregister the read callback.
187      */
188     void clearReadCallback();
189 
190     /**
191      * Process a clean close by unregistering the read callback and closing the port.
192      * Once this method has been called, you have to open the port and register the read callback again.
193      */
194     void terminate(bool silent = true);
195 
196 };
197 
198 
199 #endif //ASYNCSERIAL_H
200