Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ATHandler.h
00001 /* 00002 * Copyright (c) 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef AT_HANDLER_H_ 00019 #define AT_HANDLER_H_ 00020 00021 #include "platform/mbed_retarget.h" 00022 00023 #include "EventQueue.h" 00024 #include "PlatformMutex.h" 00025 #include "nsapi_types.h" 00026 00027 #include "PlatformMutex.h" 00028 #include "Callback.h" 00029 #include "EventQueue.h" 00030 00031 namespace mbed { 00032 00033 class FileHandle; 00034 00035 /** 00036 * If application calls associated FileHandle only from single thread context 00037 * then locking between AT command and response is not needed. However, 00038 * note that many cellular functions are called indirectly, for example with the socket API. 00039 * If you are unsure, then AT_HANDLER_MUTEX must be defined. 00040 */ 00041 #define AT_HANDLER_MUTEX 00042 00043 extern const char *OK; 00044 extern const char *CRLF; 00045 00046 #define BUFF_SIZE 16 00047 00048 /* AT Error types enumeration */ 00049 enum DeviceErrorType { 00050 DeviceErrorTypeNoError = 0, 00051 DeviceErrorTypeError, // AT ERROR 00052 DeviceErrorTypeErrorCMS, // AT ERROR CMS 00053 DeviceErrorTypeErrorCME // AT ERROR CME 00054 }; 00055 00056 /* struct used when getting at response error. Defines error code and type */ 00057 struct device_err_t { 00058 DeviceErrorType errType; 00059 int errCode; 00060 }; 00061 00062 /** Class ATHandler 00063 * 00064 * Class for sending AT commands and parsing AT responses. 00065 */ 00066 class ATHandler { 00067 00068 public: 00069 /** Constructor 00070 * 00071 * @param fh file handle used for reading AT responses and writing AT commands 00072 * @param queue Event queue used to transfer sigio events to this thread 00073 * @param timeout Timeout when reading for AT response 00074 * @param output_delimiter delimiter used when parsing at responses, "\r" should be used as output_delimiter 00075 * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command 00076 */ 00077 ATHandler(FileHandle *fh, events::EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay = 0); 00078 ~ATHandler(); 00079 00080 /** Return used file handle. 00081 * 00082 * @return used file handle 00083 */ 00084 FileHandle *get_file_handle(); 00085 00086 /** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined. 00087 */ 00088 void lock(); 00089 00090 /** Unlocks the mutex for file handle if AT_HANDLER_MUTEX is defined. 00091 */ 00092 void unlock(); 00093 00094 /** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined and returns the last error. 00095 * 00096 * @return last error that happened when parsing AT responses 00097 */ 00098 nsapi_error_t unlock_return_error(); 00099 00100 /** Set the urc callback for urc. If urc is found when parsing AT responses, then call if called. 00101 * If urc is already set then it's not set twice. 00102 * 00103 * @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: " 00104 * @param callback Callback, which is called if urc is found in AT response 00105 * @return NSAPI_ERROR_OK or NSAPI_ERROR_NO_MEMORY if no memory 00106 */ 00107 nsapi_error_t set_urc_handler(const char *prefix, mbed::Callback<void()> callback); 00108 00109 /** Remove urc handler from linked list of urc's 00110 * 00111 * @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: " 00112 * @param callback Callback, which is called if urc is found in AT response 00113 */ 00114 void remove_urc_handler(const char *prefix, mbed::Callback<void()> callback); 00115 00116 ATHandler *_nextATHandler; // linked list 00117 00118 /** returns the last error while parsing AT responses. 00119 * 00120 * @return last error 00121 */ 00122 nsapi_error_t get_last_error() const; 00123 00124 /** returns the last device error while parsing AT responses. Actually AT error (CME/CMS). 00125 * 00126 * @return last error struct device_err_t 00127 */ 00128 device_err_t get_last_device_error() const; 00129 00130 /** Increase reference count. Used for counting references to this instance. 00131 */ 00132 void inc_ref_count(); 00133 00134 /** Decrease reference count. Used for counting references to this instance. 00135 */ 00136 void dec_ref_count(); 00137 00138 /** Get the current reference count. Used for counting references to this instance. 00139 * 00140 * @return current reference count 00141 */ 00142 int get_ref_count(); 00143 00144 /** Set timeout in milliseconds for AT commands 00145 * 00146 * @param timeout_milliseconds Timeout in milliseconds 00147 * @param default_timeout Store as default timeout 00148 */ 00149 void set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout = false); 00150 00151 /** Restore timeout to previous timeout. Handy if there is a need to change timeout temporarily. 00152 */ 00153 void restore_at_timeout(); 00154 00155 /** Clear pending error flag. By default, error is cleared only in lock(). 00156 */ 00157 void clear_error(); 00158 00159 /** 00160 * Flushes the underlying stream 00161 */ 00162 void flush(); 00163 00164 /** Tries to find oob's from the AT response. Call the urc callback if one is found. 00165 */ 00166 void process_oob(); 00167 00168 /** Set sigio for the current file handle. Sigio event goes through eventqueue so that it's handled in current thread. 00169 */ 00170 void set_filehandle_sigio(); 00171 00172 /** Set file handle, which is used for reading AT responses and writing AT commands 00173 * 00174 * @param fh file handle used for reading AT responses and writing AT commands 00175 */ 00176 void set_file_handle(FileHandle *fh); 00177 00178 /** Set is file handle usable. Some situations like after going to data mode, file handle is not usable anymore. 00179 * Any items in queue are not to be processed. 00180 * 00181 * @param usable true for usable filehandle 00182 */ 00183 void set_is_filehandle_usable(bool usable); 00184 00185 protected: 00186 void event(); 00187 #ifdef AT_HANDLER_MUTEX 00188 PlatformMutex _fileHandleMutex; 00189 #endif 00190 FileHandle *_fileHandle; 00191 private: 00192 00193 void set_error(nsapi_error_t err); 00194 00195 events::EventQueue &_queue; 00196 nsapi_error_t _last_err; 00197 int _last_3gpp_error; 00198 device_err_t _last_at_err; 00199 uint16_t _oob_string_max_length; 00200 char *_output_delimiter; 00201 00202 struct oob_t { 00203 const char *prefix; 00204 int prefix_len; 00205 mbed::Callback<void()> cb; 00206 oob_t *next; 00207 }; 00208 oob_t *_oobs; 00209 uint32_t _at_timeout; 00210 uint32_t _previous_at_timeout; 00211 00212 uint16_t _at_send_delay; 00213 uint64_t _last_response_stop; 00214 00215 bool _fh_sigio_set; 00216 00217 bool _processing; 00218 int32_t _ref_count; 00219 bool _is_fh_usable; 00220 00221 //************************************* 00222 public: 00223 00224 /** Starts the command writing by clearing the last error and writing the given command. 00225 * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. 00226 * 00227 * @param cmd AT command to be written to modem 00228 */ 00229 void cmd_start(const char *cmd); 00230 00231 /** Writes integer type AT command subparameter. Starts with the delimiter if not the first param after cmd_start. 00232 * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. 00233 * 00234 * @param param int to be written to modem as AT command subparameter 00235 */ 00236 void write_int(int32_t param); 00237 00238 /** Writes string type AT command subparamater. Quotes are added to surround the given string. 00239 * Starts with the delimiter if not the first param after cmd_start. 00240 * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. 00241 * 00242 * @param param string to be written to modem as AT command subparameter 00243 * @param useQuotations flag indicating whether the string should be included in quotation marks 00244 */ 00245 void write_string(const char *param, bool useQuotations = true); 00246 00247 /** Stops the AT command by writing command-line terminator CR to mark command as finished. 00248 */ 00249 void cmd_stop(); 00250 00251 /** Write bytes without any subparameter delimiters, such as comma. 00252 * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. 00253 * 00254 * @param data bytes to be written to modem 00255 * @param len length of data string 00256 * 00257 * @return number of characters successfully written 00258 */ 00259 size_t write_bytes(const uint8_t *data, size_t len); 00260 00261 /** Sets the stop tag for the current scope (response/information response/element) 00262 * Parameter's reading routines will stop the reading when such tag is found and will set the found flag. 00263 * Consume routines will read everything until such tag is found. 00264 * 00265 * @param stop_tag_seq string to be set as stop tag 00266 */ 00267 void set_stop_tag(const char *stop_tag_seq); 00268 00269 /** Sets the delimiter between parameters or between elements of the information response. 00270 * Parameter's reading routines will stop when such char is read. 00271 * 00272 * @param delimiter char to be set as _delimiter 00273 */ 00274 void set_delimiter(char delimiter); 00275 00276 /** Sets the delimiter to default value defined by DEFAULT_DELIMITER. 00277 */ 00278 void set_default_delimiter(); 00279 00280 /** Consumes the reading buffer up to the delimiter or stop_tag 00281 * 00282 * @param count number of parameters to be skipped 00283 */ 00284 void skip_param(uint32_t count = 1); 00285 00286 /** Consumes the given length from the reading buffer 00287 * 00288 * @param len length to be consumed from reading buffer 00289 * @param count number of parameters to be skipped 00290 */ 00291 void skip_param(ssize_t len, uint32_t count); 00292 00293 /** Reads given number of bytes from receiving buffer without checking any subparameter delimiters, such as comma. 00294 * 00295 * @param buf output buffer for the read 00296 * @param len maximum number of bytes to read 00297 * @return number of successfully read bytes or -1 in case of error 00298 */ 00299 ssize_t read_bytes(uint8_t *buf, size_t len); 00300 00301 /** Reads chars from reading buffer. Terminates with null. Skips the quotation marks. 00302 * Stops on delimiter or stop tag. 00303 * 00304 * @param str output buffer for the read 00305 * @param size maximum number of chars to output 00306 * @param read_even_stop_tag if true then try to read even if the stop tag was found previously 00307 * @return length of output string or -1 in case of read timeout before delimiter or stop tag is found 00308 */ 00309 ssize_t read_string(char *str, size_t size, bool read_even_stop_tag = false); 00310 00311 /** Reads chars representing hex ascii values and converts them to the corresponding chars. 00312 * For example: "4156" to "AV". 00313 * Terminates with null. Skips the quotation marks. 00314 * Stops on delimiter or stop tag. 00315 * 00316 * @param str output buffer for the read 00317 * @param size maximum number of chars to output 00318 * @return length of output string or -1 in case of read timeout before delimiter or stop tag is found 00319 */ 00320 ssize_t read_hex_string(char *str, size_t size); 00321 00322 /** Reads as string and converts result to integer. Supports only positive integers. 00323 * 00324 * @return the positive integer or -1 in case of error. 00325 */ 00326 int32_t read_int(); 00327 00328 /** This looks for necessary matches: prefix, OK, ERROR, URCs and sets the correct scope. 00329 * 00330 * @param prefix string to be matched from receiving buffer. If not NULL and match succeeds, then scope 00331 * will be set as information response(info_type) 00332 * @param stop flag to indicate if we go to information response scope or not. 00333 * (needed when nothing is expected to be received anymore after the prefix match: 00334 * sms case: "> ", bc95 reboot case) 00335 */ 00336 void resp_start(const char *prefix = NULL, bool stop = false); 00337 00338 /** Ends all scopes starting from current scope. 00339 * Consumes everything until the scope's stop tag is found, then 00340 * goes to next scope until response scope is ending. 00341 * Possible sequence: 00342 * element scope -> information response scope -> response scope 00343 */ 00344 void resp_stop(); 00345 00346 /** Looks for matching the prefix given to resp_start() call. 00347 * If needed, it ends the scope of a previous information response. 00348 * Sets the information response scope if new prefix is found and response scope if prefix is not found. 00349 * 00350 * @return true if new information response is found, false otherwise 00351 */ 00352 bool info_resp(); 00353 00354 /** Looks for matching the start tag. 00355 * If needed, it ends the scope of a previous element. 00356 * Sets the element scope if start tag is found and information response scope if start tag is not found. 00357 * 00358 * @param start_tag tag to be matched to begin parsing an element of an information response 00359 * @return true if new element is found, false otherwise 00360 */ 00361 bool info_elem(char start_tag); 00362 00363 /** Consumes the received content until current stop tag is found. 00364 * 00365 * @return true if stop tag is found, false otherwise 00366 */ 00367 bool consume_to_stop_tag(); 00368 00369 /** Return the last 3GPP error code. 00370 * @return last 3GPP error code 00371 */ 00372 int get_3gpp_error(); 00373 00374 public: // just for debugging 00375 /** 00376 * AT debugging, when enabled will print all data read and written, 00377 * non-printable chars are printed as "[%d]". 00378 * 00379 * AT debug can be enabled at compile time using MBED_CONF_CELLULAR_DEBUG_AT flag or at runtime 00380 * calling set_debug(). Note that MBED_CONF_MBED_TRACE_ENABLE must also be enabled. 00381 * 00382 * @param debug_on Enable/disable debugging 00383 */ 00384 void set_debug(bool debug_on); 00385 00386 private: 00387 00388 // should fit any prefix and int 00389 char _recv_buff[BUFF_SIZE]; 00390 // reading position 00391 size_t _recv_len; 00392 // reading length 00393 size_t _recv_pos; 00394 00395 // resp_type: the part of the response that doesn't include the information response (+CMD1,+CMD2..) 00396 // ends with OK or (CME)(CMS)ERROR 00397 // info_type: the information response part of the response: starts with +CMD1 and ends with CRLF 00398 // information response contains parameters or subsets of parameters (elements), both separated by comma 00399 // elem_type: subsets of parameters that are part of information response, its parameters are separated by comma 00400 enum ScopeType {RespType, InfoType, ElemType, NotSet}; 00401 void set_scope(ScopeType scope_type); 00402 ScopeType _current_scope; 00403 00404 struct tag_t { 00405 char tag[7]; 00406 size_t len; 00407 bool found; 00408 }; 00409 00410 // tag to stop response scope 00411 tag_t _resp_stop; 00412 // tag to stop information response scope 00413 tag_t _info_stop; 00414 // tag to stop element scope 00415 tag_t _elem_stop; 00416 // reference to the stop tag of current scope (resp/info/elem) 00417 tag_t *_stop_tag; 00418 00419 // delimiter between parameters and also used for delimiting elements of information response 00420 char _delimiter; 00421 // set true on prefix match -> indicates start of an information response or of an element 00422 bool _prefix_matched; 00423 // set true on urc match 00424 bool _urc_matched; 00425 // set true on (CME)(CMS)ERROR 00426 bool _error_found; 00427 // Max length of OK,(CME)(CMS)ERROR and URCs 00428 size_t _max_resp_length; 00429 00430 // prefix set during resp_start and used to try matching possible information responses 00431 char _info_resp_prefix[BUFF_SIZE]; 00432 bool _debug_on; 00433 bool _cmd_start; 00434 00435 // time when a command or an URC processing was started 00436 uint64_t _start_time; 00437 00438 // Gets char from receiving buffer. 00439 // Resets and fills the buffer if all are already read (receiving position equals receiving length). 00440 // Returns a next char or -1 on failure (also sets error flag) 00441 int get_char(); 00442 // Sets to 0 the reading position, reading length and the whole buffer content. 00443 void reset_buffer(); 00444 // Reading position set to 0 and buffer's unread content moved to beginning 00445 void rewind_buffer(); 00446 // Calculate remaining time for polling based on request start time and AT timeout. 00447 // Returns 0 or time in ms for polling. 00448 int poll_timeout(bool wait_for_timeout = true); 00449 // Reads from serial to receiving buffer. 00450 // Returns true on successful read OR false on timeout. 00451 bool fill_buffer(bool wait_for_timeout = true); 00452 00453 void set_tag(tag_t *tag_dest, const char *tag_seq); 00454 00455 // Rewinds the receiving buffer and compares it against given str. 00456 bool match(const char *str, size_t size); 00457 // Iterates URCs and checks if they match the receiving buffer content. 00458 // If URC match sets the scope to information response and after urc's cb returns 00459 // finishes the information response scope(consumes to CRLF). 00460 bool match_urc(); 00461 // Checks if any of the error strings are matching the receiving buffer content. 00462 bool match_error(); 00463 // Checks if current char in buffer matches ch and consumes it, 00464 // if no match lets the buffer unchanged. 00465 bool consume_char(char ch); 00466 // Consumes the received content until tag is found. 00467 // Consumes the tag only if consume_tag flag is true. 00468 bool consume_to_tag(const char *tag, bool consume_tag); 00469 // Checks if receiving buffer contains OK, ERROR, URC or given prefix. 00470 void resp(const char *prefix, bool check_urc); 00471 00472 00473 ScopeType get_scope(); 00474 00475 // Consumes to information response stop tag which is CRLF. Sets scope to response. 00476 void information_response_stop(); 00477 // Consumes to element stop tag. Sets scope to information response 00478 void information_response_element_stop(); 00479 00480 // Reads the error code if expected and sets it as last error. 00481 void at_error(bool error_code, DeviceErrorType error_type); 00482 00483 /** Convert AT error code to 3GPP error codes 00484 * @param err AT error code read from CME/CMS ERROR responses 00485 * @param error_type error type (CMS/CME/ERROR) 00486 */ 00487 void set_3gpp_error(int err, DeviceErrorType error_type); 00488 00489 bool check_cmd_send(); 00490 size_t write(const void *data, size_t len); 00491 00492 /** Copy content of one char buffer to another buffer and sets NULL terminator 00493 * 00494 * @param dest destination char buffer 00495 * @param src source char buffer 00496 * @param src_len number of bytes to copy 00497 * 00498 */ 00499 void set_string(char *dest, const char *src, size_t src_len); 00500 00501 /** Finds occurrence of one char buffer inside another char buffer. 00502 * 00503 * @param dest destination char buffer 00504 * @param dest_len length of dest 00505 * @param src string to be searched for 00506 * @param src_len length of string to be searched for 00507 * 00508 * @return pointer to first occurrence of src in dest 00509 */ 00510 const char *mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len); 00511 00512 // check is urc is already added 00513 bool find_urc_handler(const char *prefix, mbed::Callback<void()> callback); 00514 00515 ssize_t read(char *buf, size_t size, bool read_even_stop_tag, bool hex); 00516 00517 // print contents of a buffer to trace log 00518 void debug_print(char *p, int len); 00519 }; 00520 00521 } // namespace mbed 00522 00523 #endif //AT_HANDLER_H_
Generated on Tue Jul 12 2022 12:43:34 by
