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.
Dependencies: nRF51_Vdd TextLCD BME280
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 virtual ~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 virtual 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 including NULL 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 // print contents of a buffer to trace log 00516 void debug_print(char *p, int len); 00517 }; 00518 00519 } // namespace mbed 00520 00521 #endif //AT_HANDLER_H_
Generated on Tue Jul 12 2022 15:15:40 by
