]>
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)) { | |
48a30ec4 WW |
67 | std::cout << "Got something off the callback queue: "; |
68 | std::cout << (*pair.second) << std::endl; | |
51965cc5 | 69 | if (this->listening) { |
51965cc5 | 70 | try { |
7c0c9760 | 71 | pair.first->callback((*pair.second)); |
51965cc5 WW |
72 | } catch (std::exception &e) { |
73 | this->handle_exc(e); | |
74 | }// try callback | |
75 | } // if listening | |
51965cc5 WW |
76 | } // if popped |
77 | } // while (this->listening) | |
78 | } catch (std::exception &e) { | |
79 | this->handle_exc(SerialListenerException(e.what())); | |
80 | } | |
313b0198 WW |
81 | } |
82 | ||
318bce46 | 83 | void |
709fa5e1 | 84 | SerialListener::startListening(Serial &serial_port) { |
313b0198 WW |
85 | if (this->listening) { |
86 | throw(SerialListenerException("Already listening.")); | |
87 | return; | |
88 | } | |
89 | this->listening = true; | |
90 | ||
709fa5e1 | 91 | this->serial_port = &serial_port; |
313b0198 WW |
92 | if (!this->serial_port->isOpen()) { |
93 | throw(SerialListenerException("Serial port not open.")); | |
94 | return; | |
95 | } | |
96 | ||
97 | listen_thread = boost::thread(boost::bind(&SerialListener::listen, this)); | |
51965cc5 WW |
98 | |
99 | // Start the callback thread | |
100 | callback_thread = | |
101 | boost::thread(boost::bind(&SerialListener::callback, this)); | |
313b0198 WW |
102 | } |
103 | ||
318bce46 WW |
104 | void |
105 | SerialListener::stopListening() { | |
106 | // Stop listening and clear buffers | |
313b0198 | 107 | listening = false; |
51965cc5 | 108 | |
313b0198 | 109 | listen_thread.join(); |
51965cc5 WW |
110 | callback_thread.join(); |
111 | ||
51965cc5 | 112 | this->data_buffer = ""; |
313b0198 | 113 | this->serial_port = NULL; |
318bce46 WW |
114 | |
115 | // Delete all the filters | |
dfd1837c | 116 | this->removeAllFilters(); |
318bce46 WW |
117 | } |
118 | ||
51965cc5 WW |
119 | size_t |
120 | SerialListener::determineAmountToRead() { | |
121 | // TODO: Make a more intelligent method based on the length of the things | |
7c0c9760 | 122 | // filters are looking for. e.g.: if the filter is looking for 'V=XX\r' |
51965cc5 | 123 | // make the read amount at least 5. |
7c0c9760 | 124 | return this->chunk_size; |
313b0198 WW |
125 | } |
126 | ||
318bce46 | 127 | void |
51965cc5 | 128 | SerialListener::readSomeData(std::string &temp, size_t this_many) { |
313b0198 WW |
129 | // Make sure there is a serial port |
130 | if (this->serial_port == NULL) { | |
131 | this->handle_exc(SerialListenerException("Invalid serial port.")); | |
132 | } | |
133 | // Make sure the serial port is open | |
134 | if (!this->serial_port->isOpen()) { | |
135 | this->handle_exc(SerialListenerException("Serial port not open.")); | |
136 | } | |
51965cc5 | 137 | temp = this->serial_port->read(this_many); |
48a30ec4 | 138 | std::cout << "Read(" << temp.length() << "): " << temp << std::endl; |
313b0198 WW |
139 | } |
140 | ||
51965cc5 | 141 | void |
7c0c9760 | 142 | SerialListener::filterNewTokens (std::vector<TokenPtr> new_tokens) { |
51965cc5 | 143 | // Iterate through the filters, checking each against new tokens |
7c0c9760 WW |
144 | boost::mutex::scoped_lock lock(filter_mux); |
145 | std::vector<FilterPtr>::iterator it; | |
51965cc5 | 146 | for (it=filters.begin(); it!=filters.end(); it++) { |
7c0c9760 | 147 | this->filter((*it), new_tokens); |
51965cc5 | 148 | } // for (it=filters.begin(); it!=filters.end(); it++) |
51965cc5 WW |
149 | } |
150 | ||
7c0c9760 WW |
151 | // <filter_ptr,token_ptr> |
152 | void | |
153 | SerialListener::filter (FilterPtr filter, std::vector<TokenPtr> &tokens) | |
709fa5e1 | 154 | { |
51965cc5 | 155 | // Iterate through the token uuids and run each against the filter |
7c0c9760 WW |
156 | std::vector<TokenPtr>::iterator it; |
157 | for (it=tokens.begin(); it!=tokens.end(); it++) { | |
158 | TokenPtr token = (*it); | |
159 | if (filter->comparator((*token))) | |
160 | callback_queue.push(std::make_pair(filter,token)); | |
51965cc5 | 161 | } |
313b0198 WW |
162 | } |
163 | ||
51965cc5 WW |
164 | void |
165 | SerialListener::listen() { | |
166 | try { | |
167 | while (this->listening) { | |
168 | // Read some data | |
169 | std::string temp; | |
170 | this->readSomeData(temp, determineAmountToRead()); | |
171 | // If nothing was read then we | |
172 | // don't need to iterate through the filters | |
173 | if (temp.length() != 0) { | |
174 | // Add the new data to the buffer | |
175 | this->data_buffer += temp; | |
176 | // Call the tokenizer on the updated buffer | |
7c0c9760 | 177 | std::vector<TokenPtr> new_tokens; |
51965cc5 | 178 | this->tokenize(this->data_buffer, new_tokens); |
51965cc5 | 179 | // Run the new tokens through existing filters |
7c0c9760 | 180 | this->filterNewTokens(new_tokens); |
51965cc5 | 181 | } |
51965cc5 WW |
182 | // Done parsing lines and buffer should now be set to the left overs |
183 | } // while (this->listening) | |
184 | } catch (std::exception &e) { | |
185 | this->handle_exc(SerialListenerException(e.what())); | |
186 | } | |
313b0198 WW |
187 | } |
188 | ||
7c0c9760 | 189 | /***** Filter Functions *****/ |
709fa5e1 | 190 | |
7c0c9760 | 191 | FilterPtr |
dfd1837c WW |
192 | SerialListener::createFilter(ComparatorType comparator, DataCallback callback) |
193 | { | |
7c0c9760 | 194 | FilterPtr filter_ptr(new Filter(comparator, callback)); |
313b0198 | 195 | |
7c0c9760 WW |
196 | boost::mutex::scoped_lock l(filter_mux); |
197 | this->filters.push_back(filter_ptr); | |
313b0198 | 198 | |
7c0c9760 WW |
199 | return filter_ptr; |
200 | } | |
51965cc5 | 201 | |
dfd1837c WW |
202 | BlockingFilterPtr |
203 | SerialListener::createBlockingFilter(ComparatorType comparator) { | |
204 | return BlockingFilterPtr( | |
48a30ec4 | 205 | new BlockingFilter(comparator, (*this))); |
dfd1837c | 206 | } |
313b0198 | 207 | |
dfd1837c WW |
208 | BufferedFilterPtr |
209 | SerialListener::createBufferedFilter(ComparatorType comparator, | |
210 | size_t buffer_size) | |
7c0c9760 | 211 | { |
dfd1837c | 212 | return BufferedFilterPtr( |
48a30ec4 | 213 | new BufferedFilter(comparator, buffer_size, (*this))); |
7c0c9760 | 214 | } |
313b0198 | 215 | |
dfd1837c WW |
216 | void |
217 | SerialListener::removeFilter(FilterPtr filter_ptr) { | |
218 | boost::mutex::scoped_lock l(filter_mux); | |
219 | filters.erase(std::find(filters.begin(),filters.end(),filter_ptr)); | |
313b0198 WW |
220 | } |
221 | ||
dfd1837c WW |
222 | void |
223 | SerialListener::removeFilter(BlockingFilterPtr blocking_filter) { | |
224 | this->removeFilter(blocking_filter->filter_ptr); | |
51965cc5 WW |
225 | } |
226 | ||
227 | void | |
dfd1837c WW |
228 | SerialListener::removeFilter(BufferedFilterPtr buffered_filter) { |
229 | this->removeFilter(buffered_filter->filter_ptr); | |
709fa5e1 WW |
230 | } |
231 | ||
7c0c9760 | 232 | void |
dfd1837c | 233 | SerialListener::removeAllFilters() { |
7c0c9760 WW |
234 | boost::mutex::scoped_lock l(filter_mux); |
235 | filters.clear(); | |
236 | callback_queue.clear(); | |
709fa5e1 WW |
237 | } |
238 |