├── LICENSE ├── README.md ├── README_ZH.md ├── SConscript ├── class ├── a9g │ ├── at_device_a9g.c │ ├── at_device_a9g.h │ └── at_socket_a9g.c ├── air720 │ ├── at_device_air720.c │ ├── at_device_air720.h │ └── at_socket_air720.c ├── bc26 │ ├── at_device_bc26.c │ ├── at_device_bc26.h │ └── at_socket_bc26.c ├── bc28 │ ├── README.md │ ├── at_device_bc28.c │ ├── at_device_bc28.h │ └── at_socket_bc28.c ├── ec20 │ ├── at_device_ec20.c │ ├── at_device_ec20.h │ └── at_socket_ec20.c ├── ec200x │ ├── at_device_ec200x.c │ ├── at_device_ec200x.h │ └── at_socket_ec200x.c ├── esp32 │ ├── at_device_esp32.c │ ├── at_device_esp32.h │ └── at_socket_esp32.c ├── esp8266 │ ├── at_device_esp8266.c │ ├── at_device_esp8266.h │ └── at_socket_esp8266.c ├── l610 │ ├── at_device_l610.c │ ├── at_device_l610.h │ └── at_socket_l610.c ├── m26 │ ├── at_device_m26.c │ ├── at_device_m26.h │ └── at_socket_m26.c ├── m5311 │ ├── at_device_m5311.c │ ├── at_device_m5311.h │ └── at_socket_m5311.c ├── m6315 │ ├── at_device_m6315.c │ ├── at_device_m6315.h │ └── at_socket_m6315.c ├── me3616 │ ├── at_device_me3616.c │ ├── at_device_me3616.h │ └── at_socket_me3616.c ├── ml305 │ ├── at_device_ml305.c │ ├── at_device_ml305.h │ └── at_socket_ml305.c ├── ml307 │ ├── at_device_ml307.c │ ├── at_device_ml307.h │ └── at_socket_ml307.c ├── mw31 │ ├── at_device_mw31.c │ ├── at_device_mw31.h │ └── at_socket_mw31.c ├── n21 │ ├── Kconfig │ ├── at_device_n21.c │ ├── at_device_n21.h │ └── at_socket_n21.c ├── n58 │ ├── Kconfig │ ├── at_device_n58.c │ ├── at_device_n58.h │ └── at_socket_n58.c ├── n720 │ ├── at_device_n720.c │ ├── at_device_n720.h │ └── at_socket_n720.c ├── rw007 │ ├── at_device_rw007.c │ ├── at_device_rw007.h │ └── at_socket_rw007.c ├── sim76xx │ ├── at_device_sim76xx.c │ ├── at_device_sim76xx.h │ └── at_socket_sim76xx.c ├── sim800c │ ├── at_device_sim800c.c │ ├── at_device_sim800c.h │ └── at_socket_sim800c.c └── w60x │ ├── at_device_w60x.c │ ├── at_device_w60x.h │ └── at_socket_w60x.c ├── inc └── at_device.h ├── samples ├── at_sample_a9g.c ├── at_sample_air720.c ├── at_sample_bc26.c ├── at_sample_bc28.c ├── at_sample_client.c ├── at_sample_ec20.c ├── at_sample_ec200x.c ├── at_sample_esp32.c ├── at_sample_esp8266.c ├── at_sample_l610.c ├── at_sample_m26.c ├── at_sample_m5311.c ├── at_sample_m6315.c ├── at_sample_me3616.c ├── at_sample_ml305.c ├── at_sample_ml307.c ├── at_sample_mw31.c ├── at_sample_n21.c ├── at_sample_n58.c ├── at_sample_n720.c ├── at_sample_rw007.c ├── at_sample_sim76xx.c ├── at_sample_sim800c.c └── at_sample_w60x.c └── src └── at_device.c /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AT device # 2 | 3 | [Chinese](./README_ZH.md) | English 4 | 5 | ## 1. Introduction ## 6 | 7 | 8 | The AT device software package is composed of the transplantation files and sample codes of the RT-Thread AT component for different AT devices. Currently supported AT devices are: ESP8266, ESP32, M26, MC20, RW007, MW31, SIM800C, W60X, SIM76XX, A9/ A9G, BC26, AIR720, ME3616, M6315, BC28, EC200X, M5311, L610 series devices, etc. At present, the above devices have completed the transplantation of the `AT socket` function, and the device implements the standard socket programming interface through AT commands to complete the socket communication For detailed function introduction, please refer to ["RT-Thread Programming Guide"](https://www.rt-thread.org/document/site/programming-manual/at/at/) AT command chapter. 9 | 10 | ### 1.1. Directory structure ### 11 | 12 | | Name | Description | 13 | | ---- | ---- | 14 | | src | AT device implementation source code directory | 15 | | inc | AT device header file directory | 16 | | sample | Sample file directory for different devices | 17 | | class | Migration and adaptation catalog of AT components for different devices | 18 | | class/esp8266 | ESP8266 device's migration directory for AT components, realizing AT Socket function | 19 | | class/esp32 | ESP32 device's migration directory for AT components to realize AT Socket function | 20 | | class/rw007 | RW007 device is a migration directory for AT components, realizing AT Socket function | 21 | | class/sim800c | SIM800C device for AT component transplantation directory, realize AT Socket function | 22 | | class/sim76xx | SIM76XX device's migration directory for AT components, realizing AT Socket function | 23 | | class/m26 | M26/MC20 device's migration directory for AT components, realizing AT Socket function | 24 | | class/ec20 | EC20 device's migration directory for AT components, realizing AT Socket function | 25 | | class/mw31 | Migration directory for AT components of MW31 equipment, realizing AT Socket function | 26 | | class/w60x | W60X device's migration directory for AT components, realizing AT Socket function | 27 | | class/a9g | A9G device's migration directory for AT components, realizing AT Socket function | 28 | | class/bc26 | The migration directory of bc26 device aiming at AT components to realize AT Socket function | 29 | | class/air720 | Air720 device is aimed at AT component transplantation catalog, realizes AT Socket function | 30 | | class/me3616 | The me3616 device is aimed at the transplantation directory of AT components, and realizes the AT Socket function | 31 | | class/m6315 | The migration directory of m6315 equipment for AT components, realizes the AT Socket function | 32 | | class/bc28 | The migration directory of bc28 equipment for AT components, realizes AT Socket function | 33 | | class/ec200x | EC200T, EC200S equipment for AT component migration catalog, realize AT Socket function | 34 | | class/n21 | N21 device's transplantation directory for AT components to realize AT Socket function | 35 | | class/n58 | N58 device's migration directory for AT components, realizing AT Socket function | 36 | | class/m5311 | M5311 device is aimed at AT component transplantation catalog, realizes AT Socket function | 37 | | class/l610 | A migration directory for AT components of L610 equipment, realizing AT Socket function | 38 | | class/ml305 | A migration directory for AT components of ML305 equipment, realizing AT Socket function | 39 | ### 1.2 License ### 40 | 41 | See the `LICENSE` file for details. 42 | 43 | ### 1.3 Dependency ### 44 | 45 | - RT_Thread 4.0.2+ 46 | - RT_Thread AT component 1.3.0+ 47 | - RT_Thread SAL component 48 | - RT-Thread netdev component 49 | 50 | ## 2. How to Obtain ## 51 | 52 | The AT device software package is a transplantation of the AT component and AT socket function. You need to enable the AT component library and AT socket function to obtain the AT device software package. 53 | 54 | **Version number description** 55 | 56 | At present, the AT device software package has been released in multiple versions, and the option configuration method between each version and its corresponding system version are different. The following mainly lists the currently available software package version information: 57 | 58 | - **V1.2.0**: applicable to RT-Thread version less than V3.1.3, AT component version equal to V1.0.0; 59 | - **V1.3.0**: applicable to RT-Thread version less than V3.1.3, AT component version equal to V1.1.0; 60 | - **V1.4.0**: applicable to RT-Thread version less than V3.1.3 or equal to V4.0.0, AT component version equal to V1.2.0; 61 | - **V1.5.0**: Suitable for RT-Thread version less than V3.1.3 or equal to V4.0.0, AT component version equal to V1.2.0; 62 | - **V1.6.0**: applicable to RT-Thread version equal to V3.1.3 or equal to V4.0.1, AT component version equal to V1.2.0; 63 | - **V2.0.0/V2.0.1**: applicable to RT-Thread version greater than V4.0.1 or greater than 3.1.3, AT component version equal to V1.3.0; 64 | - **latest**: Only applicable to RT-Thread version greater than V4.0.1 or greater than 3.1.3, AT component version equal to V1.3.0; 65 | 66 | > The above version judgment is automatically completed in menuconfig. When the at_device software package selects the version, it will give the best version support according to the current system environment. The version introduction is used as a reference for the operating environment. 67 | 68 | For different version numbers, the option configuration in ENV is also different, mainly divided into the following parts: 69 | 70 | **V1.X.X version configuration options introduction** 71 | 72 | Open the AT device software package. This version only supports **Enable one AT device at the same time**. The configuration options are as follows: 73 | 74 | RT-Thread online packages ---> 75 | IoT-internet of things ---> 76 | -*- AT DEVICE: RT-Thread AT component porting or samples for different device 77 | [] Enable at device init by thread 78 | AT socket device modules (Not selected, please select) ---> 79 | Version (V1.6.0) ---> 80 | 81 | - **Enable at device init by thread**: Configure whether to enable the device network initialization to be completed by creating a thread; 82 | 83 | - **AT socket device modules**: AT device selection, currently only supports RW007、ESP8266、M26/MC20、EC20、SIM800C、SIM76XX. More device support should choose V2.X.X branch. 84 | 85 | - **Version**: download the software package version; 86 | 87 | **V2.X.X (latest) version configuration options introduction** 88 | 89 | Open the AT device software package, this version supports **open multiple AT devices at the same time** configuration options are as follows: 90 | 91 | ```c 92 | RT-Thread online packages ---> 93 | IoT-internet of things ---> 94 | -*- AT DEVICE: RT-Thread AT component porting or samples for different device 95 | [*] Quectel M26/MC20 ---> 96 | [*] Enable initialize by thread 97 | [*] Enable sample 98 | (-1) Power pin 99 | (-1) Power status pin 100 | (uart3) AT client device name 101 | (512) The maximum length of receive line buffer 102 | [] Quectel EC20 ---> 103 | [] Espressif ESP32 ---> 104 | [*] Espressif ESP8266 ---> 105 | [*] Enable initialize by thread 106 | [*] Enable sample 107 | (realthread) WIFI ssid 108 | (12345678) WIFI password 109 | (uart2) AT client device name 110 | (512) The maximum length of receive line buffer 111 | [] Realthread RW007 ---> 112 | [] SIMCom SIM800C ---> 113 | [] SIMCom SIM76XX ---> 114 | [] Notion MW31 ---> 115 | [] WinnerMicro W60X ---> 116 | [] AiThink A9/A9G ---> 117 | [] Quectel BC26 ---> 118 | [] Luat air720 ---> 119 | [] GOSUNCN ME3616 ---> 120 | [] ChinaMobile M6315 ---> 121 | [] Quectel BC28 ---> 122 | [] Quectel ec200x ---> 123 | [] Neoway N21 ---> 124 | [] Neoway N58 ---> 125 | [] ChinaMobile M5311 ---> 126 | [] ChinaMobile ML305 ---> 127 | Version (latest) ---> 128 | ``` 129 | 130 | - **Quectel M26/MC20**: enable M20/MC20 (2G module) device support; 131 | - **Enable initialize by thread**: enable the use of threads to initialize the device (non-blocking mode initialization); 132 | - **Enable sample**: Open the sample code, the sample code has the registration of the sample device; 133 | - **Power pin**: Configure the power-on pin of the sample device; 134 | - **Power status pin**: Configure the power status pin of the sample device; 135 | - **AT client device name**: Configure the serial device name used by the sample device; 136 | - **The maximum length of receive line buffer**: Configure the maximum data length received in one line of the sample device; 137 | - **Quectel EC20**: enable EC20 (4G module) device support; 138 | - **Espressif ESP8266**: enable ESP8266 (WIFI module) device support; 139 | - **Enable initialize by thread**: enable the use of threads to initialize the device (non-blocking mode initialization); 140 | - **Enable sample**: Open the sample code, the sample code has the registration of the sample device; 141 | - **WIFI ssid**: Configure the WIFI user name connected to the sample device; 142 | - **WIFI password**: Configure the WIFI password connected to the sample device; 143 | - **AT client device name**: Configure the serial device name used by the sample device; 144 | - **The maximum length of receive line buffer**: Configure the maximum length of data received in one line of the sample device; 145 | - **Espressif ESP32**: enable ESP32 (WIFI module) device support; 146 | - **Realthread RW007**: enable RW007 (WIFI module) device support; 147 | - **SIMCom SIM800C**: enable SIM800C (2G module) device support; 148 | - **SIMCom SIM76XX**: enable SIM76XX (4G module) device support; 149 | - **Notion MW31**: enable MW31 (WIFI module) device support; 150 | - **WinnerMicro W60X**: enable W60X (WIFI module) device support; 151 | - **AiThink A9/A9G**: enable A9/A9G (2G module) device support; 152 | - **Quectel BC26**: enable BC26 (NB-IOT module) device support; 153 | - **Luat Air720**: enable air720 (4g module) device support; 154 | - **GOSUNCN ME3616**: enable ME3616 (NB-IOT module) device support; 155 | - **ChinaMobile M6315**: enable M6315 (2G module) device support; 156 | - **Quectel BC28**: enable BC28 (NB-IoT module) device support; 157 | - **Quectel EC200X**: enable EC200T, EC200S (4G module) device support; 158 | - **Neoway N21**: enable N21 (NB-IoT module) device support; 159 | - **Neoway N58**: enable N58 (4G module) device support; 160 | - **ChinaMobile M5311**: enable M5311 (NB-IoT module) device support; 161 | - **ChinaMobile ML305**: enable ML305 (4G module) device support; 162 | - **Version**: download the software package version; 163 | 164 | The above configuration options take 2G module and WIFI module options as examples to introduce the configuration method of the AT device software package of the `V2.X.X` version. The following points are worth noting: 165 | 166 | - `V2.X.X` version supports multiple AT devices to be turned on at the same time. You can view the information of the turned on devices through the `ifocnfig` command in FinSH; 167 | - Devices of `V2.X.X` version need to be registered before they can be used. Currently, device registration is completed in the samples directory file, and users can also customize device registration at the application layer. 168 | - Pin options such as `Power pin` and `Power status pin` are configured according to the specific device hardware connection. If the hardware power-on function is not used, it can be configured as `-1`; 169 | - An AT device corresponds to a serial port name, and the `AT client device name` configured for each device should be different. 170 | 171 | **Introduction to AT component related configuration options** 172 | 173 | After the AT device software package is selected and the related device support is enabled, the client function of the AT component will be selected by default. The following are the AT component configuration options. 174 | 175 | ```c 176 | RT-Thread Components ---> 177 | Network ---> 178 | AT commands ---> 179 | [] Enable debug log output 180 | [] Enable AT commands server 181 | -*- Enable AT commands client 182 | (1) The maximum number of supported clients 183 | -*- Enable BSD Socket API support by AT commnads 184 | [*] Enable CLI(Command-Line Interface) for AT commands 185 | [] Enable print RAW format AT command communication data 186 | (128) The maximum lenght of AT Commonds buffe 187 | ``` 188 | 189 | Among them, the configuration options related to the AT device software package: 190 | 191 | - **The maximum number of supported clients**: The maximum number of supported AT clients (multiple devices selected in the AT device software package need to be configured with the corresponding value); 192 | - **Enable BSD Socket API support by AT commnads**: enable AT Socket function support, select the AT device software package and select this option by default; 193 | - **The maximum lenght of AT Commonds buffe**: The maximum supported length of sending command data. 194 | 195 | ## 3. Matters needing attention ## 196 | 197 | - The module adapted to the AT device software package does not support serving as a TCP Server to complete server-related operations (such as accept, etc.); 198 | - The default device type of the AT device software package is not selected, and the device model needs to be specified when using it; 199 | - The `latest` version supports the access of multiple selected AT devices to realize the AT Socket function. The `V1.X.X` version only supports the access of a single AT device. 200 | - At present, multiple versions of the AT device software package are mainly used to adapt to the changes of AT components and systems. It is recommended to use the latest version of the RT-Thread system and select the `latest` version in the menuconfig option; 201 | - Please refer to the description in `at_sample_xxx.c`, some functions need to increase the setting value of `AT_CMD_MAX_LEN`, `RT_SERIAL_RB_BUFSZ`. 202 | 203 | ## 4. Related documents 204 | 205 | - [AT component programming guide](https://www.rt-thread.org/document/site/programming-manual/at/at/) 206 | - [Apply AT components to connect to ESP8266 module](https://www.rt-thread.org/document/site/application-note/components/at/an0014-at-client/) 207 | 208 | ## 5. Contact 209 | 210 | * Maintenance: RT-Thread development team and community developers 211 | * Homepage: https://github.com/RT-Thread-packages/at_device 212 | 213 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # AT device # 2 | 3 | 中文页 | [英文页](./README.md) 4 | 5 | ## 1. 简介 ## 6 | 7 | 8 | AT device 软件包是由 RT-Thread AT 组件针对不同 AT 设备的移植文件和示例代码组成,目前支持的 AT 设备有:ESP8266、ESP32、M26、MC20、RW007、MW31、SIM800C、W60X 、SIM76XX、A9/A9G、BC26 、AIR720、ME3616、M6315、BC28、EC200X、M5311、L610、ML305、ML307系列设备等,目前上述设备都完成对 `AT socket` 功能的移植,及设备通过 AT 命令实现标准 socket 编程接口,完成 socket 通讯的功能,具体功能介绍可参考 [《RT-Thread 编程指南》](https://www.rt-thread.org/document/site/programming-manual/at/at/)AT 命令章节 。 9 | 10 | ### 1.1. 目录结构 ### 11 | 12 | | 名称 | 说明 | 13 | | ---- | ---- | 14 | | src | AT device 实现源码目录 | 15 | | inc | AT device 头文件目录 | 16 | | sample | 不同设备示例文件目录 | 17 | | class | 不同设备针对 AT 组件的移植适配目录 | 18 | | class/esp8266 | ESP8266 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 19 | | class/esp32 | ESP32 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 20 | | class/rw007 | RW007 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 21 | | class/sim800c | SIM800C 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 22 | | class/sim76xx | SIM76XX 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 23 | | class/m26 | M26/MC20 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 24 | | class/ec20 | EC20 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 25 | | class/mw31 | MW31 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 26 | | class/w60x | W60X 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 27 | | class/a9g | A9G 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 28 | | class/bc26 | bc26 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 29 | | class/air720 | air720 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 30 | | class/me3616 | me3616 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 31 | | class/m6315 | m6315 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 32 | | class/bc28 | bc28 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 33 | | class/ec200x | EC200T、EC200S 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 34 | | class/n21 | N21 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 35 | | class/n58 | N58 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 36 | | class/m5311 | M5311 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 37 | | class/l610 | L610 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 38 | | class/ml305 | ML305 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 39 | | class/ml307 | ML307 设备针对 AT 组件的移植目录,实现 AT Socket 功能 | 40 | 41 | ### 1.2 许可证 ### 42 | 43 | 详见 `LICENSE` 文件。 44 | 45 | ### 1.3 依赖 ### 46 | 47 | - RT_Thread 4.0.2+ 48 | - RT_Thread AT 组件 1.3.0+ 49 | - RT_Thread SAL 组件 50 | - RT-Thread netdev 组件 51 | 52 | ## 2. 获取方式 ## 53 | 54 | AT device 软件包是对 AT 组件和 AT socket 功能的移植,需开启 AT 组件库和 AT socket 功能来获取 AT device 软件包。 55 | 56 | **版本号说明** 57 | 58 | AT device 软件包目前已经发布多个版本,各个版本之间选项配置方式和其对应的系统版本有所不同,下面主要列出当前可使用的软件包版本信息: 59 | 60 | - **V1.2.0**:适用于 RT-Thread 版本小于 V3.1.3,AT 组件版本等于 V1.0.0; 61 | - **V1.3.0**:适用于 RT-Thread 版本小于 V3.1.3,AT 组件版本等于 V1.1.0; 62 | - **V1.4.0**:适用于 RT-Thread 版本小于 V3.1.3或等于 V4.0.0, AT 组件版本等于 V1.2.0; 63 | - **V1.5.0**:适用于 RT-Thread 版本小于 V3.1.3 或等于 V4.0.0, AT 组件版本等于 V1.2.0; 64 | - **V1.6.0**:适用于 RT-Thread 版本等于 V3.1.3 或等于 V4.0.1, AT 组件版本等于 V1.2.0; 65 | - **V2.0.0/V2.0.1**:适用于 RT-Thread 版本大于 V4.0.1 或者大于 3.1.3, AT 组件版本等于 V1.3.0; 66 | - **latest**:只适用于 RT-Thread 版本大于 V4.0.1 或者大于 3.1.3, AT 组件版本等于 V1.3.0; 67 | 68 | > 上述 版本判断在 menuconfig 中自动完成,at_device 软件包选择版本时会根据当前系统环境给出最佳版本支持,这里版本介绍作为运行环境参考。 69 | 70 | 针对不同的版本号,在 ENV 中的选项配置也有所不同,主要分为如下几部分: 71 | 72 | **V1.X.X 版本配置选项介绍** 73 | 74 | 开启 AT device 软件包,该版本只支持**同时开启一种 AT 设备**, 配置选项具体如下所示: 75 | 76 | RT-Thread online packages ---> 77 | IoT - internet of things ---> 78 | -*- AT DEVICE: RT-Thread AT component porting or samples for different device 79 | [ ] Enable at device init by thread 80 | AT socket device modules (Not selected, please select) ---> 81 | Version (V1.6.0) ---> 82 | 83 | - **Enable at device init by thread**: 配置开启设备网络初始化是否通过创建线程完成; 84 | - **AT socket device modules**: AT 设备选择,目前仅支持 RW007、ESP8266、M26/MC20、EC20、SIM800C、SIM76XX;更多的设备支持请选择 V2.X.X 分支。 85 | - **Version**: 下载软件包版本; 86 | 87 | **V2.X.X (latest) 版本配置选项介绍** 88 | 89 | 开启 AT device 软件包,该版本支持**同时开启多种 AT 设备**配置选项具体如下所示: 90 | 91 | ```c 92 | RT-Thread online packages ---> 93 | IoT - internet of things ---> 94 | -*- AT DEVICE: RT-Thread AT component porting or samples for different device 95 | [*] Quectel M26/MC20 ---> 96 | [*] Enable initialize by thread 97 | [*] Enable sample 98 | (-1) Power pin 99 | (-1) Power status pin 100 | (uart3) AT client device name 101 | (512) The maximum length of receive line buffer 102 | [ ] Quectel EC20 ---> 103 | [ ] Espressif ESP32 ---> 104 | [*] Espressif ESP8266 ---> 105 | [*] Enable initialize by thread 106 | [*] Enable sample 107 | (realthread) WIFI ssid 108 | (12345678) WIFI password 109 | (uart2) AT client device name 110 | (512) The maximum length of receive line buffer 111 | [ ] Realthread RW007 ---> 112 | [ ] SIMCom SIM800C ---> 113 | [ ] SIMCom SIM76XX ---> 114 | [ ] Notion MW31 ---> 115 | [ ] WinnerMicro W60X ---> 116 | [ ] AiThink A9/A9G ---> 117 | [ ] Quectel BC26 ---> 118 | [ ] Luat air720 ---> 119 | [ ] GOSUNCN ME3616 ---> 120 | [ ] ChinaMobile M6315 ---> 121 | [ ] Quectel BC28 ---> 122 | [ ] Quectel ec200x ---> 123 | [ ] Neoway N21 ---> 124 | [ ] Neoway N58 ---> 125 | [ ] ChinaMobile M5311 ---> 126 | [ ] ChinaMobile ML305 ---> 127 | Version (latest) ---> 128 | ``` 129 | 130 | - **Quectel M26/MC20**:开启 M20/MC20(2G 模块)设备支持; 131 | - **Enable initialize by thread**:开启使用线程进行设备初始化功能(非阻塞模式初始化); 132 | - **Enable sample**:开启示例代码,该示例代码中有对示例设备的注册; 133 | - **Power pin**:配置该示例设备上电引脚; 134 | - **Power status pin**:配置该示例设备上电状态引脚; 135 | - **AT client device name**:配置该示例设备使用的串口设备名称; 136 | - **The maximum length of receive line buffer**:配置该示例设备最大一行接收的数据长度; 137 | - **Quectel EC20**:开启 EC20(4G 模块)设备支持; 138 | - **Espressif ESP8266**:开启 ESP8266 (WIFI 模块)设备支持; 139 | - **Enable initialize by thread**:开启使用线程进行设备初始化功能(非阻塞模式初始化); 140 | - **Enable sample**:开启示例代码,该示例代码中有对示例设备的注册; 141 | - **WIFI ssid**:配置该示例设备连接的 WIFI 用户名; 142 | - **WIFI password**:配置该示例设备连接的 WIFI 密码; 143 | - **AT client device name**:配置该示例设备使用的串口设备名称; 144 | - **The maximum length of receive line buffer**:配置该示例设备最大一行接收的数据长度; 145 | - **Espressif ESP32**:开启 ESP32 (WIFI 模块)设备支持; 146 | - **Realthread RW007**:开启 RW007 (WIFI 模块)设备支持; 147 | - **SIMCom SIM800C**:开启 SIM800C (2G 模块)设备支持; 148 | - **SIMCom SIM76XX**:开启 SIM76XX (4G 模块)设备支持; 149 | - **Notion MW31**:开启 MW31 (WIFI 模块)设备支持; 150 | - **WinnerMicro W60X**:开启 W60X (WIFI 模块)设备支持; 151 | - **AiThink A9/A9G**:开启 A9/A9G (2G 模块)设备支持; 152 | - **Quectel BC26**:开启 BC26(NB-IOT 模块)设备支持; 153 | - **Luat Air720**:开启 air720(4g 模块)设备支持; 154 | - **GOSUNCN ME3616**:开启 ME3616(NB-IOT 模块)设备支持; 155 | - **ChinaMobile M6315**:开启 M6315 (2G 模块)设备支持; 156 | - **Quectel BC28**:开启 BC28(NB-IoT 模块)设备支持; 157 | - **Quectel EC200X**:开启 EC200T、EC200S(4G 模块)设备支持; 158 | - **Neoway N21**:开启 N21(NB-IoT 模块)设备支持; 159 | - **Neoway N58**:开启 N58(4G 模块)设备支持; 160 | - **ChinaMobile M5311**:开启 M5311(NB-IoT 模块)设备支持; 161 | - **ChinaMobile ML305**:开启 ML305(4G 模块)设备支持; 162 | - **Version** 下载软件包版本; 163 | 164 | 上面配置选项以 2G 模块和 WIFI 模块选项为例,介绍了`V2.X.X` 版本 AT device 软件包配置方式,如下几点值得注意: 165 | 166 | - `V2.X.X` 版本支持同时开启多个 AT 设备,可以在 FinSH 中通过 `ifocnfig` 命令查看开启的设备信息; 167 | - `V2.X.X` 版本设备需要注册之后才可使用,目前在 samples 目录文件中完成设备注册,用户也可以在应用层自定义设备注册。 168 | - `Power pin` 和 `Power status pin` 等引脚选项根据具体设备硬件连接情况配置,如果不使用硬件上电功能,可以配置为 `-1`; 169 | - 一个 AT 设备对应一个串口名称,及每个设备配置的`AT client device name` 应该都不相同。 170 | 171 | **AT 组件相关配置选项介绍** 172 | 173 | 选中 AT device 软件包并开启相关设备支持之后,会默认选中 AT 组件的客户端功能,下面是 AT 组件配置选项, 174 | 175 | ```c 176 | RT-Thread Components ---> 177 | Network ---> 178 | AT commands ---> 179 | [ ] Enable debug log output 180 | [ ] Enable AT commands server 181 | -*- Enable AT commands client 182 | (1) The maximum number of supported clients 183 | -*- Enable BSD Socket API support by AT commnads 184 | [*] Enable CLI(Command-Line Interface) for AT commands 185 | [ ] Enable print RAW format AT command communication data 186 | (128) The maximum lenght of AT Commonds buffe 187 | ``` 188 | 189 | 其中和 AT device 软件包相关的配置选项: 190 | 191 | - **The maximum number of supported clients**:最大支持的同时开启的 AT 客户端数量(AT device 软件包中选中多个设备需要配置该选项为对应数值); 192 | - **Enable BSD Socket API support by AT commnads**:开启 AT Socket 功能支持,选中 AT device 软件包默认选中该选项; 193 | - **The maximum lenght of AT Commonds buffe**:最大支持的发送命令数据的长度。 194 | 195 | ## 3. 注意事项 ## 196 | 197 | - AT device 软件包适配的模块暂时不支持作为 TCP Server 完成服务器相关操作(如 accept 等); 198 | - AT device 软件包默认设备类型为未选择,使用时需要指定使用设备型号; 199 | - `latest` 版本支持多个选中多个 AT 设备接入实现 AT Socket 功能,`V1.X.X` 版本只支持单个 AT 设备接入。 200 | - AT device 软件包目前多个版本主要用于适配 AT 组件和系统的改动,推荐使用最新版本 RT-Thread 系统,并在 menuconfig 选项中选择 `latest` 版本; 201 | - 请参考 `at_sample_xxx.c` 中说明,部分功能需要增加`AT_CMD_MAX_LEN`、`RT_SERIAL_RB_BUFSZ`设定值大小。 202 | 203 | ## 4. 相关文档 204 | 205 | - [AT 组件编程指南](https://www.rt-thread.org/document/site/programming-manual/at/at/) 206 | - [应用 AT 组件连接 ESP8266 模块](https://www.rt-thread.org/document/site/application-note/components/at/an0014-at-client/) 207 | 208 | ## 5. 联系方式 209 | 210 | * 维护:RT-Thread 开发团队及社区开发者 211 | * 主页:https://github.com/RT-Thread-packages/at_device 212 | -------------------------------------------------------------------------------- /SConscript: -------------------------------------------------------------------------------- 1 | from building import * 2 | 3 | cwd = GetCurrentDir() 4 | path = [cwd + '/inc'] 5 | src = Glob('src/*.c') 6 | 7 | # A9G 8 | if GetDepend(['AT_DEVICE_USING_A9G']): 9 | path += [cwd + '/class/a9g'] 10 | src += Glob('class/a9g/at_device_a9g.c') 11 | if GetDepend(['AT_USING_SOCKET']): 12 | src += Glob('class/a9g/at_socket_a9g.c') 13 | if GetDepend(['AT_DEVICE_A9G_SAMPLE']): 14 | src += Glob('samples/at_sample_a9g.c') 15 | 16 | # M26/MC20 17 | if GetDepend(['AT_DEVICE_USING_M26']): 18 | path += [cwd + '/class/m26'] 19 | src += Glob('class/m26/at_device_m26.c') 20 | if GetDepend(['AT_USING_SOCKET']): 21 | src += Glob('class/m26/at_socket_m26.c') 22 | if GetDepend(['AT_DEVICE_M26_SAMPLE']): 23 | src += Glob('samples/at_sample_m26.c') 24 | 25 | # EC20 26 | if GetDepend(['AT_DEVICE_USING_EC20']): 27 | path += [cwd + '/class/ec20'] 28 | src += Glob('class/ec20/at_device_ec20.c') 29 | if GetDepend(['AT_USING_SOCKET']): 30 | src += Glob('class/ec20/at_socket_ec20.c') 31 | if GetDepend(['AT_DEVICE_EC20_SAMPLE']): 32 | src += Glob('samples/at_sample_ec20.c') 33 | 34 | # ESP8266 35 | if GetDepend(['AT_DEVICE_USING_ESP8266']): 36 | path += [cwd + '/class/esp8266'] 37 | src += Glob('class/esp8266/at_device_esp8266.c') 38 | if GetDepend(['AT_USING_SOCKET']): 39 | src += Glob('class/esp8266/at_socket_esp8266.c') 40 | if GetDepend(['AT_DEVICE_ESP8266_SAMPLE']): 41 | src += Glob('samples/at_sample_esp8266.c') 42 | 43 | # ESP32 44 | if GetDepend(['AT_DEVICE_USING_ESP32']): 45 | path += [cwd + '/class/esp32'] 46 | src += Glob('class/esp32/at_device_esp32.c') 47 | if GetDepend(['AT_USING_SOCKET']): 48 | src += Glob('class/esp32/at_socket_esp32.c') 49 | if GetDepend(['AT_DEVICE_ESP32_SAMPLE']): 50 | src += Glob('samples/at_sample_esp32.c') 51 | 52 | # MW31 53 | if GetDepend(['AT_DEVICE_USING_MW31']): 54 | path += [cwd + '/class/mw31'] 55 | src += Glob('class/mw31/at_device_mw31.c') 56 | if GetDepend(['AT_USING_SOCKET']): 57 | src += Glob('class/mw31/at_socket_mw31.c') 58 | if GetDepend(['AT_DEVICE_MW31_SAMPLE']): 59 | src += Glob('samples/at_sample_mw31.c') 60 | 61 | # RW007 62 | if GetDepend(['AT_DEVICE_USING_RW007']): 63 | path += [cwd + '/class/rw007'] 64 | src += Glob('class/rw007/at_device_rw007.c') 65 | if GetDepend(['AT_USING_SOCKET']): 66 | src += Glob('class/rw007/at_socket_rw007.c') 67 | if GetDepend(['AT_DEVICE_RW007_SAMPLE']): 68 | src += Glob('samples/at_sample_rw007.c') 69 | 70 | # SIM800C 71 | if GetDepend(['AT_DEVICE_USING_SIM800C']): 72 | path += [cwd + '/class/sim800c'] 73 | src += Glob('class/sim800c/at_device_sim800c.c') 74 | if GetDepend(['AT_USING_SOCKET']): 75 | src += Glob('class/sim800c/at_socket_sim800c.c') 76 | if GetDepend(['AT_DEVICE_SIM800C_SAMPLE']): 77 | src += Glob('samples/at_sample_sim800c.c') 78 | 79 | # SIM76XX 80 | if GetDepend(['AT_DEVICE_USING_SIM76XX']): 81 | path += [cwd + '/class/sim76xx'] 82 | src += Glob('class/sim76xx/at_device_sim76xx.c') 83 | if GetDepend(['AT_USING_SOCKET']): 84 | src += Glob('class/sim76xx/at_socket_sim76xx.c') 85 | if GetDepend(['AT_DEVICE_SIM76XX_SAMPLE']): 86 | src += Glob('samples/at_sample_sim76xx.c') 87 | 88 | # W60X 89 | if GetDepend(['AT_DEVICE_USING_W60X']): 90 | path += [cwd + '/class/w60x'] 91 | src += Glob('class/w60x/at_device_w60x.c') 92 | if GetDepend(['AT_USING_SOCKET']): 93 | src += Glob('class/w60x/at_socket_w60x.c') 94 | if GetDepend(['AT_DEVICE_W60X_SAMPLE']): 95 | src += Glob('samples/at_sample_w60x.c') 96 | 97 | # BC26 98 | if GetDepend(['AT_DEVICE_USING_BC26']): 99 | path += [cwd + '/class/bc26'] 100 | src += Glob('class/bc26/at_device_bc26.c') 101 | if GetDepend(['AT_USING_SOCKET']): 102 | src += Glob('class/bc26/at_socket_bc26.c') 103 | if GetDepend(['AT_DEVICE_BC26_SAMPLE']): 104 | src += Glob('samples/at_sample_bc26.c') 105 | 106 | # air720 107 | if GetDepend(['AT_DEVICE_USING_AIR720']): 108 | path += [cwd + '/class/air720'] 109 | src += Glob('class/air720/at_device_air720.c') 110 | if GetDepend(['AT_USING_SOCKET']): 111 | src += Glob('class/air720/at_socket_air720.c') 112 | if GetDepend(['AT_DEVICE_AIR720_SAMPLE']): 113 | src += Glob('samples/at_sample_air720.c') 114 | 115 | # ME3616 116 | if GetDepend(['AT_DEVICE_USING_ME3616']): 117 | path += [cwd + '/class/me3616'] 118 | src += Glob('class/me3616/at_device_me3616.c') 119 | if GetDepend(['AT_USING_SOCKET']): 120 | src += Glob('class/me3616/at_socket_me3616.c') 121 | if GetDepend(['AT_DEVICE_ME3616_SAMPLE']): 122 | src += Glob('samples/at_sample_me3616.c') 123 | 124 | # M6315 125 | if GetDepend(['AT_DEVICE_USING_M6315']): 126 | path += [cwd + '/class/m6315'] 127 | src += Glob('class/m6315/at_device_m6315.c') 128 | if GetDepend(['AT_USING_SOCKET']): 129 | src += Glob('class/m6315/at_socket_m6315.c') 130 | if GetDepend(['AT_DEVICE_M6315_SAMPLE']): 131 | src += Glob('samples/at_sample_m6315.c') 132 | 133 | # BC28 134 | if GetDepend(['AT_DEVICE_USING_BC28']): 135 | path += [cwd + '/class/bc28'] 136 | src += Glob('class/bc28/at_device_bc28.c') 137 | if GetDepend(['AT_USING_SOCKET']): 138 | src += Glob('class/bc28/at_socket_bc28.c') 139 | if GetDepend(['AT_DEVICE_BC28_SAMPLE']): 140 | src += Glob('samples/at_sample_bc28.c') 141 | 142 | # EC200X 143 | if GetDepend(['AT_DEVICE_USING_EC200X']): 144 | path += [cwd + '/class/ec200x'] 145 | src += Glob('class/ec200x/at_device_ec200x.c') 146 | if GetDepend(['AT_USING_SOCKET']): 147 | src += Glob('class/ec200x/at_socket_ec200x.c') 148 | if GetDepend(['AT_DEVICE_EC200X_SAMPLE']): 149 | src += Glob('samples/at_sample_ec200x.c') 150 | 151 | # N21 152 | if GetDepend(['AT_DEVICE_USING_N21']): 153 | path += [cwd + '/class/n21'] 154 | src += Glob('class/n21/at_device_n21.c') 155 | if GetDepend(['AT_USING_SOCKET']): 156 | src += Glob('class/n21/at_socket_n21.c') 157 | if GetDepend(['AT_DEVICE_N21_SAMPLE']): 158 | src += Glob('samples/at_sample_n21.c') 159 | 160 | # N58 161 | if GetDepend(['AT_DEVICE_USING_N58']): 162 | path += [cwd + '/class/n58'] 163 | src += Glob('class/n58/at_device_n58.c') 164 | if GetDepend(['AT_USING_SOCKET']): 165 | src += Glob('class/n58/at_socket_n58.c') 166 | if GetDepend(['AT_DEVICE_N58_SAMPLE']): 167 | src += Glob('samples/at_sample_n58.c') 168 | 169 | # M5311 170 | if GetDepend(['AT_DEVICE_USING_M5311']): 171 | path += [cwd + '/class/m5311'] 172 | src += Glob('class/m5311/at_device_m5311.c') 173 | if GetDepend(['AT_USING_SOCKET']): 174 | src +=Glob('class/m5311/at_socket_m5311.c') 175 | if GetDepend(['AT_DEVICE_M5311_SAMPLE']): 176 | src +=Glob('samples/at_sample_m5311.c') 177 | 178 | # N720 179 | if GetDepend(['AT_DEVICE_USING_N720']): 180 | path += [cwd + '/class/n720'] 181 | src += Glob('class/n720/at_device_n720.c') 182 | if GetDepend(['AT_USING_SOCKET']): 183 | src += Glob('class/n720/at_socket_n720.c') 184 | if GetDepend(['AT_DEVICE_N720_SAMPLE']): 185 | src += Glob('samples/at_sample_n720.c') 186 | 187 | # L610 188 | if GetDepend(['AT_DEVICE_USING_L610']): 189 | path += [cwd + '/class/l610'] 190 | src += Glob('class/l610/at_device_l610.c') 191 | if GetDepend(['AT_USING_SOCKET']): 192 | src +=Glob('class/l610/at_socket_l610.c') 193 | if GetDepend(['AT_DEVICE_L610_SAMPLE']): 194 | src +=Glob('samples/at_sample_l610.c') 195 | 196 | # ML305 197 | if GetDepend(['AT_DEVICE_USING_ML305']): 198 | path += [cwd + '/class/ml305'] 199 | src += Glob('class/ml305/at_device_ml305.c') 200 | if GetDepend(['AT_USING_SOCKET']): 201 | src +=Glob('class/ml305/at_socket_ml305.c') 202 | if GetDepend(['AT_DEVICE_ML305_SAMPLE']): 203 | src +=Glob('samples/at_sample_ml305.c') 204 | 205 | # ML307 206 | if GetDepend(['AT_DEVICE_USING_ML307']): 207 | path += [cwd + '/class/ml307'] 208 | src += Glob('class/ml307/at_device_ml307.c') 209 | if GetDepend(['AT_USING_SOCKET']): 210 | src +=Glob('class/ml307/at_socket_ml307.c') 211 | if GetDepend(['AT_DEVICE_ML307_SAMPLE']): 212 | src +=Glob('samples/at_sample_ml307.c') 213 | 214 | group = DefineGroup('at_device', src, depend = ['PKG_USING_AT_DEVICE'], CPPPATH = path) 215 | 216 | Return('group') 217 | -------------------------------------------------------------------------------- /class/a9g/at_device_a9g.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-11-23 luliang first version 9 | */ 10 | 11 | #ifndef __A9G_DEVICE_H__ 12 | #define __A9G_DEVICE_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the a9g device */ 23 | #define AT_DEVICE_A9G_SOCKETS_NUM 8 24 | 25 | struct at_device_a9g 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* a9g device socket initialize */ 41 | int a9g_socket_init(struct at_device *device); 42 | 43 | /* a9g device class socket register */ 44 | int a9g_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | 53 | #endif /* __AT_DEVICE_A9G_H__*/ 54 | -------------------------------------------------------------------------------- /class/air720/at_device_air720.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_AIR720_H__ 12 | #define __AT_DEVICE_AIR720_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the air720 device */ 23 | #define AT_DEVICE_AIR720_SOCKETS_NUM 6 24 | 25 | struct at_device_air720 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* air720 device socket initialize */ 41 | int air720_socket_init(struct at_device *device); 42 | 43 | /* air720 device class socket register */ 44 | int air720_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_AIR720_H__ */ 53 | -------------------------------------------------------------------------------- /class/bc26/at_device_bc26.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-13 qiyongzhong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_BC26_H__ 12 | #define __AT_DEVICE_BC26_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the bc26 device */ 23 | #define AT_DEVICE_BC26_SOCKETS_NUM 5 24 | 25 | struct at_device_bc26 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *socket_data; 36 | void *user_data; 37 | 38 | rt_bool_t power_status; 39 | rt_bool_t sleep_status; 40 | }; 41 | 42 | #ifdef AT_USING_SOCKET 43 | 44 | /* bc26 device socket initialize */ 45 | int bc26_socket_init(struct at_device *device); 46 | 47 | /* bc26 device class socket register */ 48 | int bc26_socket_class_register(struct at_device_class *class); 49 | 50 | #endif /* AT_USING_SOCKET */ 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /* __AT_DEVICE_BC26_H__ */ 57 | 58 | -------------------------------------------------------------------------------- /class/bc28/README.md: -------------------------------------------------------------------------------- 1 | # BC28 2 | 3 | ## 注意事项 4 | 5 | ### 申请 socket 6 | 7 | - BC28 最多支持 7 个 socket,编号 0-6; 8 | - 如果 BC28 使用支持 MQTT 或 CoAP 协议的固件,则相关服务会占用部分 socket,因此最小可用的 socket 并不一定是 0; 9 | - 可以创建 1 个 UDP socket,多个 TCP socket; 10 | - 另外,执行 DNS 域名解析时也会占用 socket; 11 | 12 | ### 连接 socket 13 | 14 | - R02 的基线版本固件才支持 `AT+QTCPIND` 查询 TCP 连接情况,因此目前采用保守的 30 秒延时来确保连接状态; 15 | 16 | -------------------------------------------------------------------------------- /class/bc28/at_device_bc28.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-02-12 luhuadong first version 9 | * 2022-11-9 wangcheng support bc28 low version firmware 10 | */ 11 | 12 | #ifndef __AT_DEVICE_BC28_H__ 13 | #define __AT_DEVICE_BC28_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #include 20 | 21 | #include 22 | 23 | /* The maximum number of sockets supported by the BC28 device */ 24 | #define AT_DEVICE_BC28_SOCKETS_NUM 7 25 | #define IP_ADDR_SIZE_MAX 16 26 | 27 | #define AT_DEVICE_BC28_MIN_SOCKET BC28_SAMPLE_MIN_SOCKET 28 | #define BC28_AT_CLIENT_BAUD_RATE BC28_SAMPLE_BAUD_RATE 29 | 30 | struct at_device_bc28 31 | { 32 | char *device_name; 33 | char *client_name; 34 | 35 | int power_pin; /* BC28 has not power_en, it should be reset pin */ 36 | int power_status_pin; /* ADC */ 37 | size_t recv_bufsz; 38 | struct at_device device; 39 | 40 | void *socket_data; 41 | void *user_data; 42 | 43 | rt_bool_t power_status; 44 | rt_bool_t sleep_status; 45 | }; 46 | 47 | #ifdef AT_USING_SOCKET 48 | 49 | /* bc28 device socket initialize */ 50 | int bc28_socket_init(struct at_device *device); 51 | 52 | /* bc28 device class socket register */ 53 | int bc28_socket_class_register(struct at_device_class *class); 54 | 55 | #endif /* AT_USING_SOCKET */ 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif /* __AT_DEVICE_BC28_H__ */ 62 | -------------------------------------------------------------------------------- /class/ec20/at_device_ec20.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_EC20_H__ 12 | #define __AT_DEVICE_EC20_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the ec20 device */ 23 | #define AT_DEVICE_EC20_SOCKETS_NUM 5 24 | 25 | struct at_device_ec20 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *socket_data; 36 | void *user_data; 37 | }; 38 | 39 | #ifdef AT_USING_SOCKET 40 | 41 | /* ec20 device socket initialize */ 42 | int ec20_socket_init(struct at_device *device); 43 | 44 | /* ec20 device class socket register */ 45 | int ec20_socket_class_register(struct at_device_class *class); 46 | 47 | #endif /* AT_USING_SOCKET */ 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* __AT_DEVICE_EC20_H__ */ 54 | -------------------------------------------------------------------------------- /class/ec200x/at_device_ec200x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-04-20 qiyongzhong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_EC200X_H__ 12 | #define __AT_DEVICE_EC200X_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the ec200x device */ 23 | #define AT_DEVICE_EC200X_SOCKETS_NUM 5 24 | 25 | struct at_device_ec200x 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | int wakeup_pin; 33 | size_t recv_line_num; 34 | void (*power_ctrl)(int is_on); 35 | struct at_device device; 36 | 37 | void *socket_data; 38 | void *user_data; 39 | 40 | rt_bool_t power_status; 41 | rt_bool_t sleep_status; 42 | int rssi; 43 | }; 44 | 45 | #ifdef AT_USING_SOCKET 46 | 47 | /* ec200x device socket initialize */ 48 | int ec200x_socket_init(struct at_device *device); 49 | 50 | /* ec200x device class socket register */ 51 | int ec200x_socket_class_register(struct at_device_class *class); 52 | 53 | #endif /* AT_USING_SOCKET */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* __AT_DEVICE_EC200X_H__ */ 60 | 61 | -------------------------------------------------------------------------------- /class/esp32/at_device_esp32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_ESP32_H__ 12 | #define __AT_DEVICE_ESP32_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | #define ESP32_DEFAULT_AT_VERSION "1.4.0.0" 22 | #define ESP32_DEFAULT_AT_VERSION_NUM 0x1040000 23 | 24 | /* The maximum number of sockets supported by the esp32 device */ 25 | #define AT_DEVICE_ESP32_SOCKETS_NUM 5 26 | 27 | struct at_device_esp32 28 | { 29 | char *device_name; 30 | char *client_name; 31 | 32 | char *wifi_ssid; 33 | char *wifi_password; 34 | size_t recv_line_num; 35 | struct at_device device; 36 | 37 | void *user_data; 38 | }; 39 | 40 | #ifdef AT_USING_SOCKET 41 | 42 | /* esp32 device socket initialize */ 43 | int esp32_socket_init(struct at_device *device); 44 | 45 | /* esp32 device class socket register */ 46 | int esp32_socket_class_register(struct at_device_class *class); 47 | 48 | /* convert the esp32 AT version string to hexadecimal */ 49 | unsigned int esp32_at_version_to_hex(const char *str); 50 | 51 | /* obtain the esp32 AT version number */ 52 | unsigned int esp32_get_at_version(void); 53 | #endif /* AT_USING_SOCKET */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* __AT_DEVICE_ESP32_H__ */ 60 | -------------------------------------------------------------------------------- /class/esp8266/at_device_esp8266.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_ESP8266_H__ 12 | #define __AT_DEVICE_ESP8266_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | #define ESP8266_DEFAULT_AT_VERSION "1.4.0.0" 22 | #define ESP8266_DEFAULT_AT_VERSION_NUM 0x1040000 23 | 24 | /* The maximum number of sockets supported by the esp8266 device */ 25 | #define AT_DEVICE_ESP8266_SOCKETS_NUM 5 26 | 27 | struct at_device_esp8266 28 | { 29 | char *device_name; 30 | char *client_name; 31 | 32 | char *wifi_ssid; 33 | char *wifi_password; 34 | size_t recv_line_num; 35 | struct at_device device; 36 | 37 | void *user_data; 38 | }; 39 | 40 | #ifdef AT_USING_SOCKET 41 | 42 | /* esp8266 device socket initialize */ 43 | int esp8266_socket_init(struct at_device *device); 44 | 45 | /* esp8266 device class socket register */ 46 | int esp8266_socket_class_register(struct at_device_class *class); 47 | 48 | /* convert the esp8266 AT version string to hexadecimal */ 49 | unsigned int esp8266_at_version_to_hex(const char *str); 50 | 51 | /* obtain the esp8266 AT version number */ 52 | unsigned int esp8266_get_at_version(void); 53 | #endif /* AT_USING_SOCKET */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* __AT_DEVICE_ESP8266_H__ */ 60 | -------------------------------------------------------------------------------- /class/l610/at_device_l610.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-10-28 zhangyang first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_L610_H__ 12 | #define __AT_DEVICE_L610_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | /* The maximum number of sockets supported by the l610 device */ 22 | #define AT_DEVICE_L610_SOCKETS_NUM 6 23 | 24 | struct at_device_l610 25 | { 26 | char *device_name; 27 | char *client_name; 28 | 29 | int power_pin; 30 | int power_status_pin; 31 | size_t recv_line_num; 32 | struct at_device device; 33 | 34 | void *socket_data; 35 | void *user_data; 36 | 37 | rt_bool_t power_status; 38 | rt_bool_t sleep_status; 39 | }; 40 | 41 | #ifdef AT_USING_SOCKET 42 | 43 | /* l610 device socket initialize */ 44 | int l610_socket_init(struct at_device *device); 45 | 46 | /* l610 device class socket register */ 47 | int l610_socket_class_register(struct at_device_class *class); 48 | 49 | #endif /* AT_USING_SOCKET */ 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif /* __AT_DEVICE_L610_H__ */ 56 | -------------------------------------------------------------------------------- /class/m26/at_device_m26.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_M26_H__ 12 | #define __AT_DEVICE_M26_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the m26 device */ 23 | #define AT_DEVICE_M26_SOCKETS_NUM 6 24 | 25 | struct at_device_m26 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* m26 device socket initialize */ 41 | int m26_socket_init(struct at_device *device); 42 | 43 | /* m26 device class socket register */ 44 | int m26_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_M26_H__ */ 53 | -------------------------------------------------------------------------------- /class/m5311/at_device_m5311.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-03-09 LXGMAX first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_M5311_H__ 12 | #define __AT_DEVICE_M5311_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* Max number of sockets supported by the m5311 device */ 23 | #define AT_DEVICE_M5311_SOCKETS_NUM 5 24 | 25 | struct at_device_m5311{ 26 | char *device_name; 27 | char *client_name; 28 | 29 | int power_pin; 30 | size_t recieve_line_num; 31 | struct at_device device; 32 | 33 | void *socket_data; 34 | void *user_data; 35 | }; 36 | 37 | #ifdef AT_USING_SOCKET 38 | /* m5311 device socket initialize */ 39 | int m5311_socket_init(struct at_device *device); 40 | 41 | /* m5311 device class socket register */ 42 | int m5311_socket_class_register(struct at_device_class *class); 43 | 44 | #endif /* AT_USING_SOCKET */ 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif /* __AT_DEVICE_M5311_H__ */ 51 | -------------------------------------------------------------------------------- /class/m6315/at_device_m6315.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_M6315_H__ 12 | #define __AT_DEVICE_M6315_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the m6315 device */ 23 | #define AT_DEVICE_M6315_SOCKETS_NUM 8 24 | 25 | struct at_device_m6315 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* m6315 device socket initialize */ 41 | int m6315_socket_init(struct at_device *device); 42 | 43 | /* m6315 device class socket register */ 44 | int m6315_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_M6315_H__ */ 53 | -------------------------------------------------------------------------------- /class/me3616/at_device_me3616.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-30 qiyongzhong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_ME3616_H__ 12 | #define __AT_DEVICE_ME3616_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the me3616 device */ 23 | #define AT_DEVICE_ME3616_SOCKETS_NUM 5 24 | 25 | struct at_device_me3616 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *socket_data; 36 | void *user_data; 37 | 38 | rt_bool_t power_status; 39 | rt_bool_t sleep_status; 40 | }; 41 | 42 | #ifdef AT_USING_SOCKET 43 | 44 | /* me3616 device socket initialize */ 45 | int me3616_socket_init(struct at_device *device); 46 | 47 | /* me3616 device class socket register */ 48 | int me3616_socket_class_register(struct at_device_class *class); 49 | 50 | #endif /* AT_USING_SOCKET */ 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /* __AT_DEVICE_ME3616_H__ */ 57 | 58 | -------------------------------------------------------------------------------- /class/me3616/at_socket_me3616.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-30 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define LOG_TAG "at.skt.me3616" 17 | #include 18 | 19 | #if defined(AT_DEVICE_USING_ME3616) && defined(AT_USING_SOCKET) 20 | 21 | #define ME3616_MODULE_SEND_MAX_SIZE 512 22 | 23 | static int me3616_socket_fd[AT_DEVICE_ME3616_SOCKETS_NUM] = {0}; 24 | 25 | static at_evt_cb_t at_evt_cb_set[] = { 26 | [AT_SOCKET_EVT_RECV] = NULL, 27 | [AT_SOCKET_EVT_CLOSED] = NULL, 28 | }; 29 | 30 | static int me3616_get_socket_idx(int sock) 31 | { 32 | int i; 33 | 34 | if (sock < 0) 35 | { 36 | return(-1); 37 | } 38 | 39 | for (i=0; iuser_data; 63 | struct at_device *device = (struct at_device *) socket->device; 64 | 65 | if (me3616_socket_fd[device_socket] == -1) 66 | { 67 | return RT_EOK; 68 | } 69 | 70 | resp = at_create_resp(64, 0, rt_tick_from_millisecond(300)); 71 | if (resp == RT_NULL) 72 | { 73 | LOG_E("no memory for resp create."); 74 | return -RT_ENOMEM; 75 | } 76 | 77 | result = at_obj_exec_cmd(device->client, resp, "AT+ESOCL=%d", me3616_socket_fd[device_socket]); 78 | me3616_socket_fd[device_socket] = -1; 79 | 80 | at_delete_resp(resp); 81 | 82 | return result; 83 | } 84 | 85 | /** 86 | * create TCP/UDP client or server connect by AT commands. 87 | * 88 | * @param socket current socket 89 | * @param ip server or client IP address 90 | * @param port server or client port 91 | * @param type connect socket type(tcp, udp) 92 | * @param is_client connection is client 93 | * 94 | * @return 0: connect success 95 | * -1: connect failed, send commands error or type error 96 | * -2: wait socket event timeout 97 | * -5: no memory 98 | */ 99 | static int me3616_socket_connect(struct at_socket *socket, char *ip, int32_t port, 100 | enum at_socket_type type, rt_bool_t is_client) 101 | { 102 | #define CONN_RESP_SIZE 128 103 | 104 | int type_code = 0; 105 | int result = RT_EOK; 106 | at_response_t resp = RT_NULL; 107 | int device_socket = (int) socket->user_data; 108 | struct at_device *device = (struct at_device *) socket->device; 109 | int sock = -1; 110 | 111 | RT_ASSERT(ip); 112 | RT_ASSERT(port >= 0); 113 | 114 | if ( ! is_client) 115 | { 116 | return -RT_ERROR; 117 | } 118 | 119 | switch(type) 120 | { 121 | case AT_SOCKET_TCP: 122 | type_code = 1; 123 | break; 124 | case AT_SOCKET_UDP: 125 | type_code = 2; 126 | break; 127 | default: 128 | LOG_E("%s device socket(%d) connect type error.", device->name, device_socket); 129 | return -RT_ERROR; 130 | } 131 | 132 | resp = at_create_resp(CONN_RESP_SIZE, 0, rt_tick_from_millisecond(300)); 133 | if (resp == RT_NULL) 134 | { 135 | LOG_E("no memory for resp create."); 136 | return -RT_ENOMEM; 137 | } 138 | 139 | if (me3616_socket_fd[device_socket] != -1) 140 | { 141 | at_obj_exec_cmd(device->client, resp, "AT+ESOCL=%d", me3616_socket_fd[device_socket]); 142 | me3616_socket_fd[device_socket] = -1; 143 | } 144 | 145 | if (at_obj_exec_cmd(device->client, resp, "AT+ESOC=1,%d,1", type_code) < 0) 146 | { 147 | result = -RT_ERROR; 148 | goto __exit; 149 | } 150 | 151 | if (at_resp_parse_line_args_by_kw(resp, "+ESOC=", "+ESOC=%d", &sock) <= 0) 152 | { 153 | result = -RT_ERROR; 154 | goto __exit; 155 | } 156 | 157 | at_resp_set_info(resp, CONN_RESP_SIZE, 0, (45*RT_TICK_PER_SECOND)); 158 | if (at_obj_exec_cmd(device->client, resp, "AT+ESOCON=%d,%d,\"%s\"", sock, port, ip) < 0) 159 | { 160 | at_resp_set_info(resp, CONN_RESP_SIZE, 0, rt_tick_from_millisecond(300)); 161 | at_obj_exec_cmd(device->client, resp, "AT+ESOCL=%d", sock); 162 | result = -RT_ERROR; 163 | goto __exit; 164 | } 165 | 166 | me3616_socket_fd[device_socket] = sock; 167 | 168 | __exit: 169 | if (resp) 170 | { 171 | at_delete_resp(resp); 172 | } 173 | 174 | return result; 175 | } 176 | 177 | static int at_get_send_size(struct at_socket *socket, size_t *nacked) 178 | { 179 | int result = 0; 180 | at_response_t resp = RT_NULL; 181 | int device_socket = (int) socket->user_data; 182 | struct at_device *device = (struct at_device *) socket->device; 183 | int remain_size; 184 | 185 | resp = at_create_resp(64, 0, rt_tick_from_millisecond(300)); 186 | if (resp == RT_NULL) 187 | { 188 | LOG_E("no memory for resp create.", device->name); 189 | return -RT_ENOMEM; 190 | } 191 | 192 | if (at_obj_exec_cmd(device->client, resp, "AT+ESOTCPBUF=%d", me3616_socket_fd[device_socket]) < 0) 193 | { 194 | result = -RT_ERROR; 195 | goto __exit; 196 | } 197 | 198 | if (at_resp_parse_line_args_by_kw(resp, "+ESOTCPBUF=", "+ESOTCPBUF=%d", &remain_size) <= 0) 199 | { 200 | result = -RT_ERROR; 201 | goto __exit; 202 | } 203 | 204 | *nacked = 4096 - remain_size; 205 | 206 | __exit: 207 | if (resp) 208 | { 209 | at_delete_resp(resp); 210 | } 211 | 212 | return result; 213 | } 214 | 215 | static int at_wait_send_finish(struct at_socket *socket, rt_tick_t timeout) 216 | { 217 | rt_tick_t last_time = rt_tick_get(); 218 | size_t nacked = 0xFFFF; 219 | 220 | while (rt_tick_get() - last_time <= timeout) 221 | { 222 | at_get_send_size(socket, &nacked); 223 | if (nacked == 0) 224 | { 225 | return RT_EOK; 226 | } 227 | rt_thread_mdelay(50); 228 | } 229 | 230 | return -RT_ETIMEOUT; 231 | } 232 | 233 | /** 234 | * send data to server or client by AT commands. 235 | * 236 | * @param socket current socket 237 | * @param buff send buffer 238 | * @param bfsz send buffer size 239 | * @param type connect socket type(tcp, udp) 240 | * 241 | * @return >=0: the size of send success 242 | * -1: send AT commands error or send data error 243 | * -2: waited socket event timeout 244 | * -5: no memory 245 | */ 246 | static int me3616_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type) 247 | { 248 | #define SEND_RESP_SIZE 128 249 | 250 | int result = 0; 251 | size_t cur_pkt_size = 0, sent_size = 0; 252 | at_response_t resp = RT_NULL; 253 | int device_socket = (int) socket->user_data; 254 | struct at_device *device = (struct at_device *) socket->device; 255 | rt_mutex_t lock = device->client->lock; 256 | 257 | RT_ASSERT(buff); 258 | 259 | resp = at_create_resp(SEND_RESP_SIZE, 2, RT_TICK_PER_SECOND/2); 260 | if (resp == RT_NULL) 261 | { 262 | LOG_E("no memory for resp create."); 263 | return -RT_ENOMEM; 264 | } 265 | 266 | rt_mutex_take(lock, RT_WAITING_FOREVER); 267 | 268 | while (sent_size < bfsz) 269 | { 270 | if (bfsz - sent_size < ME3616_MODULE_SEND_MAX_SIZE) 271 | { 272 | cur_pkt_size = bfsz - sent_size; 273 | } 274 | else 275 | { 276 | cur_pkt_size = ME3616_MODULE_SEND_MAX_SIZE; 277 | } 278 | 279 | at_resp_set_info(resp, SEND_RESP_SIZE, 2, RT_TICK_PER_SECOND/2); 280 | if (at_obj_exec_cmd(device->client, resp, "AT+ESOSENDRAW=%d,%d", me3616_socket_fd[device_socket], (int)cur_pkt_size) < 0) 281 | { 282 | result = -RT_ERROR; 283 | goto __exit; 284 | } 285 | 286 | if (at_resp_get_line_by_kw(resp, "CONNECT") == RT_NULL) 287 | { 288 | result = -RT_ERROR; 289 | goto __exit; 290 | } 291 | 292 | rt_thread_mdelay(5);//delay at least 4 ms 293 | 294 | /* send the real data to server or client */ 295 | result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size); 296 | if (result == 0) 297 | { 298 | result = -RT_ERROR; 299 | goto __exit; 300 | } 301 | 302 | /* wait respone "NO CARRIER ... OK " */ 303 | at_resp_set_info(resp, SEND_RESP_SIZE, 0, (2*RT_TICK_PER_SECOND)); 304 | if (at_obj_exec_cmd(device->client, resp, "") < 0) 305 | { 306 | result = -RT_ERROR; 307 | goto __exit; 308 | } 309 | 310 | if (type == AT_SOCKET_TCP) 311 | { 312 | at_wait_send_finish(socket, (5*RT_TICK_PER_SECOND)); 313 | } 314 | else 315 | { 316 | rt_thread_mdelay(10);//delay at least 10 ms 317 | } 318 | 319 | sent_size += cur_pkt_size; 320 | } 321 | 322 | __exit: 323 | 324 | rt_mutex_release(lock); 325 | 326 | if (resp) 327 | { 328 | at_delete_resp(resp); 329 | } 330 | 331 | return result > 0 ? sent_size : result; 332 | } 333 | 334 | /** 335 | * domain resolve by AT commands. 336 | * 337 | * @param name domain name 338 | * @param ip parsed IP address, it's length must be 16 339 | * 340 | * @return 0: domain resolve success 341 | * -1: send AT commands error or response error 342 | * -2: wait socket event timeout 343 | * -5: no memory 344 | */ 345 | static int me3616_domain_resolve(const char *name, char ip[16]) 346 | { 347 | int result; 348 | at_response_t resp = RT_NULL; 349 | struct at_device *device = RT_NULL; 350 | 351 | RT_ASSERT(name); 352 | RT_ASSERT(ip); 353 | 354 | device = at_device_get_first_initialized(); 355 | if (device == RT_NULL) 356 | { 357 | LOG_E("get first init device failed."); 358 | return -RT_ERROR; 359 | } 360 | 361 | resp = at_create_resp(128, 0, (15 * RT_TICK_PER_SECOND)); 362 | if (!resp) 363 | { 364 | LOG_E("no memory for resp create."); 365 | return -RT_ENOMEM; 366 | } 367 | 368 | result = at_obj_exec_cmd(device->client, resp, "AT+EDNS=\"%s\"", name); 369 | if (result != RT_EOK) 370 | { 371 | LOG_E("%s device \"AT+EDNS=\"%s\"\" cmd error.", device->name, name); 372 | goto __exit; 373 | } 374 | 375 | if (at_resp_parse_line_args_by_kw(resp, "IPV4:", "IPV4:%s\r", ip) <= 0) 376 | { 377 | LOG_E("%s device prase \"AT+EDNS=\"%s\"\" cmd error.", device->name, name); 378 | result = -RT_ERROR; 379 | goto __exit; 380 | } 381 | 382 | ip[15] = 0; 383 | if (rt_strlen(ip) < 8) 384 | { 385 | result = -RT_ERROR; 386 | } 387 | else 388 | { 389 | result = RT_EOK; 390 | } 391 | 392 | __exit: 393 | if (resp) 394 | { 395 | at_delete_resp(resp); 396 | } 397 | 398 | return result; 399 | } 400 | 401 | /** 402 | * set AT socket event notice callback 403 | * 404 | * @param event notice event 405 | * @param cb notice callback 406 | */ 407 | static void me3616_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) 408 | { 409 | if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])) 410 | { 411 | at_evt_cb_set[event] = cb; 412 | } 413 | } 414 | 415 | static void urc_close_func(struct at_client *client, const char *data, rt_size_t size) 416 | { 417 | int sock = -1; 418 | int err_code = 0; 419 | int device_socket = 0; 420 | struct at_socket *socket = RT_NULL; 421 | struct at_device *device = RT_NULL; 422 | char *client_name = client->device->parent.name; 423 | 424 | RT_ASSERT(data && size); 425 | 426 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 427 | if (device == RT_NULL) 428 | { 429 | LOG_E("get device(%s) failed.", client_name); 430 | return; 431 | } 432 | 433 | rt_sscanf(data, "+ESOERR=%d,%d", &sock, &err_code); 434 | 435 | device_socket = me3616_get_socket_idx(sock); 436 | if (device_socket < 0 || err_code < 0 || err_code > 4) 437 | { 438 | return; 439 | } 440 | 441 | /* get at socket object by device socket descriptor */ 442 | socket = &(device->sockets[device_socket]); 443 | 444 | /* notice the socket is disconnect by remote */ 445 | if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED]) 446 | { 447 | at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0); 448 | } 449 | } 450 | 451 | static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size) 452 | { 453 | int sock = -1; 454 | int device_socket = 0; 455 | rt_int32_t timeout; 456 | rt_size_t bfsz = 0, temp_size = 0; 457 | char *recv_buf = RT_NULL, temp[8] = {0}; 458 | struct at_socket *socket = RT_NULL; 459 | struct at_device *device = RT_NULL; 460 | char *client_name = client->device->parent.name; 461 | 462 | RT_ASSERT(data && size); 463 | 464 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 465 | if (device == RT_NULL) 466 | { 467 | LOG_E("get device(%s) failed.", client_name); 468 | return; 469 | } 470 | 471 | rt_sscanf(data, "+ESONMI=%d,", &sock); 472 | device_socket = me3616_get_socket_idx(sock); 473 | if (device_socket < 0) 474 | { 475 | return; 476 | } 477 | 478 | while(temp_size < sizeof(temp)) 479 | { 480 | at_client_obj_recv(client, temp+temp_size, 1, 10); 481 | if ( *(temp+temp_size) == ',') 482 | { 483 | *(temp+temp_size) = 0; 484 | break; 485 | } 486 | temp_size++; 487 | } 488 | if (temp_size == sizeof(temp)) 489 | { 490 | return; 491 | } 492 | 493 | rt_sscanf(temp, "%d", (int *)&bfsz); 494 | if(bfsz == 0) 495 | { 496 | return; 497 | } 498 | 499 | timeout = bfsz > 10 ? bfsz : 10; 500 | 501 | recv_buf = (char *) rt_calloc(1, bfsz); 502 | if (recv_buf == RT_NULL) 503 | { 504 | LOG_E("no memory for URC receive buffer(%d).", bfsz); 505 | /* read and clean the coming data */ 506 | temp_size = 0; 507 | while (temp_size < bfsz) 508 | { 509 | if (bfsz - temp_size > sizeof(temp)) 510 | { 511 | at_client_obj_recv(client, temp, sizeof(temp), timeout); 512 | } 513 | else 514 | { 515 | at_client_obj_recv(client, temp, bfsz - temp_size, timeout); 516 | } 517 | temp_size += sizeof(temp); 518 | } 519 | return; 520 | } 521 | 522 | if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz) 523 | { 524 | LOG_E("%s device receive size(%d) data failed.", device->name, bfsz); 525 | rt_free(recv_buf); 526 | return; 527 | } 528 | 529 | /* read end "\r\n" */ 530 | at_client_obj_recv(client, temp, 2, 5); 531 | 532 | /* get at socket object by device socket descriptor */ 533 | socket = &(device->sockets[device_socket]); 534 | 535 | /* notice the receive buffer and buffer size */ 536 | if (at_evt_cb_set[AT_SOCKET_EVT_RECV]) 537 | { 538 | at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); 539 | } 540 | } 541 | 542 | static const struct at_urc urc_table[] = 543 | { 544 | {"+ESOERR=", "\r\n", urc_close_func}, 545 | {"+ESONMI=", ",", urc_recv_func}, 546 | }; 547 | 548 | static const struct at_socket_ops me3616_socket_ops = 549 | { 550 | me3616_socket_connect, 551 | me3616_socket_close, 552 | me3616_socket_send, 553 | me3616_domain_resolve, 554 | me3616_socket_set_event_cb, 555 | #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300 556 | RT_NULL, 557 | #endif 558 | }; 559 | 560 | int me3616_socket_init(struct at_device *device) 561 | { 562 | RT_ASSERT(device); 563 | 564 | rt_memset(me3616_socket_fd, -1, sizeof(me3616_socket_fd)); 565 | 566 | /* register URC data execution function */ 567 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 568 | 569 | return RT_EOK; 570 | } 571 | 572 | int me3616_socket_class_register(struct at_device_class *class) 573 | { 574 | RT_ASSERT(class); 575 | 576 | class->socket_num = AT_DEVICE_ME3616_SOCKETS_NUM; 577 | class->socket_ops = &me3616_socket_ops; 578 | 579 | return RT_EOK; 580 | } 581 | 582 | #endif /* AT_DEVICE_USING_ME3616 && AT_USING_SOCKET */ 583 | 584 | -------------------------------------------------------------------------------- /class/ml305/at_device_ml305.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2022-12-16 Jonas first version 9 | */ 10 | 11 | #ifndef __ML305_DEVICE_H__ 12 | #define __ML305_DEVICE_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | #define ML305_AT_RESP_TIMEOUT RT_TICK_PER_SECOND 23 | 24 | /* The maximum number of sockets supported by the ml305 device */ 25 | #define AT_DEVICE_ML305_SOCKETS_NUM 6 26 | 27 | struct at_device_ml305 28 | { 29 | char *device_name; 30 | char *client_name; 31 | 32 | int power_pin; 33 | int power_status_pin; 34 | size_t recv_buff_size; 35 | struct at_device device; 36 | 37 | void *user_data; 38 | }; 39 | 40 | #ifdef AT_USING_SOCKET 41 | 42 | /* ml305 device socket initialize */ 43 | int ml305_socket_init(struct at_device *device); 44 | 45 | /* ml305 device class socket register */ 46 | int ml305_socket_class_register(struct at_device_class *class); 47 | 48 | #endif /* AT_USING_SOCKET */ 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif /* __AT_DEVICE_ML305_H__*/ 55 | -------------------------------------------------------------------------------- /class/ml307/at_device_ml307.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2022-12-16 Jonas first version 9 | */ 10 | 11 | #ifndef __ML307_DEVICE_H__ 12 | #define __ML307_DEVICE_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | #define ML307_AT_RESP_TIMEOUT RT_TICK_PER_SECOND 23 | 24 | /* The maximum number of sockets supported by the ml307 device */ 25 | #define AT_DEVICE_ML307_SOCKETS_NUM 6 26 | 27 | struct at_device_ml307 28 | { 29 | char *device_name; 30 | char *client_name; 31 | 32 | int power_pin; 33 | int power_status_pin; 34 | size_t recv_buff_size; 35 | struct at_device device; 36 | 37 | void *user_data; 38 | }; 39 | 40 | #ifdef AT_USING_SOCKET 41 | 42 | /* ml307 device socket initialize */ 43 | int ml307_socket_init(struct at_device *device); 44 | 45 | /* ml307 device class socket register */ 46 | int ml307_socket_class_register(struct at_device_class *class); 47 | 48 | #endif /* AT_USING_SOCKET */ 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif /* __AT_DEVICE_ML307_H__*/ 55 | -------------------------------------------------------------------------------- /class/mw31/at_device_mw31.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-06-23 flybreak first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_MW31_H__ 12 | #define __AT_DEVICE_MW31_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the mw31 device */ 23 | #define AT_DEVICE_MW31_SOCKETS_NUM 5 24 | 25 | struct at_device_mw31 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | char *wifi_ssid; 31 | char *wifi_password; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* mw31 device socket initialize */ 41 | int mw31_socket_init(struct at_device *device); 42 | 43 | /* mw31 device class socket register */ 44 | int mw31_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_MW31_H__ */ 53 | -------------------------------------------------------------------------------- /class/mw31/at_socket_mw31.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-06-23 flybreak first version 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define LOG_TAG "at.skt.mw31" 17 | #include 18 | 19 | #if defined(AT_DEVICE_USING_MW31) && defined(AT_USING_SOCKET) 20 | 21 | #define MW31_MODULE_SEND_MAX_SIZE 1024 22 | /* set real event by current socket and current state */ 23 | #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event)) 24 | 25 | /* AT socket event type */ 26 | #define MW31_EVENT_CONN_OK (1L << 0) 27 | #define MW31_EVENT_SEND_OK (1L << 1) 28 | #define MW31_EVENT_RECV_OK (1L << 2) 29 | #define MW31_EVNET_CLOSE_OK (1L << 3) 30 | #define MW31_EVENT_CONN_FAIL (1L << 4) 31 | #define MW31_EVENT_SEND_FAIL (1L << 5) 32 | 33 | static at_evt_cb_t at_evt_cb_set[] = 34 | { 35 | [AT_SOCKET_EVT_RECV] = NULL, 36 | [AT_SOCKET_EVT_CLOSED] = NULL, 37 | }; 38 | 39 | 40 | /** 41 | * close socket by AT commands. 42 | * 43 | * @param current socket 44 | * 45 | * @return 0: close socket success 46 | * -1: send AT commands error 47 | * -2: wait socket event timeout 48 | * -5: no memory 49 | */ 50 | static int mw31_socket_close(struct at_socket *socket) 51 | { 52 | int result = RT_EOK; 53 | at_response_t resp = RT_NULL; 54 | int device_socket = (int) socket->user_data; 55 | struct at_device *device = (struct at_device *) socket->device; 56 | char type[15] = {0}, status[15] = {0}; 57 | 58 | resp = at_create_resp(64, 0, rt_tick_from_millisecond(300)); 59 | if (resp == RT_NULL) 60 | { 61 | LOG_E("no memory for resp create."); 62 | return -RT_ENOMEM; 63 | } 64 | 65 | at_obj_exec_cmd(device->client, resp, "AT+CIPSTATUS=%d", device_socket); 66 | 67 | if (at_resp_parse_line_args_by_kw(resp, "+CIPSTATU:", "+CIPSTATU:%[^,],%s", type, status) > 0) 68 | { 69 | LOG_D("%s\n%s\n", type, status); 70 | } 71 | 72 | if (status[0] == 'd' || status[2] == 'o') 73 | { 74 | goto __exit; 75 | } 76 | 77 | result = at_obj_exec_cmd(device->client, resp, "AT+CIPSTOP=%d", device_socket); 78 | 79 | __exit: 80 | if (resp) 81 | { 82 | at_delete_resp(resp); 83 | } 84 | 85 | return result; 86 | } 87 | 88 | /** 89 | * create TCP/UDP client or server connect by AT commands. 90 | * 91 | * @param socket current socket 92 | * @param ip server or client IP address 93 | * @param port server or client port 94 | * @param type connect socket type(tcp, udp) 95 | * @param is_client connection is client 96 | * 97 | * @return 0: connect success 98 | * -1: connect failed, send commands error or type error 99 | * -2: wait socket event timeout 100 | * -5: no memory 101 | */ 102 | static int mw31_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client) 103 | { 104 | int result = RT_EOK; 105 | rt_bool_t retryed = RT_FALSE; 106 | at_response_t resp = RT_NULL; 107 | int device_socket = (int) socket->user_data; 108 | struct at_device *device = (struct at_device *) socket->device; 109 | 110 | RT_ASSERT(ip); 111 | RT_ASSERT(port >= 0); 112 | 113 | resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND); 114 | if (resp == RT_NULL) 115 | { 116 | LOG_E("no memory for resp create."); 117 | return -RT_ENOMEM; 118 | } 119 | 120 | __retry: 121 | if (is_client) 122 | { 123 | switch (type) 124 | { 125 | case AT_SOCKET_TCP: 126 | /* send AT commands to connect TCP server */ 127 | if (at_obj_exec_cmd(device->client, resp, 128 | "AT+CIPSTART=%d,tcp_client,%s,%d,%d", device_socket, ip, port, device_socket) < 0) 129 | { 130 | result = -RT_ERROR; 131 | } 132 | break; 133 | 134 | case AT_SOCKET_UDP: 135 | if (at_obj_exec_cmd(device->client, resp, 136 | "AT+CIPSTART=%d,udp_unicast,%s,%d,%d", device_socket, ip, port, device_socket) < 0) 137 | { 138 | result = -RT_ERROR; 139 | } 140 | break; 141 | 142 | default: 143 | LOG_E("not supported connect type %d.", type); 144 | result = -RT_ERROR; 145 | goto __exit; 146 | } 147 | } 148 | 149 | if (result != RT_EOK && retryed == RT_FALSE) 150 | { 151 | LOG_D("%s device socket (%d) connect failed, the socket was not be closed and now will connect retry.", 152 | device->name, device_socket); 153 | if (mw31_socket_close(socket) < 0) 154 | { 155 | goto __exit; 156 | } 157 | retryed = RT_TRUE; 158 | result = RT_EOK; 159 | goto __retry; 160 | } 161 | 162 | __exit: 163 | if (resp) 164 | { 165 | at_delete_resp(resp); 166 | } 167 | 168 | return result; 169 | } 170 | 171 | /** 172 | * send data to server or client by AT commands. 173 | * 174 | * @param socket current socket 175 | * @param buff send buffer 176 | * @param bfsz send buffer size 177 | * @param type connect socket type(tcp, udp) 178 | * 179 | * @return >=0: the size of send success 180 | * -1: send AT commands error or send data error 181 | * -2: waited socket event timeout 182 | * -5: no memory 183 | */ 184 | static int mw31_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type) 185 | { 186 | int result = RT_EOK; 187 | size_t cur_pkt_size = 0, sent_size = 0; 188 | at_response_t resp = RT_NULL; 189 | int device_socket = (int) socket->user_data; 190 | struct at_device *device = (struct at_device *) socket->device; 191 | struct at_device_mw31 *mw31 = (struct at_device_mw31 *) device->user_data; 192 | rt_mutex_t lock = device->client->lock; 193 | char send_buf[20] = {0}; 194 | 195 | RT_ASSERT(buff); 196 | RT_ASSERT(bfsz > 0); 197 | 198 | resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND); 199 | if (resp == RT_NULL) 200 | { 201 | LOG_E("no memory for resp create."); 202 | return -RT_ENOMEM; 203 | } 204 | 205 | rt_mutex_take(lock, RT_WAITING_FOREVER); 206 | 207 | /* set current socket for send URC event */ 208 | mw31->user_data = (void *) device_socket; 209 | 210 | /* set AT client end sign to deal with '>' sign */ 211 | at_obj_set_end_sign(device->client, '>'); 212 | 213 | while (sent_size < bfsz) 214 | { 215 | if (bfsz - sent_size < MW31_MODULE_SEND_MAX_SIZE) 216 | { 217 | cur_pkt_size = bfsz - sent_size; 218 | } 219 | else 220 | { 221 | cur_pkt_size = MW31_MODULE_SEND_MAX_SIZE; 222 | } 223 | 224 | rt_sprintf(send_buf, "AT+CIPSEND=%d,%d", device_socket, cur_pkt_size); 225 | /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line */ 226 | at_client_obj_send(device->client, send_buf, strlen(send_buf)); 227 | 228 | at_client_obj_send(device->client, "\r", 1); 229 | 230 | /* send the real data to server or client */ 231 | result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size); 232 | if (result == 0) 233 | { 234 | result = -RT_ERROR; 235 | goto __exit; 236 | } 237 | 238 | sent_size += cur_pkt_size; 239 | } 240 | 241 | __exit: 242 | /* reset the end sign for data */ 243 | at_obj_set_end_sign(device->client, 0); 244 | 245 | rt_mutex_release(lock); 246 | 247 | if (resp) 248 | { 249 | at_delete_resp(resp); 250 | } 251 | 252 | return result > 0 ? sent_size : result; 253 | } 254 | 255 | /** 256 | * domain resolve by AT commands. 257 | * 258 | * @param name domain name 259 | * @param ip parsed IP address, it's length must be 16 260 | * 261 | * @return 0: domain resolve success 262 | * -2: wait socket event timeout 263 | * -5: no memory 264 | */ 265 | static int mw31_domain_resolve(const char *name, char ip[16]) 266 | { 267 | #define RESOLVE_RETRY 5 268 | 269 | int i, result = RT_EOK; 270 | rt_uint8_t recv_ip_num = 0; 271 | char recv_ip[16] = { 0 }; 272 | at_response_t resp = RT_NULL; 273 | struct at_device *device = RT_NULL; 274 | 275 | RT_ASSERT(name); 276 | RT_ASSERT(ip); 277 | 278 | device = at_device_get_first_initialized(); 279 | if (device == RT_NULL) 280 | { 281 | LOG_E("get first init device failed."); 282 | return -RT_ERROR; 283 | } 284 | 285 | resp = at_create_resp(128, 0, 20 * RT_TICK_PER_SECOND); 286 | if (resp == RT_NULL) 287 | { 288 | LOG_E("no memory for resp create."); 289 | return -RT_ENOMEM; 290 | } 291 | 292 | for (i = 0; i < RESOLVE_RETRY; i++) 293 | { 294 | if (at_obj_exec_cmd(device->client, resp, "AT+CIPDOMAIN=%s", name) < 0) 295 | { 296 | result = -RT_ERROR; 297 | goto __exit; 298 | } 299 | 300 | /* parse the third line of response data, get the IP address */ 301 | if (at_resp_parse_line_args_by_kw(resp, "+CIPDOMAIN:", "+CIPDOMAIN:%d", &recv_ip_num) < 0 || 302 | recv_ip_num == 0 || 303 | at_resp_parse_line_args(resp, 3, "%s", recv_ip) < 0) 304 | { 305 | rt_thread_mdelay(100); 306 | /* resolve failed, maybe receive an URC CRLF */ 307 | continue; 308 | } 309 | 310 | if (rt_strlen(recv_ip) < 8) 311 | { 312 | rt_thread_mdelay(100); 313 | /* resolve failed, maybe receive an URC CRLF */ 314 | continue; 315 | } 316 | else 317 | { 318 | rt_strncpy(ip, recv_ip, 15); 319 | ip[15] = '\0'; 320 | break; 321 | } 322 | } 323 | 324 | __exit: 325 | if (resp) 326 | { 327 | at_delete_resp(resp); 328 | } 329 | 330 | return result; 331 | 332 | } 333 | 334 | /** 335 | * set AT socket event notice callback 336 | * 337 | * @param event notice event 338 | * @param cb notice callback 339 | */ 340 | static void mw31_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) 341 | { 342 | if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])) 343 | { 344 | at_evt_cb_set[event] = cb; 345 | } 346 | } 347 | 348 | static const struct at_socket_ops mw31_socket_ops = 349 | { 350 | mw31_socket_connect, 351 | mw31_socket_close, 352 | mw31_socket_send, 353 | mw31_domain_resolve, 354 | mw31_socket_set_event_cb, 355 | #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300 356 | RT_NULL, 357 | #endif 358 | }; 359 | 360 | static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size) 361 | { 362 | int device_socket = 0; 363 | rt_int32_t timeout = 0; 364 | rt_size_t bfsz = 0, temp_size = 0; 365 | char *recv_buf = RT_NULL, temp[8] = {0}; 366 | struct at_socket *socket = RT_NULL; 367 | struct at_device *device = RT_NULL; 368 | char *client_name = client->device->parent.name; 369 | rt_uint8_t i; 370 | 371 | RT_ASSERT(data && size); 372 | 373 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 374 | if (device == RT_NULL) 375 | { 376 | LOG_E("get device(%s) failed.", client_name); 377 | return; 378 | } 379 | 380 | at_client_obj_recv(client, temp, 2, 1000); 381 | /* get the at deveice socket and receive buffer size by receive data */ 382 | rt_sscanf(temp, "%d,", &device_socket); 383 | temp[0] = 0; 384 | temp[1] = 0; 385 | for (i = 0; i < 6; i++) 386 | { 387 | if (i > 0 && temp[i - 1] == ',') 388 | { 389 | break; 390 | } 391 | at_client_obj_recv(client, &temp[i], 1, 1000); 392 | } 393 | rt_sscanf(temp, "%ld,", &bfsz); 394 | 395 | LOG_D("socket:%d, size:%ld\n", device_socket, bfsz); 396 | /* set receive timeout by receive buffer length, not less than 10 ms */ 397 | timeout = bfsz > 10 ? bfsz : 10; 398 | 399 | if (device_socket < 0 || bfsz == 0) 400 | return; 401 | 402 | recv_buf = (char *) rt_calloc(1, bfsz); 403 | if (recv_buf == RT_NULL) 404 | { 405 | LOG_E("no memory for receive buffer(%d).", bfsz); 406 | /* read and clean the coming data */ 407 | while (temp_size < bfsz) 408 | { 409 | if (bfsz - temp_size > sizeof(temp)) 410 | { 411 | at_client_obj_recv(client, temp, sizeof(temp), timeout); 412 | } 413 | else 414 | { 415 | at_client_obj_recv(client, temp, bfsz - temp_size, timeout); 416 | } 417 | temp_size += sizeof(temp); 418 | } 419 | return; 420 | } 421 | 422 | /* sync receive data */ 423 | if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz) 424 | { 425 | LOG_E("%s device receive size(%d) data failed.", device->name, bfsz); 426 | rt_free(recv_buf); 427 | return; 428 | } 429 | 430 | /* get at socket object by device socket descriptor */ 431 | socket = &(device->sockets[device_socket]); 432 | 433 | /* notice the receive buffer and buffer size */ 434 | if (at_evt_cb_set[AT_SOCKET_EVT_RECV]) 435 | { 436 | at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); 437 | } 438 | } 439 | 440 | static const struct at_urc urc_table[] = 441 | { 442 | {"+CIPEVENT:SOCKET", ",", urc_recv_func}, 443 | {":SOCKET", ",", urc_recv_func}, 444 | }; 445 | 446 | int mw31_socket_init(struct at_device *device) 447 | { 448 | RT_ASSERT(device); 449 | 450 | /* register URC data execution function */ 451 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 452 | 453 | return RT_EOK; 454 | } 455 | 456 | int mw31_socket_class_register(struct at_device_class *class) 457 | { 458 | RT_ASSERT(class); 459 | 460 | class->socket_num = AT_DEVICE_MW31_SOCKETS_NUM; 461 | class->socket_ops = &mw31_socket_ops; 462 | 463 | return RT_EOK; 464 | } 465 | 466 | #endif /* AT_DEVICE_USING_MW31 && AT_USING_SOCKET */ 467 | -------------------------------------------------------------------------------- /class/n21/Kconfig: -------------------------------------------------------------------------------- 1 | 2 | # N21 AT device configuration 3 | menuconfig AT_DEVICE_USING_N21 4 | bool "neoway N21" 5 | default n 6 | 7 | if AT_DEVICE_USING_N21 8 | 9 | config AT_DEVICE_N21_INIT_ASYN 10 | bool "Enable initialize by thread" 11 | default n 12 | 13 | config AT_DEVICE_N21_SAMPLE 14 | bool "Enable sample" 15 | default y 16 | 17 | if AT_DEVICE_N21_SAMPLE 18 | 19 | config N21_SAMPLE_POWER_PIN 20 | int "Power pin" 21 | default -1 22 | 23 | config N21_SAMPLE_STATUS_PIN 24 | int "Power status pin" 25 | default -1 26 | 27 | config N21_SAMPLE_CLIENT_NAME 28 | string "AT client device name" 29 | default "uart3" 30 | 31 | config N21_SAMPLE_RECV_BUFF_LEN 32 | int "The maximum length of receive line buffer" 33 | default 512 34 | 35 | endif 36 | 37 | endif 38 | -------------------------------------------------------------------------------- /class/n21/at_device_n21.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-22 shuobatian first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_N21_H__ 12 | #define __AT_DEVICE_N21_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the N21 device */ 23 | #define AT_DEVICE_N21_SOCKETS_NUM 4 24 | 25 | struct at_device_n21 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* n21 device socket initialize */ 41 | int n21_socket_init(struct at_device *device); 42 | 43 | /* n21 device class socket register */ 44 | int n21_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_N21_H__ */ 53 | -------------------------------------------------------------------------------- /class/n58/Kconfig: -------------------------------------------------------------------------------- 1 | 2 | # N58 AT device configuration 3 | menuconfig AT_DEVICE_USING_N58 4 | bool "neoway N58" 5 | default n 6 | 7 | if AT_DEVICE_USING_N58 8 | 9 | config AT_DEVICE_N58_INIT_ASYN 10 | bool "Enable initialize by thread" 11 | default n 12 | 13 | config AT_DEVICE_N58_SAMPLE 14 | bool "Enable sample" 15 | default y 16 | 17 | if AT_DEVICE_N58_SAMPLE 18 | 19 | config N58_SAMPLE_POWER_PIN 20 | int "Power pin" 21 | default -1 22 | 23 | config N58_SAMPLE_STATUS_PIN 24 | int "Power status pin" 25 | default -1 26 | 27 | config N58_SAMPLE_CLIENT_NAME 28 | string "AT client device name" 29 | default "uart3" 30 | 31 | config N58_SAMPLE_RECV_BUFF_LEN 32 | int "The maximum length of receive line buffer" 33 | default 512 34 | 35 | endif 36 | 37 | endif 38 | -------------------------------------------------------------------------------- /class/n58/at_device_n58.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-22 shuobatian first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_N58_H__ 12 | #define __AT_DEVICE_N58_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the N58 device */ 23 | #define AT_DEVICE_N58_SOCKETS_NUM 4 24 | 25 | struct at_device_n58 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* n58 device socket initialize */ 41 | int n58_socket_init(struct at_device *device); 42 | 43 | /* n58 device class socket register */ 44 | int n58_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_N58_H__ */ 53 | -------------------------------------------------------------------------------- /class/n720/at_device_n720.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-10-27 qiyongzhong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_EC200X_H__ 12 | #define __AT_DEVICE_EC200X_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the ec200x device */ 23 | #define AT_DEVICE_N720_SOCKETS_NUM 6 24 | 25 | struct at_device_n720 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | int wakeup_pin; 33 | size_t recv_line_num; 34 | void (*power_ctrl)(int is_on); 35 | struct at_device device; 36 | 37 | void *socket_data; 38 | void *user_data; 39 | 40 | rt_bool_t power_status; 41 | rt_bool_t sleep_status; 42 | }; 43 | 44 | #ifdef AT_USING_SOCKET 45 | 46 | /* n720 device socket initialize */ 47 | int n720_socket_init(struct at_device *device); 48 | 49 | /* n720 device class socket register */ 50 | int n720_socket_class_register(struct at_device_class *class); 51 | 52 | #endif /* AT_USING_SOCKET */ 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* __AT_DEVICE_EC200X_H__ */ 59 | 60 | -------------------------------------------------------------------------------- /class/n720/at_socket_n720.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-10-28 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define LOG_TAG "at.skt.n720" 17 | #include 18 | 19 | #if defined(AT_DEVICE_USING_N720) && defined(AT_USING_SOCKET) 20 | 21 | #define N720_MODULE_SEND_MAX_SIZE 2000 22 | 23 | /* set real event by current socket and current state */ 24 | #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event)) 25 | 26 | /* AT socket event type */ 27 | #define N720_EVENT_CONN_OK (1L << 0) 28 | #define N720_EVENT_SEND_OK (1L << 1) 29 | #define N720_EVENT_RECV_OK (1L << 2) 30 | #define N720_EVNET_CLOSE_OK (1L << 3) 31 | #define N720_EVENT_CONN_FAIL (1L << 4) 32 | #define N720_EVENT_SEND_FAIL (1L << 5) 33 | #define N720_EVENT_DOMAIN_OK (1L << 6) 34 | 35 | static at_evt_cb_t at_evt_cb_set[] = { 36 | [AT_SOCKET_EVT_RECV] = NULL, 37 | [AT_SOCKET_EVT_CLOSED] = NULL, 38 | }; 39 | 40 | /** 41 | * close socket by AT commands. 42 | * 43 | * @param current socket 44 | * 45 | * @return 0: close socket success 46 | * -1: send AT commands error 47 | * -2: wait socket event timeout 48 | * -5: no memory 49 | */ 50 | static int n720_socket_close(struct at_socket *socket) 51 | { 52 | int result = RT_EOK; 53 | at_response_t resp = RT_NULL; 54 | int device_socket = (int) socket->user_data; 55 | struct at_device *device = (struct at_device *) socket->device; 56 | 57 | resp = at_create_resp(64, 0, rt_tick_from_millisecond(300)); 58 | if (resp == RT_NULL) 59 | { 60 | LOG_E("no memory for resp create."); 61 | return -RT_ENOMEM; 62 | } 63 | 64 | result = at_obj_exec_cmd(device->client, resp, "AT$MYNETCLOSE=%d", device_socket); 65 | 66 | at_delete_resp(resp); 67 | 68 | return result; 69 | } 70 | 71 | /** 72 | * create TCP/UDP client or server connect by AT commands. 73 | * 74 | * @param socket current socket 75 | * @param ip server or client IP address 76 | * @param port server or client port 77 | * @param type connect socket type(tcp, udp) 78 | * @param is_client connection is client 79 | * 80 | * @return 0: connect success 81 | * -1: connect failed, send commands error or type error 82 | * -2: wait socket event timeout 83 | * -5: no memory 84 | */ 85 | static int n720_socket_connect(struct at_socket *socket, char *ip, int32_t port, 86 | enum at_socket_type type, rt_bool_t is_client) 87 | { 88 | int type_val = 0; 89 | at_response_t resp = RT_NULL; 90 | int device_socket = (int) socket->user_data; 91 | struct at_device *device = (struct at_device *) socket->device; 92 | 93 | RT_ASSERT(ip); 94 | RT_ASSERT(port >= 0); 95 | 96 | if ( ! is_client) 97 | { 98 | return -RT_ERROR; 99 | } 100 | 101 | switch(type) 102 | { 103 | case AT_SOCKET_TCP: 104 | type_val = 0; 105 | break; 106 | case AT_SOCKET_UDP: 107 | type_val = 2; 108 | break; 109 | default: 110 | LOG_E("%s device socket(%d) connect type error.", device->name, device_socket); 111 | return -RT_ERROR; 112 | } 113 | 114 | resp = at_create_resp(128, 0, rt_tick_from_millisecond(15*1000)); 115 | if (resp == RT_NULL) 116 | { 117 | LOG_E("no memory for resp create."); 118 | return -RT_ENOMEM; 119 | } 120 | 121 | if (at_obj_exec_cmd(device->client, resp, "AT$MYNETSRV=0,%d,%d,0,\"%s:%d\"", device_socket, type_val, ip, port) < 0) 122 | { 123 | at_delete_resp(resp); 124 | LOG_E("%s device socket(%d) config params fail.", device->name, device_socket); 125 | return -RT_ERROR; 126 | } 127 | 128 | if (at_obj_exec_cmd(device->client, resp, "AT$MYNETOPEN=%d", device_socket) < 0) 129 | { 130 | at_delete_resp(resp); 131 | LOG_E("%s device socket(%d) connect failed.", device->name, device_socket); 132 | return -RT_ERROR; 133 | } 134 | 135 | at_delete_resp(resp); 136 | return RT_EOK; 137 | } 138 | 139 | static int at_get_send_size(struct at_socket *socket, size_t *nacked) 140 | { 141 | int result = 0; 142 | at_response_t resp = RT_NULL; 143 | int device_socket = (int) socket->user_data; 144 | struct at_device *device = (struct at_device *) socket->device; 145 | 146 | resp = at_create_resp(128, 0, rt_tick_from_millisecond(300)); 147 | if (resp == RT_NULL) 148 | { 149 | LOG_E("no memory for resp create.", device->name); 150 | return -RT_ENOMEM; 151 | } 152 | 153 | if (at_obj_exec_cmd(device->client, resp, "AT$MYNETACK=%d", device_socket) < 0) 154 | { 155 | result = -RT_ERROR; 156 | goto __exit; 157 | } 158 | 159 | if (at_resp_parse_line_args_by_kw(resp, "$MYNETACK:", "$MYNETACK:%*d,%d,%*d", nacked) <= 0) 160 | { 161 | result = -RT_ERROR; 162 | goto __exit; 163 | } 164 | 165 | __exit: 166 | if (resp) 167 | { 168 | at_delete_resp(resp); 169 | } 170 | 171 | return result; 172 | } 173 | 174 | static int at_wait_send_finish(struct at_socket *socket, size_t settings_size) 175 | { 176 | /* get the timeout by the input data size */ 177 | rt_tick_t timeout = rt_tick_from_millisecond(settings_size); 178 | rt_tick_t last_time = rt_tick_get(); 179 | size_t nacked = 0xFFFF; 180 | 181 | while (rt_tick_get() - last_time <= timeout) 182 | { 183 | at_get_send_size(socket, &nacked); 184 | if (nacked == 0) 185 | { 186 | return RT_EOK; 187 | } 188 | rt_thread_mdelay(100); 189 | } 190 | 191 | return -RT_ETIMEOUT; 192 | } 193 | 194 | /** 195 | * send data to server or client by AT commands. 196 | * 197 | * @param socket current socket 198 | * @param buff send buffer 199 | * @param bfsz send buffer size 200 | * @param type connect socket type(tcp, udp) 201 | * 202 | * @return >=0: the size of send success 203 | * -1: send AT commands error or send data error 204 | * -2: waited socket event timeout 205 | * -5: no memory 206 | */ 207 | static int n720_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type) 208 | { 209 | int result = 0; 210 | size_t cur_pkt_size = 0, sent_size = 0; 211 | at_response_t resp = RT_NULL; 212 | int device_socket = (int) socket->user_data; 213 | struct at_device *device = (struct at_device *) socket->device; 214 | struct at_device_n720 *n720 = (struct at_device_n720 *) device->user_data; 215 | rt_mutex_t lock = device->client->lock; 216 | 217 | RT_ASSERT(buff); 218 | 219 | resp = at_create_resp(128, 2, rt_tick_from_millisecond(300)); 220 | if (resp == RT_NULL) 221 | { 222 | LOG_E("no memory for resp create."); 223 | return -RT_ENOMEM; 224 | } 225 | 226 | rt_mutex_take(lock, RT_WAITING_FOREVER); 227 | 228 | /* set current socket for send URC event */ 229 | n720->user_data = (void *) device_socket; 230 | 231 | while (sent_size < bfsz) 232 | { 233 | if (bfsz - sent_size < N720_MODULE_SEND_MAX_SIZE) 234 | { 235 | cur_pkt_size = bfsz - sent_size; 236 | } 237 | else 238 | { 239 | cur_pkt_size = N720_MODULE_SEND_MAX_SIZE; 240 | } 241 | 242 | if (at_obj_exec_cmd(device->client, resp, "AT$MYNETWRITE=%d,%d", device_socket, (int)cur_pkt_size) < 0) 243 | { 244 | result = -RT_ERROR; 245 | goto __exit; 246 | } 247 | 248 | if (at_resp_get_line_by_kw(resp, "$MYNETWRITE:") == RT_NULL) 249 | { 250 | result = -RT_ERROR; 251 | goto __exit; 252 | } 253 | 254 | /* send the real data to server or client */ 255 | result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size); 256 | if (result == 0) 257 | { 258 | result = -RT_ERROR; 259 | goto __exit; 260 | } 261 | 262 | if (type == AT_SOCKET_TCP) 263 | { 264 | at_wait_send_finish(socket, cur_pkt_size); 265 | //rt_thread_mdelay(10); 266 | } 267 | 268 | sent_size += cur_pkt_size; 269 | } 270 | 271 | __exit: 272 | 273 | rt_mutex_release(lock); 274 | 275 | if (resp) 276 | { 277 | at_delete_resp(resp); 278 | } 279 | 280 | return result > 0 ? sent_size : result; 281 | } 282 | 283 | /** 284 | * domain resolve by AT commands. 285 | * 286 | * @param name domain name 287 | * @param ip parsed IP address, it's length must be 16 288 | * 289 | * @return 0: domain resolve success 290 | * -1: send AT commands error or response error 291 | * -2: wait socket event timeout 292 | * -5: no memory 293 | */ 294 | static int n720_domain_resolve(const char *name, char ip[16]) 295 | { 296 | #define RESOLVE_RETRY 3 297 | 298 | int i, result = RT_EOK; 299 | char recv_ip[20] = {0}; 300 | at_response_t resp = RT_NULL; 301 | struct at_device *device = RT_NULL; 302 | 303 | RT_ASSERT(name); 304 | RT_ASSERT(ip); 305 | 306 | device = at_device_get_first_initialized(); 307 | if (device == RT_NULL) 308 | { 309 | LOG_E("get first initialization n58 device failed."); 310 | return -RT_ERROR; 311 | } 312 | 313 | /* The maximum response time is 14 seconds, affected by network status */ 314 | resp = at_create_resp(128, 0, 15 * RT_TICK_PER_SECOND); 315 | if (resp == RT_NULL) 316 | { 317 | LOG_E("no memory for n58 device(%s) response structure.", device->name); 318 | return -RT_ENOMEM; 319 | } 320 | 321 | for (i = 0; i < RESOLVE_RETRY; i++) 322 | { 323 | if (at_obj_exec_cmd(device->client, resp, "AT+DNS=%s", name) < 0) 324 | { 325 | result = -RT_ERROR; 326 | goto __exit; 327 | } 328 | 329 | /* parse the third line of response data, get the IP address */ 330 | if (at_resp_parse_line_args_by_kw(resp, "+DNS:", "+DNS: %s", recv_ip) < 0) 331 | { 332 | rt_thread_mdelay(100); 333 | /* resolve failed, maybe receive an URC CRLF */ 334 | continue; 335 | } 336 | 337 | if (rt_strlen(recv_ip) < 8) 338 | { 339 | rt_thread_mdelay(100); 340 | /* resolve failed, maybe receive an URC CRLF */ 341 | continue; 342 | } 343 | else 344 | { 345 | rt_thread_mdelay(10); 346 | rt_strncpy(ip, recv_ip, 15); 347 | ip[15] = '\0'; 348 | break; 349 | } 350 | } 351 | 352 | __exit: 353 | if (resp) 354 | { 355 | at_delete_resp(resp); 356 | } 357 | 358 | return result; 359 | } 360 | 361 | 362 | /** 363 | * set AT socket event notice callback 364 | * 365 | * @param event notice event 366 | * @param cb notice callback 367 | */ 368 | static void n720_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) 369 | { 370 | if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])) 371 | { 372 | at_evt_cb_set[event] = cb; 373 | } 374 | } 375 | 376 | static void urc_close_func(struct at_client *client, const char *data, rt_size_t size) 377 | { 378 | int device_socket = 0; 379 | struct at_socket *socket = RT_NULL; 380 | struct at_device *device = RT_NULL; 381 | char *client_name = client->device->parent.name; 382 | 383 | RT_ASSERT(data && size); 384 | 385 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 386 | if (device == RT_NULL) 387 | { 388 | LOG_E("get device(%s) failed.", client_name); 389 | return; 390 | } 391 | 392 | rt_sscanf(data, "$MYURCCLOSE: %d", &device_socket); 393 | /* get at socket object by device socket descriptor */ 394 | socket = &(device->sockets[device_socket]); 395 | 396 | /* notice the socket is disconnect by remote */ 397 | if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED]) 398 | { 399 | at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0); 400 | } 401 | } 402 | 403 | static void send_net_read(struct at_client *client, int device_socket) 404 | { 405 | char *send_buf = (char *) rt_malloc(128); 406 | if (send_buf == RT_NULL) 407 | { 408 | return; 409 | } 410 | 411 | rt_sprintf(send_buf, "AT$MYNETREAD=%d,%d\r\n", device_socket, N720_MODULE_SEND_MAX_SIZE); 412 | at_client_obj_send(client, send_buf, strlen(send_buf)); 413 | 414 | rt_free(send_buf); 415 | } 416 | 417 | static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size) 418 | { 419 | int device_socket = 0; 420 | struct at_device *device = RT_NULL; 421 | char *client_name = client->device->parent.name; 422 | 423 | RT_ASSERT(data && size); 424 | 425 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 426 | if (device == RT_NULL) 427 | { 428 | LOG_E("get device(%s) failed.", client_name); 429 | return; 430 | } 431 | 432 | if (rt_sscanf(data, "$MYURCREAD: %d", &device_socket) <= 0) 433 | { 434 | return; 435 | } 436 | 437 | send_net_read(client, device_socket); 438 | } 439 | 440 | static void read_ack_func(struct at_client *client, const char *data, rt_size_t size) 441 | { 442 | int device_socket = 0; 443 | rt_int32_t timeout; 444 | int bfsz = 0, temp_size = 0; 445 | char *recv_buf = RT_NULL, temp[8] = {0}; 446 | struct at_socket *socket = RT_NULL; 447 | struct at_device *device = RT_NULL; 448 | char *client_name = client->device->parent.name; 449 | 450 | RT_ASSERT(data && size); 451 | 452 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 453 | if (device == RT_NULL) 454 | { 455 | LOG_E("get device(%s) failed.", client_name); 456 | return; 457 | } 458 | 459 | /* get the current socket and receive buffer size by receive data */ 460 | rt_sscanf(data, "$MYNETREAD: %d,%d", &device_socket, &bfsz); 461 | /* set receive timeout by receive buffer length, not less than 10 ms */ 462 | timeout = bfsz > 10 ? bfsz : 10; 463 | 464 | if (device_socket < 0 || bfsz == 0) 465 | { 466 | return; 467 | } 468 | 469 | recv_buf = (char *) rt_calloc(1, bfsz); 470 | if (recv_buf == RT_NULL) 471 | { 472 | LOG_E("no memory for URC receive buffer(%d).", bfsz); 473 | /* read and clean the coming data */ 474 | while (temp_size < bfsz) 475 | { 476 | if (bfsz - temp_size > sizeof(temp)) 477 | { 478 | at_client_obj_recv(client, temp, sizeof(temp), timeout); 479 | } 480 | else 481 | { 482 | at_client_obj_recv(client, temp, bfsz - temp_size, timeout); 483 | } 484 | temp_size += sizeof(temp); 485 | } 486 | return; 487 | } 488 | 489 | /* sync receive data */ 490 | if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz) 491 | { 492 | LOG_E("%s device receive size(%d) data failed.", device->name, bfsz); 493 | rt_free(recv_buf); 494 | return; 495 | } 496 | 497 | /* get at socket object by device socket descriptor */ 498 | socket = &(device->sockets[device_socket]); 499 | 500 | /* notice the receive buffer and buffer size */ 501 | if (at_evt_cb_set[AT_SOCKET_EVT_RECV]) 502 | { 503 | at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); 504 | } 505 | 506 | send_net_read(client, device_socket); 507 | } 508 | 509 | static const struct at_urc urc_table[] = 510 | { 511 | {"$MYURCCLOSE:", "\r\n", urc_close_func}, 512 | {"$MYURCREAD:", "\r\n", urc_recv_func}, 513 | {"$MYNETREAD:", "\r\n", read_ack_func}, 514 | }; 515 | 516 | static const struct at_socket_ops n720_socket_ops = 517 | { 518 | n720_socket_connect, 519 | n720_socket_close, 520 | n720_socket_send, 521 | n720_domain_resolve, 522 | n720_socket_set_event_cb, 523 | }; 524 | 525 | int n720_socket_init(struct at_device *device) 526 | { 527 | RT_ASSERT(device); 528 | 529 | /* register URC data execution function */ 530 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 531 | 532 | return RT_EOK; 533 | } 534 | 535 | int n720_socket_class_register(struct at_device_class *class) 536 | { 537 | RT_ASSERT(class); 538 | 539 | class->socket_num = AT_DEVICE_N720_SOCKETS_NUM; 540 | class->socket_ops = &n720_socket_ops; 541 | 542 | return RT_EOK; 543 | } 544 | 545 | #endif /* AT_DEVICE_USING_N720 && AT_USING_SOCKET */ 546 | 547 | -------------------------------------------------------------------------------- /class/rw007/at_device_rw007.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-06-20 chenyong first version 9 | * 2019-05-12 chenyong multi AT socket client support 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define LOG_TAG "at.dev.rw007" 18 | 19 | #include 20 | 21 | #ifdef AT_DEVICE_USING_RW007 22 | 23 | #define RW007_WAIT_CONNECT_TIME 5000 24 | #define RW007_THREAD_STACK_SIZE 2048 25 | #define RW007_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 2) 26 | 27 | /* ============================= rw007 network interface operations ============================= */ 28 | 29 | static struct netdev *rw007_netdev_add(const char *netdev_name) 30 | { 31 | #define ETHERNET_MTU 1500 32 | #define HWADDR_LEN 6 33 | struct netdev *netdev = RT_NULL; 34 | 35 | RT_ASSERT(netdev_name); 36 | 37 | netdev = netdev_get_by_name(netdev_name); 38 | if (netdev != RT_NULL) 39 | { 40 | return (netdev); 41 | } 42 | 43 | netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev)); 44 | if (netdev == RT_NULL) 45 | { 46 | return RT_NULL; 47 | } 48 | 49 | /* TODO: improve netdev adaptation */ 50 | netdev->mtu = ETHERNET_MTU; 51 | netdev->hwaddr_len = HWADDR_LEN; 52 | netdev->ops = RT_NULL; 53 | 54 | #ifdef SAL_USING_AT 55 | extern int sal_at_netdev_set_pf_info(struct netdev *netdev); 56 | /* set the network interface socket/netdb operations */ 57 | sal_at_netdev_set_pf_info(netdev); 58 | #endif 59 | 60 | netdev_register(netdev, netdev_name, RT_NULL); 61 | 62 | /*TODO: improve netdev adaptation */ 63 | netdev_low_level_set_status(netdev, RT_TRUE); 64 | netdev_low_level_set_link_status(netdev, RT_TRUE); 65 | netdev_low_level_set_dhcp_status(netdev, RT_TRUE); 66 | netdev->flags |= NETDEV_FLAG_INTERNET_UP; 67 | 68 | return netdev; 69 | } 70 | 71 | /* ============================= rw007 device operations ============================= */ 72 | 73 | #define AT_SEND_CMD(client, resp, cmd) \ 74 | do { \ 75 | (resp) = at_resp_set_info((resp), 256, 0, 5 * RT_TICK_PER_SECOND); \ 76 | if (at_obj_exec_cmd((client), (resp), (cmd)) < 0) \ 77 | { \ 78 | result = -RT_ERROR; \ 79 | goto __exit; \ 80 | } \ 81 | } while(0) \ 82 | 83 | static void rw007_init_thread_entry(void *parameter) 84 | { 85 | #define INIT_RETRY 5 86 | 87 | struct at_device *device = (struct at_device *) parameter; 88 | struct at_device_rw007 *rw007 = (struct at_device_rw007 *) device->user_data; 89 | struct at_client *client = device->client; 90 | at_response_t resp = RT_NULL; 91 | rt_err_t result = RT_EOK; 92 | rt_size_t i = 0, retry_num = INIT_RETRY; 93 | 94 | /* wait rw007 device startup finish */ 95 | if (at_client_obj_wait_connect(client, RW007_WAIT_CONNECT_TIME)) 96 | { 97 | return; 98 | } 99 | 100 | resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND); 101 | if (resp == RT_NULL) 102 | { 103 | LOG_E("no memory for resp create."); 104 | return; 105 | } 106 | 107 | while (retry_num--) 108 | { 109 | /* reset module */ 110 | AT_SEND_CMD(client, resp, "AT+RST"); 111 | /* reset waiting delay */ 112 | rt_thread_mdelay(1000); 113 | /* disable echo */ 114 | AT_SEND_CMD(client, resp, "ATE0"); 115 | /* set current mode to Wi-Fi station */ 116 | AT_SEND_CMD(client, resp, "AT+CWMODE=1"); 117 | /* get module version */ 118 | AT_SEND_CMD(client, resp, "AT+GMR"); 119 | /* show module version */ 120 | for (i = 0; i < resp->line_counts - 1; i++) 121 | { 122 | LOG_D("%s", at_resp_get_line(resp, i + 1)); 123 | } 124 | /* connect to WiFi AP */ 125 | if (at_obj_exec_cmd(client, at_resp_set_info(resp, 128, 0, 20 * RT_TICK_PER_SECOND), 126 | "AT+CWJAP=\"%s\",\"%s\"", rw007->wifi_ssid, rw007->wifi_password) != RT_EOK) 127 | { 128 | LOG_E("%s device wifi connect failed, check ssid(%s) and password(%s).", 129 | device->name, rw007->wifi_ssid, rw007->wifi_password); 130 | result = -RT_ERROR; 131 | goto __exit; 132 | } 133 | 134 | AT_SEND_CMD(client, resp, "AT+CIPMUX=1"); 135 | 136 | /* initialize successfully */ 137 | result = RT_EOK; 138 | break; 139 | 140 | __exit: 141 | if (result != RT_EOK) 142 | { 143 | rt_thread_mdelay(1000); 144 | LOG_I("%s device initialize retry...", device->name); 145 | } 146 | } 147 | 148 | if (resp) 149 | { 150 | at_delete_resp(resp); 151 | } 152 | 153 | if (result != RT_EOK) 154 | { 155 | netdev_low_level_set_status(device->netdev, RT_FALSE); 156 | LOG_E("%s device network initialize failed(%d).", device->name, result); 157 | } 158 | else 159 | { 160 | netdev_low_level_set_status(device->netdev, RT_TRUE); 161 | LOG_I("%s device network initialize success.", device->name); 162 | } 163 | } 164 | 165 | int rw007_net_init(struct at_device *device) 166 | { 167 | #ifdef AT_DEVICE_RW007_INIT_ASYN 168 | rt_thread_t tid; 169 | 170 | tid = rt_thread_create("rw007_net", rw007_init_thread_entry, 171 | (void *)device, RW007_THREAD_STACK_SIZE, RW007_THREAD_PRIORITY, 20); 172 | if (tid) 173 | { 174 | rt_thread_startup(tid); 175 | } 176 | else 177 | { 178 | LOG_E("create %s device initialization thread failed.", device->name); 179 | return -RT_ERROR; 180 | } 181 | #else 182 | rw007_init_thread_entry(device); 183 | #endif /* AT_DEVICE_RW007_INIT_ASYN */ 184 | 185 | return RT_EOK; 186 | } 187 | 188 | static void urc_busy_p_func(struct at_client *client, const char *data, rt_size_t size) 189 | { 190 | LOG_D("system is processing a commands..."); 191 | } 192 | 193 | static void urc_busy_s_func(struct at_client *client, const char *data, rt_size_t size) 194 | { 195 | LOG_D("system is sending data..."); 196 | } 197 | 198 | static void urc_func(struct at_client *client, const char *data, rt_size_t size) 199 | { 200 | struct at_device *device = RT_NULL; 201 | char *client_name = client->device->parent.name; 202 | 203 | RT_ASSERT(client && data && size); 204 | 205 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 206 | if (device == RT_NULL) 207 | { 208 | LOG_E("get device(%s) failed.", client_name); 209 | return; 210 | } 211 | 212 | if (rt_strstr(data, "WIFI CONNECTED")) 213 | { 214 | LOG_I("%s device wifi is connected.", device->name); 215 | } 216 | else if (rt_strstr(data, "WIFI DISCONNECT")) 217 | { 218 | LOG_I("%s device wifi is disconnect.", device->name); 219 | } 220 | } 221 | 222 | static struct at_urc urc_table[] = { 223 | {"busy p", "\r\n", urc_busy_p_func}, 224 | {"busy s", "\r\n", urc_busy_s_func}, 225 | {"WIFI CONNECTED", "\r\n", urc_func}, 226 | {"WIFI DISCONNECT", "\r\n", urc_func}, 227 | }; 228 | 229 | static int rw007_init(struct at_device *device) 230 | { 231 | struct at_device_rw007 *rw007 = (struct at_device_rw007 *) device->user_data; 232 | 233 | /* initialize AT client */ 234 | #if RT_VER_NUM >= 0x50100 235 | at_client_init(rw007->client_name, rw007->recv_line_num, rw007->recv_line_num); 236 | #else 237 | at_client_init(rw007->client_name, rw007->recv_line_num); 238 | #endif 239 | 240 | device->client = at_client_get(rw007->client_name); 241 | if (device->client == RT_NULL) 242 | { 243 | LOG_E("get AT client(%s) failed.", rw007->client_name); 244 | return -RT_ERROR; 245 | } 246 | 247 | /* register URC data execution function */ 248 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 249 | 250 | #ifdef AT_USING_SOCKET 251 | rw007_socket_init(device); 252 | #endif 253 | 254 | /* add rw007 device to the netdev list */ 255 | device->netdev = rw007_netdev_add(rw007->device_name); 256 | if (device->netdev == RT_NULL) 257 | { 258 | LOG_E("get netdev(%s) failed.", rw007->device_name); 259 | return -RT_ERROR; 260 | } 261 | 262 | /* initialize rw007 device network */ 263 | return rw007_net_init(device); 264 | } 265 | 266 | static int rw007_deinit(struct at_device *device) 267 | { 268 | // TODO add netdev operation 269 | device->is_init = RT_FALSE; 270 | return RT_EOK; 271 | } 272 | 273 | /* reset eap8266 device and initialize device network again */ 274 | static int rw007_reset(struct at_device *device) 275 | { 276 | int result = RT_EOK; 277 | struct at_client *client = device->client; 278 | 279 | /* send "AT+RST" commonds to rw007 device */ 280 | result = at_obj_exec_cmd(client, RT_NULL, "AT+RST"); 281 | rt_thread_delay(1000); 282 | 283 | /* waiting 10 seconds for rw007 device reset */ 284 | device->is_init = RT_FALSE; 285 | if (at_client_obj_wait_connect(client, RW007_WAIT_CONNECT_TIME)) 286 | { 287 | return -RT_ETIMEOUT; 288 | } 289 | 290 | /* initialize rw007 device network */ 291 | rw007_net_init(device); 292 | 293 | device->is_init = RT_TRUE; 294 | 295 | return result; 296 | } 297 | 298 | /* change eap8266 wifi ssid and password information */ 299 | static int rw007_wifi_info_set(struct at_device *device, struct at_device_ssid_pwd *info) 300 | { 301 | int result = RT_EOK; 302 | struct at_response *resp = RT_NULL; 303 | 304 | if (info->ssid == RT_NULL || info->password == RT_NULL) 305 | { 306 | LOG_E("input wifi ssid(%s) and password(%s) error.", info->ssid, info->password); 307 | return -RT_ERROR; 308 | } 309 | 310 | resp = at_create_resp(128, 0, 20 * RT_TICK_PER_SECOND); 311 | if (resp == RT_NULL) 312 | { 313 | LOG_E("no memory for resp create."); 314 | return -RT_ENOMEM; 315 | } 316 | 317 | /* connect to input wifi ap */ 318 | if (at_obj_exec_cmd(device->client, resp, "AT+CWJAP=\"%s\",\"%s\"", info->ssid, info->password) != RT_EOK) 319 | { 320 | LOG_E("%s device wifi connect failed, check ssid(%s) and password(%s).", 321 | device->name, info->ssid, info->password); 322 | result = -RT_ERROR; 323 | } 324 | 325 | if (resp) 326 | { 327 | at_delete_resp(resp); 328 | } 329 | 330 | return result; 331 | } 332 | static int rw007_control(struct at_device *device, int cmd, void *arg) 333 | { 334 | int result = -RT_ERROR; 335 | 336 | RT_ASSERT(device); 337 | 338 | switch (cmd) 339 | { 340 | case AT_DEVICE_CTRL_POWER_ON: 341 | case AT_DEVICE_CTRL_POWER_OFF: 342 | case AT_DEVICE_CTRL_LOW_POWER: 343 | case AT_DEVICE_CTRL_SLEEP: 344 | case AT_DEVICE_CTRL_WAKEUP: 345 | case AT_DEVICE_CTRL_NET_CONN: 346 | case AT_DEVICE_CTRL_NET_DISCONN: 347 | case AT_DEVICE_CTRL_GET_SIGNAL: 348 | case AT_DEVICE_CTRL_GET_GPS: 349 | case AT_DEVICE_CTRL_GET_VER: 350 | LOG_W("not support the control command(%d).", cmd); 351 | break; 352 | case AT_DEVICE_CTRL_RESET: 353 | result = rw007_reset(device); 354 | break; 355 | case AT_DEVICE_CTRL_SET_WIFI_INFO: 356 | result = rw007_wifi_info_set(device, (struct at_device_ssid_pwd *) arg); 357 | break; 358 | default: 359 | LOG_E("input error control command(%d).", cmd); 360 | break; 361 | } 362 | 363 | return result; 364 | } 365 | 366 | const struct at_device_ops rw007_device_ops = 367 | { 368 | rw007_init, 369 | rw007_deinit, 370 | rw007_control, 371 | }; 372 | 373 | static int rw007_device_class_register(void) 374 | { 375 | struct at_device_class *class = RT_NULL; 376 | 377 | class = (struct at_device_class *) rt_calloc(1, sizeof(struct at_device_class)); 378 | if (class == RT_NULL) 379 | { 380 | LOG_E("no memory for device class create."); 381 | return -RT_ENOMEM; 382 | } 383 | 384 | /* fill rw007 device class object */ 385 | #ifdef AT_USING_SOCKET 386 | rw007_socket_class_register(class); 387 | #endif 388 | class->device_ops = &rw007_device_ops; 389 | 390 | return at_device_class_register(class, AT_DEVICE_CLASS_RW007); 391 | } 392 | INIT_DEVICE_EXPORT(rw007_device_class_register); 393 | 394 | #endif /* AT_DEVICE_USING_RW007 */ 395 | -------------------------------------------------------------------------------- /class/rw007/at_device_rw007.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_RW007_H__ 12 | #define __AT_DEVICE_RW007_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the rw007 device */ 23 | #define AT_DEVICE_RW007_SOCKETS_NUM 5 24 | 25 | struct at_device_rw007 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | char *wifi_ssid; 31 | char *wifi_password; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* rw007 device socket initialize */ 41 | int rw007_socket_init(struct at_device *device); 42 | 43 | /* rw007 device class socket register */ 44 | int rw007_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_RW007_H__ */ 53 | -------------------------------------------------------------------------------- /class/rw007/at_socket_rw007.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-06-20 chenyong first version 9 | * 2019-05-12 chenyong multi AT socket client support 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define LOG_TAG "at.skt.rw007" 18 | #include 19 | 20 | #if defined(AT_DEVICE_USING_RW007) && defined(AT_USING_SOCKET) 21 | 22 | #define RW007_MODULE_SEND_MAX_SIZE 2048 23 | /* set real event by current socket and current state */ 24 | #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event)) 25 | 26 | /* AT socket event type */ 27 | #define RW007_EVENT_CONN_OK (1L << 0) 28 | #define RW007_EVENT_SEND_OK (1L << 1) 29 | #define RW007_EVENT_RECV_OK (1L << 2) 30 | #define RW007_EVNET_CLOSE_OK (1L << 3) 31 | #define RW007_EVENT_CONN_FAIL (1L << 4) 32 | #define RW007_EVENT_SEND_FAIL (1L << 5) 33 | 34 | static at_evt_cb_t at_evt_cb_set[] = { 35 | [AT_SOCKET_EVT_RECV] = NULL, 36 | [AT_SOCKET_EVT_CLOSED] = NULL, 37 | }; 38 | 39 | static int rw007_socket_event_send(struct at_device *device, uint32_t event) 40 | { 41 | return (int) rt_event_send(device->socket_event, event); 42 | } 43 | 44 | static int rw007_socket_event_recv(struct at_device *device, uint32_t event, uint32_t timeout, rt_uint8_t option) 45 | { 46 | int result = RT_EOK; 47 | rt_uint32_t recved; 48 | 49 | result = rt_event_recv(device->socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved); 50 | if (result != RT_EOK) 51 | { 52 | return -RT_ETIMEOUT; 53 | } 54 | 55 | return recved; 56 | } 57 | 58 | /** 59 | * close socket by AT commands. 60 | * 61 | * @param current socket 62 | * 63 | * @return 0: close socket success 64 | * -1: send AT commands error 65 | * -2: wait socket event timeout 66 | * -5: no memory 67 | */ 68 | static int rw007_socket_close(struct at_socket *socket) 69 | { 70 | int result = RT_EOK; 71 | at_response_t resp = RT_NULL; 72 | int device_socket = (int) socket->user_data; 73 | struct at_device *device = (struct at_device *) socket->device; 74 | 75 | resp = at_create_resp(64, 0, RT_TICK_PER_SECOND); 76 | if (resp == RT_NULL) 77 | { 78 | LOG_E("no memory for resp create."); 79 | return -RT_ENOMEM; 80 | } 81 | 82 | result = at_obj_exec_cmd(device->client, resp, "AT+CIPCLOSE=%d", device_socket); 83 | 84 | if (resp) 85 | { 86 | at_delete_resp(resp); 87 | } 88 | 89 | return result; 90 | } 91 | 92 | /** 93 | * create TCP/UDP client or server connect by AT commands. 94 | * 95 | * @param socket current socket 96 | * @param ip server or client IP address 97 | * @param port server or client port 98 | * @param type connect socket type(tcp, udp) 99 | * @param is_client connection is client 100 | * 101 | * @return 0: connect success 102 | * -1: connect failed, send commands error or type error 103 | * -2: wait socket event timeout 104 | * -5: no memory 105 | */ 106 | static int rw007_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client) 107 | { 108 | int result = RT_EOK; 109 | rt_bool_t retryed = RT_FALSE; 110 | at_response_t resp = RT_NULL; 111 | int device_socket = (int) socket->user_data; 112 | struct at_device *device = (struct at_device *) socket->device; 113 | 114 | RT_ASSERT(ip); 115 | RT_ASSERT(port >= 0); 116 | 117 | resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND); 118 | if (resp == RT_NULL) 119 | { 120 | LOG_E("no memory for resp create."); 121 | return -RT_ENOMEM; 122 | } 123 | 124 | __retry: 125 | if (is_client) 126 | { 127 | switch (type) 128 | { 129 | case AT_SOCKET_TCP: 130 | /* send AT commands to connect TCP server */ 131 | if (at_obj_exec_cmd(device->client, resp, 132 | "AT+CIPSTART=%d,\"TCP\",\"%s\",%d,60", device_socket, ip, port) < 0) 133 | { 134 | result = -RT_ERROR; 135 | } 136 | break; 137 | 138 | case AT_SOCKET_UDP: 139 | if (at_obj_exec_cmd(device->client, resp, 140 | "AT+CIPSTART=%d,\"UDP\",\"%s\",%d", device_socket, ip, port) < 0) 141 | { 142 | result = -RT_ERROR; 143 | } 144 | break; 145 | 146 | default: 147 | LOG_E("not supported connect type %d.", type); 148 | result = -RT_ERROR; 149 | goto __exit; 150 | } 151 | } 152 | 153 | if (result != RT_EOK && retryed == RT_FALSE) 154 | { 155 | LOG_D("%s device socket(%d) connect failed, the socket was not be closed and now will connect retry.", 156 | device->name, socket); 157 | if (rw007_socket_close(socket) < 0) 158 | { 159 | goto __exit; 160 | } 161 | retryed = RT_TRUE; 162 | result = RT_EOK; 163 | goto __retry; 164 | } 165 | 166 | __exit: 167 | if (resp) 168 | { 169 | at_delete_resp(resp); 170 | } 171 | 172 | return result; 173 | } 174 | 175 | /** 176 | * send data to server or client by AT commands. 177 | * 178 | * @param socket current socket 179 | * @param buff send buffer 180 | * @param bfsz send buffer size 181 | * @param type connect socket type(tcp, udp) 182 | * 183 | * @return >=0: the size of send success 184 | * -1: send AT commands error or send data error 185 | * -2: waited socket event timeout 186 | * -5: no memory 187 | */ 188 | static int rw007_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type) 189 | { 190 | int result = RT_EOK; 191 | int event_result = 0; 192 | size_t cur_pkt_size = 0, sent_size = 0; 193 | at_response_t resp = RT_NULL; 194 | int device_socket = (int) socket->user_data; 195 | struct at_device *device = (struct at_device *) socket->device; 196 | struct at_device_rw007 *rw007 = (struct at_device_rw007 *) device->user_data; 197 | rt_mutex_t lock = device->client->lock; 198 | 199 | RT_ASSERT(buff); 200 | RT_ASSERT(bfsz > 0); 201 | 202 | resp = at_create_resp(128, 2, 5 * RT_TICK_PER_SECOND); 203 | if (resp == RT_NULL) 204 | { 205 | LOG_E("no memory for resp create."); 206 | return -RT_ENOMEM; 207 | } 208 | 209 | rt_mutex_take(lock, RT_WAITING_FOREVER); 210 | 211 | /* set current socket for send URC event */ 212 | rw007->user_data = (void *) device_socket; 213 | 214 | /* set AT client end sign to deal with '>' sign */ 215 | at_obj_set_end_sign(device->client, '>'); 216 | 217 | while (sent_size < bfsz) 218 | { 219 | if (bfsz - sent_size < RW007_MODULE_SEND_MAX_SIZE) 220 | { 221 | cur_pkt_size = bfsz - sent_size; 222 | } 223 | else 224 | { 225 | cur_pkt_size = RW007_MODULE_SEND_MAX_SIZE; 226 | } 227 | 228 | /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line */ 229 | if (at_obj_exec_cmd(device->client, resp, "AT+CIPSEND=%d,%d", device_socket, cur_pkt_size) < 0) 230 | { 231 | result = -RT_ERROR; 232 | goto __exit; 233 | } 234 | 235 | /* send the real data to server or client */ 236 | result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size); 237 | if (result == 0) 238 | { 239 | result = -RT_ERROR; 240 | goto __exit; 241 | } 242 | 243 | /* waiting result event from AT URC */ 244 | if (rw007_socket_event_recv(device, SET_EVENT(device_socket, 0), 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0) 245 | { 246 | LOG_E("%s device socket(%d) wait send result timeout.", device->name, device_socket); 247 | result = -RT_ETIMEOUT; 248 | goto __exit; 249 | } 250 | /* waiting OK or failed result */ 251 | event_result = rw007_socket_event_recv(device, RW007_EVENT_SEND_OK | RW007_EVENT_SEND_FAIL, 252 | 5 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR); 253 | if (event_result < 0) 254 | { 255 | LOG_E("%s device socket(%d) wait send OK|FAIL timeout.", device->name, device_socket); 256 | result = -RT_ETIMEOUT; 257 | goto __exit; 258 | } 259 | /* check result */ 260 | if (event_result & RW007_EVENT_SEND_FAIL) 261 | { 262 | LOG_E("%s device socket(%d) send failed.", device->name, device_socket); 263 | result = -RT_ERROR; 264 | goto __exit; 265 | } 266 | 267 | sent_size += cur_pkt_size; 268 | } 269 | 270 | __exit: 271 | /* reset the end sign for data */ 272 | at_obj_set_end_sign(device->client, 0); 273 | 274 | rt_mutex_release(lock); 275 | 276 | if (resp) 277 | { 278 | at_delete_resp(resp); 279 | } 280 | 281 | return result > 0 ? sent_size : result; 282 | } 283 | 284 | /** 285 | * domain resolve by AT commands. 286 | * 287 | * @param name domain name 288 | * @param ip parsed IP address, it's length must be 16 289 | * 290 | * @return 0: domain resolve success 291 | * -2: wait socket event timeout 292 | * -5: no memory 293 | */ 294 | static int rw007_domain_resolve(const char *name, char ip[16]) 295 | { 296 | #define RESOLVE_RETRY 5 297 | 298 | int i, result = RT_EOK; 299 | char recv_ip[16] = { 0 }; 300 | at_response_t resp = RT_NULL; 301 | struct at_device *device = RT_NULL; 302 | 303 | RT_ASSERT(name); 304 | RT_ASSERT(ip); 305 | 306 | device = at_device_get_first_initialized(); 307 | if (device == RT_NULL) 308 | { 309 | LOG_E("get first init device failed."); 310 | return -RT_ERROR; 311 | } 312 | 313 | resp = at_create_resp(128, 0, 20 * RT_TICK_PER_SECOND); 314 | if (resp == RT_NULL) 315 | { 316 | LOG_E("no memory for resp create."); 317 | return -RT_ENOMEM; 318 | } 319 | 320 | for (i = 0; i < RESOLVE_RETRY; i++) 321 | { 322 | if (at_obj_exec_cmd(device->client, resp, "AT+CIPDOMAIN=\"%s\"", name) < 0) 323 | { 324 | result = -RT_ERROR; 325 | goto __exit; 326 | } 327 | 328 | /* parse the third line of response data, get the IP address */ 329 | if (at_resp_parse_line_args_by_kw(resp, "+CIPDOMAIN:", "+CIPDOMAIN:%s", recv_ip) < 0) 330 | { 331 | rt_thread_mdelay(100); 332 | /* resolve failed, maybe receive an URC CRLF */ 333 | continue; 334 | } 335 | 336 | if (rt_strlen(recv_ip) < 8) 337 | { 338 | rt_thread_mdelay(100); 339 | /* resolve failed, maybe receive an URC CRLF */ 340 | continue; 341 | } 342 | else 343 | { 344 | rt_strncpy(ip, recv_ip, 15); 345 | ip[15] = '\0'; 346 | break; 347 | } 348 | } 349 | 350 | __exit: 351 | if (resp) 352 | { 353 | at_delete_resp(resp); 354 | } 355 | 356 | return result; 357 | 358 | } 359 | 360 | /** 361 | * set AT socket event notice callback 362 | * 363 | * @param event notice event 364 | * @param cb notice callback 365 | */ 366 | static void rw007_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) 367 | { 368 | if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])) 369 | { 370 | at_evt_cb_set[event] = cb; 371 | } 372 | } 373 | 374 | static const struct at_socket_ops rw007_socket_ops = 375 | { 376 | rw007_socket_connect, 377 | rw007_socket_close, 378 | rw007_socket_send, 379 | rw007_domain_resolve, 380 | rw007_socket_set_event_cb, 381 | #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300 382 | RT_NULL, 383 | #endif 384 | }; 385 | 386 | static void urc_send_func(struct at_client *client, const char *data, rt_size_t size) 387 | { 388 | int device_socket = 0; 389 | struct at_device *device = RT_NULL; 390 | struct at_device_rw007 *rw007 = RT_NULL; 391 | char *client_name = client->device->parent.name; 392 | 393 | RT_ASSERT(data && size); 394 | 395 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 396 | if (device == RT_NULL) 397 | { 398 | LOG_E("get device(%s) failed.", client_name); 399 | return; 400 | } 401 | rw007 = (struct at_device_rw007 *) device->user_data; 402 | device_socket = (int) rw007->user_data; 403 | 404 | if (rt_strstr(data, "SEND OK")) 405 | { 406 | rw007_socket_event_send(device, SET_EVENT(device_socket, RW007_EVENT_SEND_OK)); 407 | } 408 | else if (rt_strstr(data, "SEND FAIL")) 409 | { 410 | rw007_socket_event_send(device, SET_EVENT(device_socket, RW007_EVENT_SEND_FAIL)); 411 | } 412 | } 413 | 414 | static void urc_send_bfsz_func(struct at_client *client, const char *data, rt_size_t size) 415 | { 416 | static int cur_send_bfsz = 0; 417 | 418 | RT_ASSERT(data && size); 419 | 420 | rt_sscanf(data, "Recv %d bytes", &cur_send_bfsz); 421 | } 422 | 423 | static void urc_close_func(struct at_client *client, const char *data, rt_size_t size) 424 | { 425 | int device_socket = 0; 426 | struct at_socket *socket = RT_NULL; 427 | struct at_device *device = RT_NULL; 428 | char *client_name = client->device->parent.name; 429 | 430 | RT_ASSERT(data && size); 431 | 432 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 433 | if (device == RT_NULL) 434 | { 435 | LOG_E("get device(%s) failed.", client_name); 436 | return; 437 | } 438 | 439 | rt_sscanf(data, "%d,CLOSED", &device_socket); 440 | /* get at socket object by device socket descriptor */ 441 | socket = &(device->sockets[device_socket]); 442 | 443 | /* notice the socket is disconnect by remote */ 444 | if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED]) 445 | { 446 | at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0); 447 | } 448 | } 449 | 450 | static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size) 451 | { 452 | int device_socket = 0; 453 | rt_int32_t timeout = 0; 454 | rt_size_t bfsz = 0, temp_size = 0; 455 | char *recv_buf = RT_NULL, temp[8] = {0}; 456 | struct at_socket *socket = RT_NULL; 457 | struct at_device *device = RT_NULL; 458 | char *client_name = client->device->parent.name; 459 | 460 | RT_ASSERT(data && size); 461 | 462 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 463 | if (device == RT_NULL) 464 | { 465 | LOG_E("get device(%s) failed.", client_name); 466 | return; 467 | } 468 | 469 | /* get the current socket and receive buffer size by receive data */ 470 | rt_sscanf(data, "+IPD,%d,%d:", &device_socket, (int *) &bfsz); 471 | /* set receive timeout by receive buffer length, not less than 10 ms */ 472 | timeout = bfsz > 10 ? bfsz : 10; 473 | 474 | if (device_socket < 0 || bfsz == 0) 475 | { 476 | return; 477 | } 478 | 479 | recv_buf = (char *) rt_calloc(1, bfsz); 480 | if (recv_buf == RT_NULL) 481 | { 482 | LOG_E("no memory for receive buffer (%d).", bfsz); 483 | /* read and clean the coming data */ 484 | while (temp_size < bfsz) 485 | { 486 | if (bfsz - temp_size > sizeof(temp)) 487 | { 488 | at_client_obj_recv(client, temp, sizeof(temp), timeout); 489 | } 490 | else 491 | { 492 | at_client_obj_recv(client, temp, bfsz - temp_size, timeout); 493 | } 494 | temp_size += sizeof(temp); 495 | } 496 | return; 497 | } 498 | 499 | /* sync receive data */ 500 | if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz) 501 | { 502 | LOG_E("%s device receive size(%d) data failed.", device->name, bfsz); 503 | rt_free(recv_buf); 504 | return; 505 | } 506 | 507 | /* get at socket object by device socket descriptor */ 508 | socket = &(device->sockets[device_socket]); 509 | 510 | /* notice the receive buffer and buffer size */ 511 | if (at_evt_cb_set[AT_SOCKET_EVT_RECV]) 512 | { 513 | at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); 514 | } 515 | } 516 | 517 | static struct at_urc urc_table[] = 518 | { 519 | {"SEND OK", "\r\n", urc_send_func}, 520 | {"SEND FAIL", "\r\n", urc_send_func}, 521 | {"Recv", "bytes\r\n", urc_send_bfsz_func}, 522 | {"", ",CLOSED\r\n", urc_close_func}, 523 | {"+IPD", ":", urc_recv_func}, 524 | }; 525 | 526 | int rw007_socket_init(struct at_device *device) 527 | { 528 | RT_ASSERT(device); 529 | 530 | /* register URC data execution function */ 531 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 532 | 533 | return RT_EOK; 534 | } 535 | 536 | int rw007_socket_class_register(struct at_device_class *class) 537 | { 538 | RT_ASSERT(class); 539 | 540 | class->socket_num = AT_DEVICE_RW007_SOCKETS_NUM; 541 | class->socket_ops = &rw007_socket_ops; 542 | 543 | return RT_EOK; 544 | } 545 | 546 | #endif /* AT_DEVICE_USING_RW007 && AT_USING_SOCKET */ 547 | -------------------------------------------------------------------------------- /class/sim76xx/at_device_sim76xx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_SIM76XX_H__ 12 | #define __AT_DEVICE_SIM76XX_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the sim76xx device */ 23 | #define AT_DEVICE_SIM76XX_SOCKETS_NUM 10 24 | 25 | struct at_device_sim76xx 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* sim76xx device socket initialize */ 41 | int sim76xx_socket_init(struct at_device *device); 42 | 43 | /* sim76xx device class socket register */ 44 | int sim76xx_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_SIM76XX_H__ */ 53 | -------------------------------------------------------------------------------- /class/sim800c/at_device_sim800c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_SIM800C_H__ 12 | #define __AT_DEVICE_SIM800C_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the sim800c device */ 23 | #define AT_DEVICE_SIM800C_SOCKETS_NUM 6 24 | 25 | struct at_device_sim800c 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | int power_pin; 31 | int power_status_pin; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* sim800c device socket initialize */ 41 | int sim800c_socket_init(struct at_device *device); 42 | 43 | /* sim800c device class socket register */ 44 | int sim800c_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_SIM800C_H__ */ 53 | -------------------------------------------------------------------------------- /class/w60x/at_device_w60x.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-16 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_W60X_H__ 12 | #define __AT_DEVICE_W60X_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #include 21 | 22 | /* The maximum number of sockets supported by the w60x device */ 23 | #define AT_DEVICE_W60X_SOCKETS_NUM 20 24 | 25 | struct at_device_w60x 26 | { 27 | char *device_name; 28 | char *client_name; 29 | 30 | char *wifi_ssid; 31 | char *wifi_password; 32 | size_t recv_line_num; 33 | struct at_device device; 34 | 35 | void *user_data; 36 | }; 37 | 38 | #ifdef AT_USING_SOCKET 39 | 40 | /* w60x device socket initialize */ 41 | int w60x_socket_init(struct at_device *device); 42 | 43 | /* w60x device class socket register */ 44 | int w60x_socket_class_register(struct at_device_class *class); 45 | 46 | #endif /* AT_USING_SOCKET */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* __AT_DEVICE_W60X_H__ */ 53 | -------------------------------------------------------------------------------- /class/w60x/at_socket_w60x.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-06-20 chenyong first version 9 | * 2019-05-09 chenyong multi AT socket client support 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #define LOG_TAG "at.skt.w60x" 18 | #include 19 | 20 | #if defined(AT_DEVICE_USING_W60X) && defined(AT_USING_SOCKET) 21 | 22 | #define W60X_MODULE_SEND_MAX_SIZE 512 23 | 24 | static rt_int32_t w60x_socket_fd[AT_DEVICE_W60X_SOCKETS_NUM] = {-1}; 25 | 26 | static at_evt_cb_t at_evt_cb_set[] = { 27 | [AT_SOCKET_EVT_RECV] = NULL, 28 | [AT_SOCKET_EVT_CLOSED] = NULL, 29 | }; 30 | 31 | /** 32 | * close socket by AT commands. 33 | * 34 | * @param current socket 35 | * 36 | * @return 0: close socket success 37 | * -1: send AT commands error 38 | * -2: wait socket event timeout 39 | * -5: no memory 40 | */ 41 | static int w60x_socket_close(struct at_socket *socket) 42 | { 43 | int result = RT_EOK; 44 | at_response_t resp = RT_NULL; 45 | int device_socket = (int) socket->user_data; 46 | struct at_device *device = (struct at_device *) socket->device; 47 | int wsk = w60x_socket_fd[device_socket]; 48 | 49 | w60x_socket_fd[device_socket] = -1; 50 | resp = at_create_resp(64, 1, rt_tick_from_millisecond(300)); 51 | if (resp == RT_NULL) 52 | { 53 | LOG_E("no memory for resp create."); 54 | return -RT_ENOMEM; 55 | } 56 | 57 | at_obj_set_end_sign(device->client, '\r'); 58 | 59 | result = at_obj_exec_cmd(device->client, resp, "AT+SKCLS=%d", wsk); 60 | 61 | if (resp) 62 | { 63 | at_delete_resp(resp); 64 | } 65 | 66 | return result; 67 | } 68 | 69 | /** 70 | * create TCP/UDP client or server connect by AT commands. 71 | * 72 | * @param socket current socket 73 | * @param ip server or client IP address 74 | * @param port server or client port 75 | * @param type connect socket type(tcp, udp) 76 | * @param is_client connection is client 77 | * 78 | * @return 0: connect success 79 | * -1: connect failed, send commands error or type error 80 | * -2: wait socket event timeout 81 | * -5: no memory 82 | */ 83 | static int w60x_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client) 84 | { 85 | int result = RT_EOK; 86 | at_response_t resp = RT_NULL; 87 | int device_socket = (int) socket->user_data; 88 | struct at_device *device = (struct at_device *) socket->device; 89 | int socket_fd = -1; 90 | 91 | RT_ASSERT(ip); 92 | RT_ASSERT(port >= 0); 93 | 94 | resp = at_create_resp(64, 1, 5 * RT_TICK_PER_SECOND); 95 | if (resp == RT_NULL) 96 | { 97 | LOG_E("no memory for resp create."); 98 | return -RT_ENOMEM; 99 | } 100 | 101 | at_obj_set_end_sign(device->client, '\r'); 102 | 103 | /* send the "AT+SKRPTM" commands */ 104 | if (at_obj_exec_cmd(device->client, resp, "AT+SKRPTM=1") < 0) 105 | { 106 | result = -RT_ERROR; 107 | goto __exit; 108 | } 109 | rt_thread_mdelay(20); 110 | 111 | switch (type) 112 | { 113 | case AT_SOCKET_TCP: 114 | /* send AT commands */ 115 | if (at_obj_exec_cmd(device->client, resp, 116 | "AT+SKCT=0,%d,%s,%d", is_client ? 0 : 1, is_client ? ip : 0, port) < 0) 117 | { 118 | result = -RT_ERROR; 119 | } 120 | break; 121 | 122 | case AT_SOCKET_UDP: 123 | if (at_obj_exec_cmd(device->client, resp, 124 | "AT+SKCT=1,%d,%s,%d", is_client ? 0 : 1, is_client ? ip : 0, port) < 0) 125 | { 126 | result = -RT_ERROR; 127 | } 128 | break; 129 | 130 | default: 131 | LOG_E("not supported connect type %d.", type); 132 | result = -RT_ERROR; 133 | goto __exit; 134 | } 135 | 136 | if ((result != RT_EOK) || !rt_strstr(at_resp_get_line(resp, 1), "+OK=")) 137 | { 138 | LOG_D("%s device socket connect failed.", device->name); 139 | result = -1; 140 | goto __exit; 141 | } 142 | 143 | socket_fd = atoi(rt_strstr(at_resp_get_line(resp, 1), "+OK=") + rt_strlen("+OK=")); 144 | w60x_socket_fd[device_socket] = socket_fd; 145 | 146 | __exit: 147 | if (resp) 148 | { 149 | at_delete_resp(resp); 150 | } 151 | 152 | return result; 153 | } 154 | 155 | /** 156 | * send data to server or client by AT commands. 157 | * 158 | * @param socket current socket 159 | * @param buff send buffer 160 | * @param bfsz send buffer size 161 | * @param type connect socket type(tcp, udp) 162 | * 163 | * @return >=0: the size of send success 164 | * -1: send AT commands error or send data error 165 | * -2: waited socket event timeout 166 | * -5: no memory 167 | */ 168 | static int w60x_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type) 169 | { 170 | int result = RT_EOK; 171 | size_t cur_pkt_size = 0, sent_size = 0; 172 | at_response_t resp = RT_NULL; 173 | int device_socket = (int) socket->user_data; 174 | struct at_device *device = (struct at_device *) socket->device; 175 | struct at_device_w60x *w60x = (struct at_device_w60x *) device->user_data; 176 | rt_mutex_t lock = device->client->lock; 177 | 178 | RT_ASSERT(buff); 179 | RT_ASSERT(bfsz > 0); 180 | 181 | resp = at_create_resp(128, 1, 5 * RT_TICK_PER_SECOND); 182 | if (resp == RT_NULL) 183 | { 184 | LOG_E("no memory for resp create."); 185 | return -RT_ENOMEM; 186 | } 187 | 188 | rt_mutex_take(lock, RT_WAITING_FOREVER); 189 | 190 | /* set current socket for send URC event */ 191 | w60x->user_data = (void *) device_socket; 192 | 193 | /* set AT client end sign to deal with '\n' sign */ 194 | at_obj_set_end_sign(device->client, '\n'); 195 | 196 | while (sent_size < bfsz) 197 | { 198 | if (bfsz - sent_size < W60X_MODULE_SEND_MAX_SIZE) 199 | { 200 | cur_pkt_size = bfsz - sent_size; 201 | } 202 | else 203 | { 204 | cur_pkt_size = W60X_MODULE_SEND_MAX_SIZE; 205 | } 206 | 207 | rt_thread_mdelay(5); 208 | /* send the "AT+SKSND" commands */ 209 | if (at_obj_exec_cmd(device->client, resp, "AT+SKSND=%d,%d", w60x_socket_fd[device_socket], cur_pkt_size) < 0) 210 | { 211 | result = -RT_ERROR; 212 | goto __exit; 213 | } 214 | 215 | if (!rt_strstr(at_resp_get_line(resp, 1), "+OK=")) 216 | { 217 | result = -RT_ERROR; 218 | goto __exit; 219 | } 220 | 221 | /* send the real data to server or client */ 222 | result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size); 223 | if (result == 0) 224 | { 225 | result = -RT_ERROR; 226 | goto __exit; 227 | } 228 | 229 | sent_size += cur_pkt_size; 230 | } 231 | 232 | __exit: 233 | /* reset the end sign for data */ 234 | at_obj_set_end_sign(device->client, 0); 235 | 236 | rt_mutex_release(lock); 237 | 238 | if (resp) 239 | { 240 | at_delete_resp(resp); 241 | } 242 | 243 | return result > 0 ? sent_size : result; 244 | } 245 | 246 | /** 247 | * domain resolve by AT commands. 248 | * 249 | * @param name domain name 250 | * @param ip parsed IP address, it's length must be 16 251 | * 252 | * @return 0: domain resolve success 253 | * -2: wait socket event timeout 254 | * -5: no memory 255 | */ 256 | static int w60x_domain_resolve(const char *name, char ip[16]) 257 | { 258 | #define RESOLVE_RETRY 5 259 | 260 | int i, result = -RT_ERROR; 261 | char recv_ip[16] = { 0 }; 262 | at_response_t resp = RT_NULL; 263 | struct at_device *device = RT_NULL; 264 | char *pos; 265 | 266 | RT_ASSERT(name); 267 | RT_ASSERT(ip); 268 | 269 | device = at_device_get_first_initialized(); 270 | if (device == RT_NULL) 271 | { 272 | LOG_E("get first init device failed."); 273 | return -RT_ERROR; 274 | } 275 | 276 | resp = at_create_resp(128, 1, 20 * RT_TICK_PER_SECOND); 277 | if (resp == RT_NULL) 278 | { 279 | LOG_E("no memory for resp create."); 280 | return -RT_ENOMEM; 281 | } 282 | 283 | at_obj_set_end_sign(device->client, '\r'); 284 | 285 | for (i = 0; i < RESOLVE_RETRY; i++) 286 | { 287 | if (at_obj_exec_cmd(device->client, resp, "AT+SKGHBN=%s", name) < 0) 288 | { 289 | goto __exit; 290 | } 291 | 292 | /* parse the third line of response data, get the IP address */ 293 | pos = rt_strstr(resp->buf, "+OK="); 294 | if (!pos) 295 | { 296 | rt_thread_mdelay(100); 297 | /* resolve failed, maybe receive an URC CRLF */ 298 | continue; 299 | } 300 | 301 | rt_sscanf(pos, "+OK=\"%[^\"]\"", recv_ip); 302 | 303 | if (rt_strlen(recv_ip) < 8) 304 | { 305 | rt_thread_mdelay(100); 306 | /* resolve failed, maybe receive an URC CRLF */ 307 | continue; 308 | } 309 | else 310 | { 311 | rt_strncpy(ip, recv_ip, 15); 312 | ip[15] = '\0'; 313 | result = RT_EOK; 314 | break; 315 | } 316 | } 317 | 318 | __exit: 319 | if (resp) 320 | { 321 | at_delete_resp(resp); 322 | } 323 | 324 | return result; 325 | 326 | } 327 | 328 | /** 329 | * set AT socket event notice callback 330 | * 331 | * @param event notice event 332 | * @param cb notice callback 333 | */ 334 | static void w60x_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb) 335 | { 336 | if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])) 337 | { 338 | at_evt_cb_set[event] = cb; 339 | } 340 | } 341 | 342 | static const struct at_socket_ops w60x_socket_ops = 343 | { 344 | w60x_socket_connect, 345 | w60x_socket_close, 346 | w60x_socket_send, 347 | w60x_domain_resolve, 348 | w60x_socket_set_event_cb, 349 | #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300 350 | RT_NULL, 351 | #endif 352 | }; 353 | 354 | static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size) 355 | { 356 | int device_socket = -1; 357 | rt_int32_t timeout = 0; 358 | rt_size_t bfsz = 0, temp_size = 0; 359 | char *recv_buf = RT_NULL, temp[8] = {0}; 360 | struct at_socket *socket = RT_NULL; 361 | struct at_device *device = RT_NULL; 362 | char *client_name = client->device->parent.name; 363 | char recv_ip[16] = { 0 }; 364 | rt_int32_t recv_port = 0; 365 | rt_uint8_t i; 366 | char *pos; 367 | int wsk; 368 | 369 | RT_ASSERT(data && size); 370 | 371 | device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name); 372 | if (device == RT_NULL) 373 | { 374 | LOG_E("get device(%s) failed.", client_name); 375 | return; 376 | } 377 | 378 | /* get the at deveice socket and receive buffer size by receive data */ 379 | pos = rt_strstr(data, "+SKTRPT="); 380 | rt_sscanf(pos, "+SKTRPT=%d,%d,%[^,],%d", &wsk, (int *) &bfsz, recv_ip, &recv_port); 381 | 382 | for (i = 0; i < AT_DEVICE_W60X_SOCKETS_NUM; i++) 383 | { 384 | if (wsk == w60x_socket_fd[i]) 385 | { 386 | device_socket = i; 387 | break; 388 | } 389 | } 390 | 391 | /* set receive timeout by receive buffer length, not less than 10ms */ 392 | timeout = bfsz > 10 ? bfsz : 10; 393 | 394 | if (device_socket < 0 || bfsz == 0) 395 | return; 396 | 397 | recv_buf = (char *) rt_calloc(1, bfsz); 398 | if (recv_buf == RT_NULL) 399 | { 400 | LOG_E("no memory receive buffer(%d).", bfsz); 401 | /* read and clean the coming data */ 402 | while (temp_size < bfsz) 403 | { 404 | if (bfsz - temp_size > sizeof(temp)) 405 | { 406 | at_client_obj_recv(client, temp, sizeof(temp), timeout); 407 | } 408 | else 409 | { 410 | at_client_obj_recv(client, temp, bfsz - temp_size, timeout); 411 | } 412 | temp_size += sizeof(temp); 413 | } 414 | return; 415 | } 416 | 417 | /* "\n\r\n" left in SERIAL */ 418 | at_client_obj_recv(client, temp, 3, timeout); 419 | 420 | /* sync receive data */ 421 | if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz) 422 | { 423 | LOG_E("%s device receive size(%d) data failed.", device->name, bfsz); 424 | rt_free(recv_buf); 425 | return; 426 | } 427 | 428 | /* get at socket object by device socket descriptor */ 429 | socket = &(device->sockets[device_socket]); 430 | 431 | /* notice the receive buffer and buffer size */ 432 | if (at_evt_cb_set[AT_SOCKET_EVT_RECV]) 433 | { 434 | at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz); 435 | } 436 | } 437 | 438 | static const struct at_urc urc_table[] = 439 | { 440 | {"+SKTRPT=", "\r", urc_recv_func}, 441 | {"\r\n+SKTRPT=", "\r", urc_recv_func}, 442 | {"\r+SKTRPT=", "\r", urc_recv_func}, 443 | {"\n+SKTRPT=", "\r", urc_recv_func}, 444 | }; 445 | 446 | int w60x_socket_init(struct at_device *device) 447 | { 448 | RT_ASSERT(device); 449 | 450 | /* register URC data execution function */ 451 | at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0])); 452 | 453 | return RT_EOK; 454 | } 455 | 456 | int w60x_socket_class_register(struct at_device_class *class) 457 | { 458 | RT_ASSERT(class); 459 | 460 | class->socket_num = AT_DEVICE_W60X_SOCKETS_NUM; 461 | class->socket_ops = &w60x_socket_ops; 462 | 463 | return RT_EOK; 464 | } 465 | 466 | #endif /* AT_DEVICE_USING_W60X && AT_USING_SOCKET */ 467 | -------------------------------------------------------------------------------- /inc/at_device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-08 chenyong first version 9 | */ 10 | 11 | #ifndef __AT_DEVICE_H__ 12 | #define __AT_DEVICE_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | #if !defined(RT_USING_NETDEV) || (!defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10300) 22 | #error "This RT-Thread version is older, please check and updata laster RT-Thread!" 23 | #else 24 | 25 | #include 26 | #include 27 | #endif /* RT_USING_NETDEV */ 28 | 29 | #if RT_VER_NUM < 0x50200 30 | #define rt_sscanf sscanf 31 | #endif 32 | 33 | #define AT_DEVICE_SW_VERSION "2.1.0" 34 | #define AT_DEVICE_SW_VERSION_NUM 0x20100 35 | 36 | /* AT device class ID */ 37 | #define AT_DEVICE_CLASS_ESP8266 0x01U 38 | #define AT_DEVICE_CLASS_M26_MC20 0x02U 39 | #define AT_DEVICE_CLASS_EC20 0x03U 40 | #define AT_DEVICE_CLASS_SIM800C 0x04U 41 | #define AT_DEVICE_CLASS_SIM76XX 0x05U 42 | #define AT_DEVICE_CLASS_RW007 0x06U 43 | #define AT_DEVICE_CLASS_MW31 0x07U 44 | #define AT_DEVICE_CLASS_ESP32 0x08U 45 | #define AT_DEVICE_CLASS_W60X 0x09U 46 | #define AT_DEVICE_CLASS_A9G 0x0AU 47 | #define AT_DEVICE_CLASS_BC26 0x0BU 48 | #define AT_DEVICE_CLASS_AIR720 0x0CU 49 | #define AT_DEVICE_CLASS_ME3616 0x0DU 50 | #define AT_DEVICE_CLASS_M6315 0x0EU 51 | #define AT_DEVICE_CLASS_BC28 0x0FU 52 | #define AT_DEVICE_CLASS_EC200X 0x10U 53 | #define AT_DEVICE_CLASS_N21 0x11U 54 | #define AT_DEVICE_CLASS_N58 0x12U 55 | #define AT_DEVICE_CLASS_M5311 0X13U 56 | #define AT_DEVICE_CLASS_N720 0X14U 57 | #define AT_DEVICE_CLASS_L610 0X15U 58 | #define AT_DEVICE_CLASS_ML305 0X16U 59 | #define AT_DEVICE_CLASS_ML307 0X17U 60 | 61 | /* Options and Commands for AT device control opreations */ 62 | #define AT_DEVICE_CTRL_POWER_ON 0x01L 63 | #define AT_DEVICE_CTRL_POWER_OFF 0x02L 64 | #define AT_DEVICE_CTRL_RESET 0x03L 65 | #define AT_DEVICE_CTRL_LOW_POWER 0x04L 66 | #define AT_DEVICE_CTRL_SLEEP 0x05L 67 | #define AT_DEVICE_CTRL_WAKEUP 0x06L 68 | #define AT_DEVICE_CTRL_NET_CONN 0x07L 69 | #define AT_DEVICE_CTRL_NET_DISCONN 0x08L 70 | #define AT_DEVICE_CTRL_SET_WIFI_INFO 0x09L 71 | #define AT_DEVICE_CTRL_GET_SIGNAL 0x0AL 72 | #define AT_DEVICE_CTRL_GET_GPS 0x0BL 73 | #define AT_DEVICE_CTRL_GET_VER 0x0CL 74 | 75 | /* Name type */ 76 | #define AT_DEVICE_NAMETYPE_DEVICE 0x01 77 | #define AT_DEVICE_NAMETYPE_NETDEV 0x02 78 | #define AT_DEVICE_NAMETYPE_CLIENT 0x03 79 | 80 | struct at_device; 81 | 82 | /* AT device wifi ssid and password information */ 83 | struct at_device_ssid_pwd 84 | { 85 | char *ssid; 86 | char *password; 87 | }; 88 | 89 | /* AT device operations */ 90 | struct at_device_ops 91 | { 92 | int (*init)(struct at_device *device); 93 | int (*deinit)(struct at_device *device); 94 | int (*control)(struct at_device *device, int cmd, void *arg); 95 | }; 96 | 97 | struct at_device_class 98 | { 99 | uint16_t class_id; /* AT device class ID */ 100 | const struct at_device_ops *device_ops; /* AT device operaiotns */ 101 | #ifdef AT_USING_SOCKET 102 | uint32_t socket_num; /* The maximum number of sockets support */ 103 | const struct at_socket_ops *socket_ops; /* AT device socket operations */ 104 | #endif 105 | rt_slist_t list; /* AT device class list */ 106 | }; 107 | 108 | struct at_device 109 | { 110 | char name[RT_NAME_MAX]; /* AT device name */ 111 | rt_bool_t is_init; /* AT device initialization completed */ 112 | struct at_device_class *class; /* AT device class object */ 113 | struct at_client *client; /* AT Client object for AT device */ 114 | struct netdev *netdev; /* Network interface device for AT device */ 115 | #ifdef AT_USING_SOCKET 116 | rt_event_t socket_event; /* AT device socket event */ 117 | struct at_socket *sockets; /* AT device sockets list */ 118 | #endif 119 | rt_slist_t list; /* AT device list */ 120 | 121 | void *user_data; /* User-specific data */ 122 | }; 123 | 124 | /* Get AT device object */ 125 | struct at_device *at_device_get_first_initialized(void); 126 | struct at_device *at_device_get_by_name(int type, const char *name); 127 | #ifdef AT_USING_SOCKET 128 | struct at_device *at_device_get_by_socket(int at_socket); 129 | #endif 130 | 131 | /* AT device control operaions */ 132 | int at_device_control(struct at_device *device, int cmd, void *arg); 133 | /* Register AT device class object */ 134 | int at_device_class_register(struct at_device_class *class, uint16_t class_id); 135 | /* Register AT device object */ 136 | int at_device_register(struct at_device *device, const char *device_name, 137 | const char *at_client_name, uint16_t class_id, void *user_data); 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* __AT_DEVICE_H__ */ 144 | -------------------------------------------------------------------------------- /samples/at_sample_a9g.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-11-23 luliang first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.a9g" 14 | #include 15 | 16 | #define A9G_SAMPLE_DEIVCE_NAME "a9g0" 17 | 18 | static struct at_device_a9g a9g0 = 19 | { 20 | A9G_SAMPLE_DEIVCE_NAME, 21 | A9G_SAMPLE_CLIENT_NAME, 22 | 23 | A9G_SAMPLE_POWER_PIN, 24 | A9G_SAMPLE_STATUS_PIN, 25 | A9G_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int a9g_device_register(void) 29 | { 30 | struct at_device_a9g *a9g = &a9g0; 31 | 32 | return at_device_register(&(a9g->device), 33 | a9g->device_name, 34 | a9g->client_name, 35 | AT_DEVICE_CLASS_A9G, 36 | (void *) a9g); 37 | } 38 | INIT_APP_EXPORT(a9g_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_air720.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-07 liang.shao first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample" 14 | #include 15 | 16 | #define AIR720_SAMPLE_DEIVCE_NAME "air720" 17 | 18 | static struct at_device_air720 sim0 = 19 | { 20 | AIR720_SAMPLE_DEIVCE_NAME, 21 | AIR720_SAMPLE_CLIENT_NAME, 22 | 23 | AIR720_SAMPLE_POWER_PIN, 24 | AIR720_SAMPLE_STATUS_PIN, 25 | AIR720_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int air720_device_register(void) 29 | { 30 | struct at_device_air720 *air720 = &sim0; 31 | 32 | return at_device_register(&(air720->device), 33 | air720->device_name, 34 | air720->client_name, 35 | AT_DEVICE_CLASS_AIR720, 36 | (void *) air720); 37 | } 38 | INIT_APP_EXPORT(air720_device_register); 39 | //MSH_CMD_EXPORT(air720_device_register,air720_device_register); 40 | -------------------------------------------------------------------------------- /samples/at_sample_bc26.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-13 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.bc26" 14 | #include 15 | 16 | #define BC26_SAMPLE_DEIVCE_NAME "bc26" 17 | 18 | static struct at_device_bc26 _dev = 19 | { 20 | BC26_SAMPLE_DEIVCE_NAME, 21 | BC26_SAMPLE_CLIENT_NAME, 22 | 23 | BC26_SAMPLE_POWER_PIN, 24 | BC26_SAMPLE_STATUS_PIN, 25 | BC26_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int bc26_device_register(void) 29 | { 30 | struct at_device_bc26 *bc26 = &_dev; 31 | 32 | return at_device_register(&(bc26->device), 33 | bc26->device_name, 34 | bc26->client_name, 35 | AT_DEVICE_CLASS_BC26, 36 | (void *) bc26); 37 | } 38 | INIT_APP_EXPORT(bc26_device_register); 39 | 40 | -------------------------------------------------------------------------------- /samples/at_sample_bc28.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-02-13 luhuadong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.bc28" 14 | #include 15 | 16 | #define BC28_SAMPLE_DEIVCE_NAME "bc28" 17 | 18 | static struct at_device_bc28 _dev = 19 | { 20 | BC28_SAMPLE_DEIVCE_NAME, 21 | BC28_SAMPLE_CLIENT_NAME, 22 | 23 | BC28_SAMPLE_POWER_PIN, 24 | BC28_SAMPLE_STATUS_PIN, 25 | BC28_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int bc28_device_register(void) 29 | { 30 | struct at_device_bc28 *bc28 = &_dev; 31 | 32 | return at_device_register(&(bc28->device), 33 | bc28->device_name, 34 | bc28->client_name, 35 | AT_DEVICE_CLASS_BC28, 36 | (void *) bc28); 37 | } 38 | INIT_APP_EXPORT(bc28_device_register); 39 | 40 | -------------------------------------------------------------------------------- /samples/at_sample_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2018-07-06 chenyong first version 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #define LOG_TAG "at.sample" 18 | #include 19 | 20 | /* AT+CIFSR Query local IP address and MAC */ 21 | int at_client_test(int argc, char **argv) 22 | { 23 | at_response_t resp = RT_NULL; 24 | int result = 0; 25 | 26 | if (argc != 1) 27 | { 28 | LOG_E("at_client_test - AT client send commands to AT server."); 29 | return -1; 30 | } 31 | 32 | resp = at_create_resp(256, 0, rt_tick_from_millisecond(5000)); 33 | if (resp == RT_NULL) 34 | { 35 | LOG_E("No memory for response structure!"); 36 | return -2; 37 | } 38 | 39 | /* close echo */ 40 | at_exec_cmd(resp, "ATE0"); 41 | 42 | result = at_exec_cmd(resp, "AT+CIFSR"); 43 | if (result != RT_EOK) 44 | { 45 | LOG_E("AT client send commands failed or return response error!"); 46 | goto __exit; 47 | } 48 | 49 | /* Print response line buffer */ 50 | { 51 | const char *line_buffer = RT_NULL; 52 | 53 | LOG_D("Response buffer"); 54 | 55 | for(rt_size_t line_num = 1; line_num <= resp->line_counts; line_num++) 56 | { 57 | if((line_buffer = at_resp_get_line(resp, line_num)) != RT_NULL) 58 | { 59 | LOG_D("line %d buffer : %s", line_num, line_buffer); 60 | } 61 | else 62 | { 63 | LOG_E("Parse line buffer error!"); 64 | } 65 | } 66 | } 67 | 68 | { 69 | char resp_arg[AT_CMD_MAX_LEN] = { 0 }; 70 | const char * resp_expr = "%*[^\"]\"%[^\"]\""; 71 | 72 | LOG_D(" Parse arguments"); 73 | if (at_resp_parse_line_args(resp, 1, resp_expr, resp_arg) == 1) 74 | { 75 | LOG_D("Station IP : %s", resp_arg); 76 | rt_memset(resp_arg, 0x00, AT_CMD_MAX_LEN); 77 | } 78 | else 79 | { 80 | LOG_E("Parse error, current line buff : %s", at_resp_get_line(resp, 4)); 81 | } 82 | 83 | if (at_resp_parse_line_args(resp, 2, resp_expr, resp_arg) == 1) 84 | { 85 | LOG_D("Station MAC : %s", resp_arg); 86 | } 87 | else 88 | { 89 | LOG_E("Parse error, current line buff : %s", at_resp_get_line(resp, 5)); 90 | goto __exit; 91 | } 92 | } 93 | __exit: 94 | if(resp) 95 | { 96 | at_delete_resp(resp); 97 | } 98 | 99 | return result; 100 | } 101 | 102 | int at_client_test_init(int argc, char **argv) 103 | { 104 | #define AT_CLIENT_RECV_BUFF_LEN 512 105 | 106 | if (argc != 2) 107 | { 108 | rt_kprintf("at_client_init -- AT client initialize.\n"); 109 | return -RT_ERROR; 110 | } 111 | 112 | at_client_init(argv[1], AT_CLIENT_RECV_BUFF_LEN); 113 | 114 | return RT_EOK; 115 | } 116 | #ifdef FINSH_USING_MSH 117 | #include 118 | MSH_CMD_EXPORT(at_client_test, AT client send cmd and get response); 119 | MSH_CMD_EXPORT_ALIAS(at_client_test_init, at_client_init, initialize AT client); 120 | #endif 121 | -------------------------------------------------------------------------------- /samples/at_sample_ec20.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.ec20" 14 | #include 15 | 16 | #define EC20_SAMPLE_DEIVCE_NAME "e0" 17 | 18 | static struct at_device_ec20 e0 = 19 | { 20 | EC20_SAMPLE_DEIVCE_NAME, 21 | EC20_SAMPLE_CLIENT_NAME, 22 | 23 | EC20_SAMPLE_POWER_PIN, 24 | EC20_SAMPLE_STATUS_PIN, 25 | EC20_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int ec20_device_register(void) 29 | { 30 | struct at_device_ec20 *ec20 = &e0; 31 | 32 | return at_device_register(&(ec20->device), 33 | ec20->device_name, 34 | ec20->client_name, 35 | AT_DEVICE_CLASS_EC20, 36 | (void *) ec20); 37 | } 38 | INIT_APP_EXPORT(ec20_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_ec200x.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-13 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.ec200x" 14 | #include 15 | 16 | #define EC200X_SAMPLE_DEIVCE_NAME "ec200x" 17 | 18 | static struct at_device_ec200x _dev = 19 | { 20 | EC200X_SAMPLE_DEIVCE_NAME, 21 | EC200X_SAMPLE_CLIENT_NAME, 22 | 23 | EC200X_SAMPLE_POWER_PIN, 24 | EC200X_SAMPLE_STATUS_PIN, 25 | EC200X_SAMPLE_WAKEUP_PIN, 26 | EC200X_SAMPLE_RECV_BUFF_LEN, 27 | RT_NULL 28 | }; 29 | 30 | static int ec200x_device_register(void) 31 | { 32 | struct at_device_ec200x *ec200x = &_dev; 33 | 34 | return at_device_register(&(ec200x->device), 35 | ec200x->device_name, 36 | ec200x->client_name, 37 | AT_DEVICE_CLASS_EC200X, 38 | (void *) ec200x); 39 | } 40 | INIT_APP_EXPORT(ec200x_device_register); 41 | 42 | int ec200x_get_rssi(void) 43 | { 44 | struct at_device_ec200x *ec200x = &_dev; 45 | return(ec200x->rssi); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /samples/at_sample_esp32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-10 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.esp" 14 | #include 15 | 16 | #define ESP32_SAMPLE_DEIVCE_NAME "esp32" 17 | 18 | static struct at_device_esp32 esp0 = 19 | { 20 | ESP32_SAMPLE_DEIVCE_NAME, 21 | ESP32_SAMPLE_CLIENT_NAME, 22 | 23 | ESP32_SAMPLE_WIFI_SSID, 24 | ESP32_SAMPLE_WIFI_PASSWORD, 25 | ESP32_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int esp32_device_register(void) 29 | { 30 | struct at_device_esp32 *esp32 = &esp0; 31 | 32 | return at_device_register(&(esp32->device), 33 | esp32->device_name, 34 | esp32->client_name, 35 | AT_DEVICE_CLASS_ESP32, 36 | (void *) esp32); 37 | } 38 | INIT_APP_EXPORT(esp32_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_esp8266.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-10 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.esp" 14 | #include 15 | 16 | #define ESP8266_SAMPLE_DEIVCE_NAME "esp0" 17 | 18 | static struct at_device_esp8266 esp0 = 19 | { 20 | ESP8266_SAMPLE_DEIVCE_NAME, 21 | ESP8266_SAMPLE_CLIENT_NAME, 22 | 23 | ESP8266_SAMPLE_WIFI_SSID, 24 | ESP8266_SAMPLE_WIFI_PASSWORD, 25 | ESP8266_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int esp8266_device_register(void) 29 | { 30 | struct at_device_esp8266 *esp8266 = &esp0; 31 | 32 | return at_device_register(&(esp8266->device), 33 | esp8266->device_name, 34 | esp8266->client_name, 35 | AT_DEVICE_CLASS_ESP8266, 36 | (void *) esp8266); 37 | } 38 | INIT_APP_EXPORT(esp8266_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_l610.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-10-28 zhangyang first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.l610" 14 | #include 15 | 16 | #define L610_SAMPLE_DEIVCE_NAME "l610" 17 | 18 | static struct at_device_l610 sim0 = 19 | { 20 | L610_SAMPLE_DEIVCE_NAME, 21 | L610_SAMPLE_CLIENT_NAME, 22 | 23 | L610_SAMPLE_POWER_PIN, 24 | L610_SAMPLE_STATUS_PIN, 25 | L610_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int l610_device_register(void) 29 | { 30 | struct at_device_l610 *l610 = &sim0; 31 | 32 | return at_device_register(&(l610->device), 33 | l610->device_name, 34 | l610->client_name, 35 | AT_DEVICE_CLASS_L610, 36 | (void *) l610); 37 | } 38 | INIT_APP_EXPORT(l610_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_m26.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.m26" 14 | #include 15 | 16 | #define M26_SAMPLE_DEIVCE_NAME "m0" 17 | 18 | static struct at_device_m26 m0 = 19 | { 20 | M26_SAMPLE_DEIVCE_NAME, 21 | M26_SAMPLE_CLIENT_NAME, 22 | 23 | M26_SAMPLE_POWER_PIN, 24 | M26_SAMPLE_STATUS_PIN, 25 | M26_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int m26_device_register(void) 29 | { 30 | struct at_device_m26 *m26 = &m0; 31 | 32 | return at_device_register(&(m26->device), 33 | m26->device_name, 34 | m26->client_name, 35 | AT_DEVICE_CLASS_M26_MC20, 36 | (void *) m26); 37 | } 38 | INIT_APP_EXPORT(m26_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_m5311.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-03-09 LXGMAX first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.m5311" 14 | #include 15 | 16 | /* Requirement: 17 | * AT_CMD_MAX_LEN -> 2048 18 | * RT_SERIAL_RB_BUFSZ -> 4096 19 | * M5311_SAMPLE_RECV_BUFF_LEN -> 2048 20 | */ 21 | 22 | #define M5311_SAMPLE_DEVICE_NAME "m5311" 23 | 24 | static struct at_device_m5311 nb_m5311 = { 25 | M5311_SAMPLE_DEVICE_NAME, 26 | M5311_SAMPLE_CLIENT_NAME, 27 | 28 | M5311_SAMPLE_POWER_PIN, 29 | M5311_SAMPLE_RECV_BUFF_LEN, 30 | }; 31 | 32 | static int m5311_device_register(void) 33 | { 34 | struct at_device_m5311 *m5311 = &nb_m5311; 35 | 36 | return at_device_register(&(m5311->device), 37 | m5311->device_name, 38 | m5311->client_name, 39 | AT_DEVICE_CLASS_M5311, 40 | (void *) m5311); 41 | } 42 | 43 | INIT_APP_EXPORT(m5311_device_register); 44 | -------------------------------------------------------------------------------- /samples/at_sample_m6315.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.m6315" 14 | #include 15 | 16 | #define M6315_SAMPLE_DEIVCE_NAME "m6315" 17 | 18 | static struct at_device_m6315 m6315_dev = 19 | { 20 | M6315_SAMPLE_DEIVCE_NAME, 21 | M6315_SAMPLE_CLIENT_NAME, 22 | 23 | M6315_SAMPLE_POWER_PIN, 24 | M6315_SAMPLE_STATUS_PIN, 25 | M6315_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int m6315_device_register(void) 29 | { 30 | struct at_device_m6315 *m6315 = &m6315_dev; 31 | 32 | return at_device_register(&(m6315->device), 33 | m6315->device_name, 34 | m6315->client_name, 35 | AT_DEVICE_CLASS_M6315, 36 | (void *) m6315); 37 | } 38 | INIT_APP_EXPORT(m6315_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_me3616.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-30 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.me3616" 14 | #include 15 | 16 | #define ME3616_SAMPLE_DEIVCE_NAME "me3616" 17 | 18 | static struct at_device_me3616 _dev = 19 | { 20 | ME3616_SAMPLE_DEIVCE_NAME, 21 | ME3616_SAMPLE_CLIENT_NAME, 22 | 23 | ME3616_SAMPLE_POWER_PIN, 24 | ME3616_SAMPLE_STATUS_PIN, 25 | ME3616_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int me3616_device_register(void) 29 | { 30 | struct at_device_me3616 *me3616 = &_dev; 31 | 32 | return at_device_register(&(me3616->device), 33 | me3616->device_name, 34 | me3616->client_name, 35 | AT_DEVICE_CLASS_ME3616, 36 | (void *) me3616); 37 | } 38 | INIT_APP_EXPORT(me3616_device_register); 39 | 40 | -------------------------------------------------------------------------------- /samples/at_sample_ml305.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2022-12-16 Jonas first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.ml305" 14 | #include 15 | 16 | #define ML305_SAMPLE_DEIVCE_NAME "ml3050" 17 | 18 | #ifndef ML305_SAMPLE_CLIENT_NAME 19 | #define ML305_SAMPLE_CLIENT_NAME "uart3" 20 | #endif 21 | 22 | #if !defined (ML305_SAMPLE_POWER_PIN) 23 | #define ML305_SAMPLE_POWER_PIN 0x1C 24 | #endif 25 | 26 | #if !defined (ML305_SAMPLE_STATUS_PIN) 27 | #define ML305_SAMPLE_STATUS_PIN 0x1E 28 | #endif 29 | 30 | #if !defined (ML305_SAMPLE_RECV_BUFF_LEN) 31 | #define ML305_SAMPLE_RECV_BUFF_LEN 4096 32 | #endif 33 | 34 | #if !defined (AT_DEVICE_CLASS_ML305) 35 | #define AT_DEVICE_CLASS_ML305 0xFFFFU 36 | #endif 37 | static struct at_device_ml305 ml3050 = 38 | { 39 | ML305_SAMPLE_DEIVCE_NAME, 40 | ML305_SAMPLE_CLIENT_NAME, 41 | 42 | ML305_SAMPLE_POWER_PIN, 43 | ML305_SAMPLE_STATUS_PIN, 44 | ML305_SAMPLE_RECV_BUFF_LEN, 45 | }; 46 | 47 | static int ml305_device_register(void) 48 | { 49 | struct at_device_ml305 *ml305 = &ml3050; 50 | 51 | return at_device_register(&(ml305->device), 52 | ml305->device_name, 53 | ml305->client_name, 54 | AT_DEVICE_CLASS_ML305, 55 | (void *) ml305); 56 | } 57 | INIT_APP_EXPORT(ml305_device_register); 58 | -------------------------------------------------------------------------------- /samples/at_sample_ml307.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2022-12-16 Jonas first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.ml307" 14 | #include 15 | 16 | #define ML307_SAMPLE_DEIVCE_NAME "ml3070" 17 | 18 | #define ML307_SAMPLE_CLIENT_NAME "uart2" 19 | 20 | #if !defined (ML307_SAMPLE_POWER_PIN) 21 | #define ML307_SAMPLE_POWER_PIN 0x1C 22 | #endif 23 | 24 | #if !defined (ML307_SAMPLE_STATUS_PIN) 25 | #define ML307_SAMPLE_STATUS_PIN 0x1E 26 | #endif 27 | 28 | #if !defined (ML307_SAMPLE_RECV_BUFF_LEN) 29 | #define ML307_SAMPLE_RECV_BUFF_LEN 4096 30 | #endif 31 | 32 | #if !defined (AT_DEVICE_CLASS_ML307) 33 | #define AT_DEVICE_CLASS_ML307 0xFFFFU 34 | #endif 35 | static struct at_device_ml307 ml3070 = 36 | { 37 | ML307_SAMPLE_DEIVCE_NAME, 38 | ML307_SAMPLE_CLIENT_NAME, 39 | 40 | ML307_SAMPLE_POWER_PIN, 41 | ML307_SAMPLE_STATUS_PIN, 42 | ML307_SAMPLE_RECV_BUFF_LEN, 43 | }; 44 | 45 | static int ml307_device_register(void) 46 | { 47 | struct at_device_ml307 *ml307 = &ml3070; 48 | 49 | return at_device_register(&(ml307->device), 50 | ml307->device_name, 51 | ml307->client_name, 52 | AT_DEVICE_CLASS_ML307, 53 | (void *) ml307); 54 | } 55 | INIT_APP_EXPORT(ml307_device_register); 56 | -------------------------------------------------------------------------------- /samples/at_sample_mw31.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-06-23 flybreak first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.mw31" 14 | #include 15 | 16 | #define MW31_SAMPLE_DEIVCE_NAME "mw0" 17 | 18 | static struct at_device_mw31 mw0 = 19 | { 20 | MW31_SAMPLE_DEIVCE_NAME, 21 | MW31_SAMPLE_CLIENT_NAME, 22 | 23 | MW31_SAMPLE_WIFI_SSID, 24 | MW31_SAMPLE_WIFI_PASSWORD, 25 | MW31_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int mw31_device_register(void) 29 | { 30 | struct at_device_mw31 *mw31 = &mw0; 31 | 32 | return at_device_register(&(mw31->device), 33 | mw31->device_name, 34 | mw31->client_name, 35 | AT_DEVICE_CLASS_MW31, 36 | (void *) mw31); 37 | } 38 | INIT_APP_EXPORT(mw31_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_n21.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-07 liang.shao first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample" 14 | #include 15 | 16 | #define N21_SAMPLE_DEIVCE_NAME "n21" 17 | 18 | static struct at_device_n21 sim0 = 19 | { 20 | N21_SAMPLE_DEIVCE_NAME, 21 | N21_SAMPLE_CLIENT_NAME, 22 | 23 | N21_SAMPLE_POWER_PIN, 24 | N21_SAMPLE_STATUS_PIN, 25 | N21_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int n21_device_register(void) 29 | { 30 | struct at_device_n21 *n21 = &sim0; 31 | 32 | return at_device_register(&(n21->device), 33 | n21->device_name, 34 | n21->client_name, 35 | AT_DEVICE_CLASS_N21, 36 | (void *) n21); 37 | } 38 | INIT_APP_EXPORT(n21_device_register); 39 | //MSH_CMD_EXPORT(n21_device_register,n21_device_register); 40 | -------------------------------------------------------------------------------- /samples/at_sample_n58.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2020-05-22 shuobatian first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample" 14 | #include 15 | 16 | #define N58_SAMPLE_DEIVCE_NAME "n58" 17 | 18 | static struct at_device_n58 sim0 = 19 | { 20 | N58_SAMPLE_DEIVCE_NAME, 21 | N58_SAMPLE_CLIENT_NAME, 22 | 23 | N58_SAMPLE_POWER_PIN, 24 | N58_SAMPLE_STATUS_PIN, 25 | N58_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int n58_device_register(void) 29 | { 30 | struct at_device_n58 *n58 = &sim0; 31 | 32 | return at_device_register(&(n58->device), 33 | n58->device_name, 34 | n58->client_name, 35 | AT_DEVICE_CLASS_N58, 36 | (void *) n58); 37 | } 38 | INIT_APP_EXPORT(n58_device_register); 39 | //MSH_CMD_EXPORT(n58_device_register,n58_device_register); 40 | -------------------------------------------------------------------------------- /samples/at_sample_n720.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-12-13 qiyongzhong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.n720" 14 | #include 15 | 16 | #define N720_SAMPLE_DEIVCE_NAME "n720" 17 | 18 | #ifndef N720_SAMPLE_CLIENT_NAME 19 | #define N720_SAMPLE_CLIENT_NAME "uart4" 20 | #endif 21 | 22 | #ifndef N720_SAMPLE_POWER_PIN 23 | #define N720_SAMPLE_POWER_PIN 23 24 | #endif 25 | 26 | #ifndef N720_SAMPLE_STATUS_PIN 27 | #define N720_SAMPLE_STATUS_PIN -1 28 | #endif 29 | 30 | #ifndef N720_SAMPLE_WAKEUP_PIN 31 | #define N720_SAMPLE_WAKEUP_PIN -1 32 | #endif 33 | 34 | #ifndef N720_SAMPLE_RECV_BUFF_LEN 35 | #define N720_SAMPLE_RECV_BUFF_LEN 512 36 | #endif 37 | 38 | static struct at_device_n720 _dev = 39 | { 40 | N720_SAMPLE_DEIVCE_NAME, 41 | N720_SAMPLE_CLIENT_NAME, 42 | 43 | N720_SAMPLE_POWER_PIN, 44 | N720_SAMPLE_STATUS_PIN, 45 | N720_SAMPLE_WAKEUP_PIN, 46 | N720_SAMPLE_RECV_BUFF_LEN, 47 | RT_NULL, 48 | }; 49 | 50 | static int n720_device_register(void) 51 | { 52 | struct at_device_n720 *n720 = &_dev; 53 | 54 | return at_device_register(&(n720->device), 55 | n720->device_name, 56 | n720->client_name, 57 | AT_DEVICE_CLASS_N720, 58 | (void *) n720); 59 | } 60 | INIT_APP_EXPORT(n720_device_register); 61 | 62 | -------------------------------------------------------------------------------- /samples/at_sample_rw007.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.rw007" 14 | #include 15 | 16 | #define RW007_SAMPLE_DEIVCE_NAME "r0" 17 | 18 | static struct at_device_rw007 r0 = 19 | { 20 | RW007_SAMPLE_DEIVCE_NAME, 21 | RW007_SAMPLE_CLIENT_NAME, 22 | 23 | RW007_SAMPLE_WIFI_SSID, 24 | RW007_SAMPLE_WIFI_PASSWORD, 25 | RW007_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int rw007_device_register(void) 29 | { 30 | struct at_device_rw007 *rw007 = &r0; 31 | 32 | return at_device_register(&(rw007->device), 33 | rw007->device_name, 34 | rw007->client_name, 35 | AT_DEVICE_CLASS_RW007, 36 | (void *) rw007); 37 | } 38 | INIT_APP_EXPORT(rw007_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_sim76xx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.sim76" 14 | #include 15 | 16 | #define SIM76XX_SAMPLE_DEIVCE_NAME "sim1" 17 | 18 | static struct at_device_sim76xx sim1 = 19 | { 20 | SIM76XX_SAMPLE_DEIVCE_NAME, 21 | SIM76XX_SAMPLE_CLIENT_NAME, 22 | 23 | SIM76XX_SAMPLE_POWER_PIN, 24 | SIM76XX_SAMPLE_STATUS_PIN, 25 | SIM76XX_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int sim76xx_device_register(void) 29 | { 30 | struct at_device_sim76xx *sim76xx = &sim1; 31 | 32 | return at_device_register(&(sim76xx->device), 33 | sim76xx->device_name, 34 | sim76xx->client_name, 35 | AT_DEVICE_CLASS_SIM76XX, 36 | (void *) sim76xx); 37 | } 38 | INIT_APP_EXPORT(sim76xx_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_sim800c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-13 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.sim800" 14 | #include 15 | 16 | #define SIM800C_SAMPLE_DEIVCE_NAME "sim0" 17 | 18 | static struct at_device_sim800c sim0 = 19 | { 20 | SIM800C_SAMPLE_DEIVCE_NAME, 21 | SIM800C_SAMPLE_CLIENT_NAME, 22 | 23 | SIM800C_SAMPLE_POWER_PIN, 24 | SIM800C_SAMPLE_STATUS_PIN, 25 | SIM800C_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int sim800c_device_register(void) 29 | { 30 | struct at_device_sim800c *sim800c = &sim0; 31 | 32 | return at_device_register(&(sim800c->device), 33 | sim800c->device_name, 34 | sim800c->client_name, 35 | AT_DEVICE_CLASS_SIM800C, 36 | (void *) sim800c); 37 | } 38 | INIT_APP_EXPORT(sim800c_device_register); 39 | -------------------------------------------------------------------------------- /samples/at_sample_w60x.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-10 chenyong first version 9 | */ 10 | 11 | #include 12 | 13 | #define LOG_TAG "at.sample.w60x" 14 | #include 15 | 16 | #define W60X_SAMPLE_DEIVCE_NAME "w60x0" 17 | 18 | static struct at_device_w60x w60x0 = 19 | { 20 | W60X_SAMPLE_DEIVCE_NAME, 21 | W60X_SAMPLE_CLIENT_NAME, 22 | 23 | W60X_SAMPLE_WIFI_SSID, 24 | W60X_SAMPLE_WIFI_PASSWORD, 25 | W60X_SAMPLE_RECV_BUFF_LEN, 26 | }; 27 | 28 | static int w60x_device_register(void) 29 | { 30 | struct at_device_w60x *w60x = &w60x0; 31 | 32 | return at_device_register(&(w60x->device), 33 | w60x->device_name, 34 | w60x->client_name, 35 | AT_DEVICE_CLASS_W60X, 36 | (void *) w60x); 37 | } 38 | INIT_APP_EXPORT(w60x_device_register); 39 | -------------------------------------------------------------------------------- /src/at_device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2023, RT-Thread Development Team 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Change Logs: 7 | * Date Author Notes 8 | * 2019-05-08 chenyong first version 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #define DBG_TAG "at.dev" 17 | #define DBG_LVL DBG_INFO 18 | #include 19 | 20 | /* The global list of at device */ 21 | static rt_slist_t at_device_list = RT_SLIST_OBJECT_INIT(at_device_list); 22 | /* The global list of at device class */ 23 | static rt_slist_t at_device_class_list = RT_SLIST_OBJECT_INIT(at_device_class_list); 24 | 25 | /** 26 | * This function will get the first initialized AT device. 27 | * 28 | * @return the AT device structure pointer 29 | */ 30 | struct at_device *at_device_get_first_initialized(void) 31 | { 32 | rt_base_t level; 33 | rt_slist_t *node = RT_NULL; 34 | struct at_device *device = RT_NULL; 35 | 36 | level = rt_hw_interrupt_disable(); 37 | 38 | rt_slist_for_each(node, &at_device_list) 39 | { 40 | device = rt_slist_entry(node, struct at_device, list); 41 | if (device && device->is_init == RT_TRUE) 42 | { 43 | rt_hw_interrupt_enable(level); 44 | return device; 45 | } 46 | } 47 | 48 | rt_hw_interrupt_enable(level); 49 | 50 | return RT_NULL; 51 | } 52 | 53 | /** 54 | * This function will get AT device by device name. 55 | * 56 | * @param type the name type 57 | * @param name the device name or the client name 58 | * 59 | * @return the AT device structure pointer 60 | */ 61 | struct at_device *at_device_get_by_name(int type, const char *name) 62 | { 63 | rt_base_t level; 64 | rt_slist_t *node = RT_NULL; 65 | struct at_device *device = RT_NULL; 66 | 67 | RT_ASSERT(name); 68 | 69 | level = rt_hw_interrupt_disable(); 70 | 71 | rt_slist_for_each(node, &at_device_list) 72 | { 73 | device = rt_slist_entry(node, struct at_device, list); 74 | if (device) 75 | { 76 | if (((type == AT_DEVICE_NAMETYPE_DEVICE) || (type == AT_DEVICE_NAMETYPE_NETDEV)) && 77 | (rt_strncmp(device->name, name, rt_strlen(name)) == 0)) 78 | { 79 | rt_hw_interrupt_enable(level); 80 | return device; 81 | } 82 | else if ((type == AT_DEVICE_NAMETYPE_CLIENT) && 83 | (rt_strncmp(device->client->device->parent.name, name, rt_strlen(name)) == 0)) 84 | { 85 | rt_hw_interrupt_enable(level); 86 | return device; 87 | } 88 | } 89 | } 90 | 91 | rt_hw_interrupt_enable(level); 92 | 93 | return RT_NULL; 94 | } 95 | 96 | #ifdef AT_USING_SOCKET 97 | /** 98 | * This function will get AT device by ip address. 99 | * 100 | * @param ip_addr input ip address 101 | * network 102 | * @return != NULL: network interface device object 103 | * NULL: get failed 104 | */ 105 | struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr) 106 | { 107 | rt_base_t level; 108 | rt_slist_t *node = RT_NULL; 109 | struct at_device *device = RT_NULL; 110 | 111 | level = rt_hw_interrupt_disable(); 112 | 113 | rt_slist_for_each(node, &at_device_list) 114 | { 115 | device = rt_slist_entry(node, struct at_device, list); 116 | if (device && ip_addr_cmp(ip_addr, &(device->netdev->ip_addr))) 117 | { 118 | rt_hw_interrupt_enable(level); 119 | return device; 120 | } 121 | } 122 | 123 | rt_hw_interrupt_enable(level); 124 | 125 | return RT_NULL; 126 | 127 | } 128 | #endif /* AT_USING_SOCKET */ 129 | 130 | 131 | /** 132 | * This function will perform a variety of control functions on AT devices. 133 | * 134 | * @param device the pointer of AT device structure 135 | * @param cmd the command sent to AT device 136 | * @param arg the argument of command 137 | * 138 | * @return = 0: perform successfully 139 | * < 0: perform failed 140 | */ 141 | int at_device_control(struct at_device *device, int cmd, void *arg) 142 | { 143 | if (device->class->device_ops->control) 144 | { 145 | return device->class->device_ops->control(device, cmd, arg); 146 | } 147 | else 148 | { 149 | LOG_W("AT device(%s) not support control operations.", device->name); 150 | return RT_EOK; 151 | } 152 | } 153 | 154 | /** 155 | * This function registers an AT device class with specified device class ID. 156 | * 157 | * @param class the pointer of AT device class structure 158 | * @param class_id AT device class ID 159 | * 160 | * @return 0: register successfully 161 | */ 162 | int at_device_class_register(struct at_device_class *class, uint16_t class_id) 163 | { 164 | rt_base_t level; 165 | 166 | RT_ASSERT(class); 167 | 168 | /* Fill AT device class */ 169 | class->class_id = class_id; 170 | 171 | /* Initialize current AT device class single list */ 172 | rt_slist_init(&(class->list)); 173 | 174 | level = rt_hw_interrupt_disable(); 175 | 176 | /* Add current AT device class to list */ 177 | rt_slist_append(&at_device_class_list, &(class->list)); 178 | 179 | rt_hw_interrupt_enable(level); 180 | 181 | return RT_EOK; 182 | } 183 | 184 | /* Get AT device class by client ID */ 185 | static struct at_device_class *at_device_class_get(uint16_t class_id) 186 | { 187 | rt_base_t level; 188 | rt_slist_t *node = RT_NULL; 189 | struct at_device_class *class = RT_NULL; 190 | 191 | level = rt_hw_interrupt_disable(); 192 | 193 | /* Get AT device class by class ID */ 194 | rt_slist_for_each(node, &at_device_class_list) 195 | { 196 | class = rt_slist_entry(node, struct at_device_class, list); 197 | if (class && class->class_id == class_id) 198 | { 199 | rt_hw_interrupt_enable(level); 200 | return class; 201 | } 202 | } 203 | 204 | rt_hw_interrupt_enable(level); 205 | 206 | return RT_NULL; 207 | } 208 | 209 | /** 210 | * This function registers an AT device with specified device name and AT client name. 211 | * 212 | * @param device the pointer of AT device structure 213 | * @param device_name AT device name 214 | * @param at_client_name AT device client name 215 | * @param class_id AT device class ID 216 | * @param user_data user-specific data 217 | * 218 | * @return = 0: register successfully 219 | * < 0: register failed 220 | */ 221 | int at_device_register(struct at_device *device, const char *device_name, 222 | const char *at_client_name, uint16_t class_id, void *user_data) 223 | { 224 | rt_base_t level; 225 | int result = 0; 226 | static int device_counts = 0; 227 | char name[RT_NAME_MAX] = {0}; 228 | struct at_device_class *class = RT_NULL; 229 | 230 | RT_ASSERT(device); 231 | RT_ASSERT(device_name); 232 | RT_ASSERT(at_client_name); 233 | 234 | class = at_device_class_get(class_id); 235 | if (class == RT_NULL) 236 | { 237 | LOG_E("get AT device class(%d) failed.", class_id); 238 | result = -RT_ERROR; 239 | goto __exit; 240 | } 241 | 242 | /* Fill AT device object*/ 243 | #ifdef AT_USING_SOCKET 244 | device->sockets = (struct at_socket *) rt_calloc(class->socket_num, sizeof(struct at_socket)); 245 | if (device->sockets == RT_NULL) 246 | { 247 | LOG_E("no memory for AT Socket number(%d) create.", class->socket_num); 248 | result = -RT_ENOMEM; 249 | goto __exit; 250 | } 251 | 252 | /* create AT device socket event */ 253 | rt_snprintf(name, RT_NAME_MAX, "at_se%d", device_counts++); 254 | device->socket_event = rt_event_create(name, RT_IPC_FLAG_FIFO); 255 | if (device->socket_event == RT_NULL) 256 | { 257 | LOG_E("no memory for AT device(%s) socket event create.", device_name); 258 | result = -RT_ENOMEM; 259 | goto __exit; 260 | } 261 | #endif /* AT_USING_SOCKET */ 262 | 263 | rt_memcpy(device->name, device_name, rt_strlen(device_name)); 264 | device->class = class; 265 | device->user_data = user_data; 266 | 267 | /* Initialize current AT device single list */ 268 | rt_slist_init(&(device->list)); 269 | 270 | level = rt_hw_interrupt_disable(); 271 | 272 | /* Add current AT device to device list */ 273 | rt_slist_append(&at_device_list, &(device->list)); 274 | 275 | rt_hw_interrupt_enable(level); 276 | 277 | /* Initialize AT device */ 278 | result = class->device_ops->init(device); 279 | if (result < 0) 280 | { 281 | goto __exit; 282 | } 283 | 284 | __exit: 285 | if (result < 0) 286 | { 287 | device->is_init = RT_FALSE; 288 | } 289 | else 290 | { 291 | device->is_init = RT_TRUE; 292 | } 293 | 294 | return result; 295 | } 296 | --------------------------------------------------------------------------------