]> Git Repo - serial.git/blame - src/serial_listener.cc
Everything builds, but haven't tested it on a serial device.
[serial.git] / src / serial_listener.cc
CommitLineData
318bce46 1#include "serial/serial_listener.h"
313b0198
WW
2
3/***** Inline Functions *****/
4
5inline void defaultWarningCallback(const std::string& msg) {
6 std::cout << "SerialListener Warning: " << msg << std::endl;
7}
8
9inline void defaultDebugCallback(const std::string& msg) {
10 std::cout << "SerialListener Debug: " << msg << std::endl;
11}
12
13inline void defaultInfoCallback(const std::string& msg) {
14 std::cout << "SerialListener Info: " << msg << std::endl;
15}
16
17inline void defaultExceptionCallback(const std::exception &error) {
18 std::cerr << "SerialListener Unhandled Exception: " << error.what();
19 std::cerr << std::endl;
20 throw(error);
21}
22
7c0c9760
WW
23inline bool defaultComparator(const std::string &token) {
24 return true;
25}
26
313b0198
WW
27using namespace serial;
28
29/***** Listener Class Functions *****/
30
7c0c9760
WW
31void
32SerialListener::default_handler(const std::string &token) {
33 if (this->_default_handler)
34 this->_default_handler(token);
35}
36
37SerialListener::SerialListener() : listening(false), chunk_size(5) {
313b0198
WW
38 // Set default callbacks
39 this->handle_exc = defaultExceptionCallback;
40 this->info = defaultInfoCallback;
41 this->debug = defaultDebugCallback;
42 this->warn = defaultWarningCallback;
7c0c9760
WW
43
44 // Default handler stuff
45 this->_default_handler = NULL;
46 this->default_comparator = defaultComparator;
47 DataCallback tmp = boost::bind(&SerialListener::default_handler, this, _1);
48 this->default_filter = FilterPtr(new Filter(default_comparator, tmp));
49
318bce46
WW
50 // Set default tokenizer
51 this->setTokenizer(delimeter_tokenizer("\r"));
313b0198
WW
52}
53
54SerialListener::~SerialListener() {
51965cc5
WW
55 if (this->listening) {
56 this->stopListening();
57 }
58}
59
60void
61SerialListener::callback() {
62 try {
7c0c9760
WW
63 // <filter id, token>
64 std::pair<FilterPtr,TokenPtr> pair;
51965cc5
WW
65 while (this->listening) {
66 if (this->callback_queue.timed_wait_and_pop(pair, 10)) {
67 if (this->listening) {
51965cc5 68 try {
7c0c9760 69 pair.first->callback((*pair.second));
51965cc5
WW
70 } catch (std::exception &e) {
71 this->handle_exc(e);
72 }// try callback
73 } // if listening
51965cc5
WW
74 } // if popped
75 } // while (this->listening)
76 } catch (std::exception &e) {
77 this->handle_exc(SerialListenerException(e.what()));
78 }
313b0198
WW
79}
80
318bce46 81void
709fa5e1 82SerialListener::startListening(Serial &serial_port) {
313b0198
WW
83 if (this->listening) {
84 throw(SerialListenerException("Already listening."));
85 return;
86 }
87 this->listening = true;
88
709fa5e1 89 this->serial_port = &serial_port;
313b0198
WW
90 if (!this->serial_port->isOpen()) {
91 throw(SerialListenerException("Serial port not open."));
92 return;
93 }
94
95 listen_thread = boost::thread(boost::bind(&SerialListener::listen, this));
51965cc5
WW
96
97 // Start the callback thread
98 callback_thread =
99 boost::thread(boost::bind(&SerialListener::callback, this));
313b0198
WW
100}
101
318bce46
WW
102void
103SerialListener::stopListening() {
104 // Stop listening and clear buffers
313b0198 105 listening = false;
51965cc5 106
313b0198 107 listen_thread.join();
51965cc5
WW
108 callback_thread.join();
109
51965cc5 110 this->data_buffer = "";
313b0198 111 this->serial_port = NULL;
318bce46
WW
112
113 // Delete all the filters
dfd1837c 114 this->removeAllFilters();
318bce46
WW
115}
116
51965cc5
WW
117size_t
118SerialListener::determineAmountToRead() {
119 // TODO: Make a more intelligent method based on the length of the things
7c0c9760 120 // filters are looking for. e.g.: if the filter is looking for 'V=XX\r'
51965cc5 121 // make the read amount at least 5.
7c0c9760 122 return this->chunk_size;
313b0198
WW
123}
124
318bce46 125void
51965cc5 126SerialListener::readSomeData(std::string &temp, size_t this_many) {
313b0198
WW
127 // Make sure there is a serial port
128 if (this->serial_port == NULL) {
129 this->handle_exc(SerialListenerException("Invalid serial port."));
130 }
131 // Make sure the serial port is open
132 if (!this->serial_port->isOpen()) {
133 this->handle_exc(SerialListenerException("Serial port not open."));
134 }
51965cc5 135 temp = this->serial_port->read(this_many);
313b0198
WW
136}
137
51965cc5 138void
7c0c9760 139SerialListener::filterNewTokens (std::vector<TokenPtr> new_tokens) {
51965cc5 140 // Iterate through the filters, checking each against new tokens
7c0c9760
WW
141 boost::mutex::scoped_lock lock(filter_mux);
142 std::vector<FilterPtr>::iterator it;
51965cc5 143 for (it=filters.begin(); it!=filters.end(); it++) {
7c0c9760 144 this->filter((*it), new_tokens);
51965cc5 145 } // for (it=filters.begin(); it!=filters.end(); it++)
51965cc5
WW
146}
147
7c0c9760
WW
148// <filter_ptr,token_ptr>
149void
150SerialListener::filter (FilterPtr filter, std::vector<TokenPtr> &tokens)
709fa5e1 151{
51965cc5 152 // Iterate through the token uuids and run each against the filter
7c0c9760
WW
153 std::vector<TokenPtr>::iterator it;
154 for (it=tokens.begin(); it!=tokens.end(); it++) {
155 TokenPtr token = (*it);
156 if (filter->comparator((*token)))
157 callback_queue.push(std::make_pair(filter,token));
51965cc5 158 }
313b0198
WW
159}
160
51965cc5
WW
161void
162SerialListener::listen() {
163 try {
164 while (this->listening) {
165 // Read some data
166 std::string temp;
167 this->readSomeData(temp, determineAmountToRead());
168 // If nothing was read then we
169 // don't need to iterate through the filters
170 if (temp.length() != 0) {
171 // Add the new data to the buffer
172 this->data_buffer += temp;
173 // Call the tokenizer on the updated buffer
7c0c9760 174 std::vector<TokenPtr> new_tokens;
51965cc5 175 this->tokenize(this->data_buffer, new_tokens);
51965cc5 176 // Run the new tokens through existing filters
7c0c9760 177 this->filterNewTokens(new_tokens);
51965cc5 178 }
51965cc5
WW
179 // Done parsing lines and buffer should now be set to the left overs
180 } // while (this->listening)
181 } catch (std::exception &e) {
182 this->handle_exc(SerialListenerException(e.what()));
183 }
313b0198
WW
184}
185
7c0c9760 186/***** Filter Functions *****/
709fa5e1 187
7c0c9760 188FilterPtr
dfd1837c
WW
189SerialListener::createFilter(ComparatorType comparator, DataCallback callback)
190{
7c0c9760 191 FilterPtr filter_ptr(new Filter(comparator, callback));
313b0198 192
7c0c9760
WW
193 boost::mutex::scoped_lock l(filter_mux);
194 this->filters.push_back(filter_ptr);
313b0198 195
7c0c9760
WW
196 return filter_ptr;
197}
51965cc5 198
dfd1837c
WW
199BlockingFilterPtr
200SerialListener::createBlockingFilter(ComparatorType comparator) {
201 return BlockingFilterPtr(
202 new BlockingFilter(comparator, boost::shared_ptr<SerialListener>(this)));
203}
313b0198 204
dfd1837c
WW
205BufferedFilterPtr
206SerialListener::createBufferedFilter(ComparatorType comparator,
207 size_t buffer_size)
7c0c9760 208{
dfd1837c
WW
209 return BufferedFilterPtr(
210 new BufferedFilter(comparator,
211 buffer_size,
212 boost::shared_ptr<SerialListener>(this)));
7c0c9760 213}
313b0198 214
dfd1837c
WW
215void
216SerialListener::removeFilter(FilterPtr filter_ptr) {
217 boost::mutex::scoped_lock l(filter_mux);
218 filters.erase(std::find(filters.begin(),filters.end(),filter_ptr));
313b0198
WW
219}
220
dfd1837c
WW
221void
222SerialListener::removeFilter(BlockingFilterPtr blocking_filter) {
223 this->removeFilter(blocking_filter->filter_ptr);
51965cc5
WW
224}
225
226void
dfd1837c
WW
227SerialListener::removeFilter(BufferedFilterPtr buffered_filter) {
228 this->removeFilter(buffered_filter->filter_ptr);
709fa5e1
WW
229}
230
7c0c9760 231void
dfd1837c 232SerialListener::removeAllFilters() {
7c0c9760
WW
233 boost::mutex::scoped_lock l(filter_mux);
234 filters.clear();
235 callback_queue.clear();
709fa5e1
WW
236}
237
This page took 0.052423 seconds and 4 git commands to generate.