]>
Commit | Line | Data |
---|---|---|
318bce46 | 1 | #include "serial/serial_listener.h" |
313b0198 WW |
2 | |
3 | /***** Inline Functions *****/ | |
4 | ||
5 | inline void defaultWarningCallback(const std::string& msg) { | |
6 | std::cout << "SerialListener Warning: " << msg << std::endl; | |
7 | } | |
8 | ||
9 | inline void defaultDebugCallback(const std::string& msg) { | |
10 | std::cout << "SerialListener Debug: " << msg << std::endl; | |
11 | } | |
12 | ||
13 | inline void defaultInfoCallback(const std::string& msg) { | |
14 | std::cout << "SerialListener Info: " << msg << std::endl; | |
15 | } | |
16 | ||
17 | inline 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 |
23 | inline bool defaultComparator(const std::string &token) { |
24 | return true; | |
25 | } | |
26 | ||
313b0198 WW |
27 | using namespace serial; |
28 | ||
29 | /***** Listener Class Functions *****/ | |
30 | ||
7c0c9760 WW |
31 | void |
32 | SerialListener::default_handler(const std::string &token) { | |
33 | if (this->_default_handler) | |
34 | this->_default_handler(token); | |
35 | } | |
36 | ||
37 | SerialListener::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 | ||
54 | SerialListener::~SerialListener() { | |
51965cc5 WW |
55 | if (this->listening) { |
56 | this->stopListening(); | |
57 | } | |
58 | } | |
59 | ||
60 | void | |
61 | SerialListener::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 | 81 | void |
709fa5e1 | 82 | SerialListener::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 |
102 | void |
103 | SerialListener::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 |
117 | size_t |
118 | SerialListener::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 | 125 | void |
51965cc5 | 126 | SerialListener::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 | 138 | void |
7c0c9760 | 139 | SerialListener::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> |
149 | void | |
150 | SerialListener::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 |
161 | void |
162 | SerialListener::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 | 188 | FilterPtr |
dfd1837c WW |
189 | SerialListener::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 |
199 | BlockingFilterPtr |
200 | SerialListener::createBlockingFilter(ComparatorType comparator) { | |
201 | return BlockingFilterPtr( | |
202 | new BlockingFilter(comparator, boost::shared_ptr<SerialListener>(this))); | |
203 | } | |
313b0198 | 204 | |
dfd1837c WW |
205 | BufferedFilterPtr |
206 | SerialListener::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 |
215 | void |
216 | SerialListener::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 |
221 | void |
222 | SerialListener::removeFilter(BlockingFilterPtr blocking_filter) { | |
223 | this->removeFilter(blocking_filter->filter_ptr); | |
51965cc5 WW |
224 | } |
225 | ||
226 | void | |
dfd1837c WW |
227 | SerialListener::removeFilter(BufferedFilterPtr buffered_filter) { |
228 | this->removeFilter(buffered_filter->filter_ptr); | |
709fa5e1 WW |
229 | } |
230 | ||
7c0c9760 | 231 | void |
dfd1837c | 232 | SerialListener::removeAllFilters() { |
7c0c9760 WW |
233 | boost::mutex::scoped_lock l(filter_mux); |
234 | filters.clear(); | |
235 | callback_queue.clear(); | |
709fa5e1 WW |
236 | } |
237 |