at_device_rw007.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. #include <stdio.h>
  12. #include <string.h>
  13. #include <at_device_rw007.h>
  14. #define LOG_TAG "at.dev.rw007"
  15. #include <at_log.h>
  16. #ifdef AT_DEVICE_USING_RW007
  17. #define RW007_WAIT_CONNECT_TIME 5000
  18. #define RW007_THREAD_STACK_SIZE 2048
  19. #define RW007_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 2)
  20. /* ============================= rw007 network interface operations ============================= */
  21. static struct netdev *rw007_netdev_add(const char *netdev_name)
  22. {
  23. #define ETHERNET_MTU 1500
  24. #define HWADDR_LEN 6
  25. struct netdev *netdev = RT_NULL;
  26. RT_ASSERT(netdev_name);
  27. netdev = netdev_get_by_name(netdev_name);
  28. if (netdev != RT_NULL)
  29. {
  30. return (netdev);
  31. }
  32. netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev));
  33. if (netdev == RT_NULL)
  34. {
  35. return RT_NULL;
  36. }
  37. /* TODO: improve netdev adaptation */
  38. netdev->mtu = ETHERNET_MTU;
  39. netdev->hwaddr_len = HWADDR_LEN;
  40. netdev->ops = RT_NULL;
  41. #ifdef SAL_USING_AT
  42. extern int sal_at_netdev_set_pf_info(struct netdev *netdev);
  43. /* set the network interface socket/netdb operations */
  44. sal_at_netdev_set_pf_info(netdev);
  45. #endif
  46. netdev_register(netdev, netdev_name, RT_NULL);
  47. /*TODO: improve netdev adaptation */
  48. netdev_low_level_set_status(netdev, RT_TRUE);
  49. netdev_low_level_set_link_status(netdev, RT_TRUE);
  50. netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
  51. netdev->flags |= NETDEV_FLAG_INTERNET_UP;
  52. return netdev;
  53. }
  54. /* ============================= rw007 device operations ============================= */
  55. #define AT_SEND_CMD(client, resp, cmd) \
  56. do { \
  57. (resp) = at_resp_set_info((resp), 256, 0, 5 * RT_TICK_PER_SECOND); \
  58. if (at_obj_exec_cmd((client), (resp), (cmd)) < 0) \
  59. { \
  60. result = -RT_ERROR; \
  61. goto __exit; \
  62. } \
  63. } while(0) \
  64. static void rw007_init_thread_entry(void *parameter)
  65. {
  66. #define INIT_RETRY 5
  67. struct at_device *device = (struct at_device *) parameter;
  68. struct at_device_rw007 *rw007 = (struct at_device_rw007 *) device->user_data;
  69. struct at_client *client = device->client;
  70. at_response_t resp = RT_NULL;
  71. rt_err_t result = RT_EOK;
  72. rt_size_t i = 0, retry_num = INIT_RETRY;
  73. /* wait rw007 device startup finish */
  74. if (at_client_obj_wait_connect(client, RW007_WAIT_CONNECT_TIME))
  75. {
  76. return;
  77. }
  78. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  79. if (resp == RT_NULL)
  80. {
  81. LOG_E("no memory for resp create.");
  82. return;
  83. }
  84. while (retry_num--)
  85. {
  86. /* reset module */
  87. AT_SEND_CMD(client, resp, "AT+RST");
  88. /* reset waiting delay */
  89. rt_thread_mdelay(1000);
  90. /* disable echo */
  91. AT_SEND_CMD(client, resp, "ATE0");
  92. /* set current mode to Wi-Fi station */
  93. AT_SEND_CMD(client, resp, "AT+CWMODE=1");
  94. /* get module version */
  95. AT_SEND_CMD(client, resp, "AT+GMR");
  96. /* show module version */
  97. for (i = 0; i < resp->line_counts - 1; i++)
  98. {
  99. LOG_D("%s", at_resp_get_line(resp, i + 1));
  100. }
  101. /* connect to WiFi AP */
  102. if (at_obj_exec_cmd(client, at_resp_set_info(resp, 128, 0, 20 * RT_TICK_PER_SECOND),
  103. "AT+CWJAP=\"%s\",\"%s\"", rw007->wifi_ssid, rw007->wifi_password) != RT_EOK)
  104. {
  105. LOG_E("%s device wifi connect failed, check ssid(%s) and password(%s).",
  106. device->name, rw007->wifi_ssid, rw007->wifi_password);
  107. result = -RT_ERROR;
  108. goto __exit;
  109. }
  110. AT_SEND_CMD(client, resp, "AT+CIPMUX=1");
  111. /* initialize successfully */
  112. result = RT_EOK;
  113. break;
  114. __exit:
  115. if (result != RT_EOK)
  116. {
  117. rt_thread_mdelay(1000);
  118. LOG_I("%s device initialize retry...", device->name);
  119. }
  120. }
  121. if (resp)
  122. {
  123. at_delete_resp(resp);
  124. }
  125. if (result != RT_EOK)
  126. {
  127. netdev_low_level_set_status(device->netdev, RT_FALSE);
  128. LOG_E("%s device network initialize failed(%d).", device->name, result);
  129. }
  130. else
  131. {
  132. netdev_low_level_set_status(device->netdev, RT_TRUE);
  133. LOG_I("%s device network initialize success.", device->name);
  134. }
  135. }
  136. int rw007_net_init(struct at_device *device)
  137. {
  138. #ifdef AT_DEVICE_RW007_INIT_ASYN
  139. rt_thread_t tid;
  140. tid = rt_thread_create("rw007_net", rw007_init_thread_entry,
  141. (void *)device, RW007_THREAD_STACK_SIZE, RW007_THREAD_PRIORITY, 20);
  142. if (tid)
  143. {
  144. rt_thread_startup(tid);
  145. }
  146. else
  147. {
  148. LOG_E("create %s device initialization thread failed.", device->name);
  149. return -RT_ERROR;
  150. }
  151. #else
  152. rw007_init_thread_entry(device);
  153. #endif /* AT_DEVICE_RW007_INIT_ASYN */
  154. return RT_EOK;
  155. }
  156. static void urc_busy_p_func(struct at_client *client, const char *data, rt_size_t size)
  157. {
  158. LOG_D("system is processing a commands...");
  159. }
  160. static void urc_busy_s_func(struct at_client *client, const char *data, rt_size_t size)
  161. {
  162. LOG_D("system is sending data...");
  163. }
  164. static void urc_func(struct at_client *client, const char *data, rt_size_t size)
  165. {
  166. struct at_device *device = RT_NULL;
  167. char *client_name = client->device->parent.name;
  168. RT_ASSERT(client && data && size);
  169. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  170. if (device == RT_NULL)
  171. {
  172. LOG_E("get device(%s) failed.", client_name);
  173. return;
  174. }
  175. if (rt_strstr(data, "WIFI CONNECTED"))
  176. {
  177. LOG_I("%s device wifi is connected.", device->name);
  178. }
  179. else if (rt_strstr(data, "WIFI DISCONNECT"))
  180. {
  181. LOG_I("%s device wifi is disconnect.", device->name);
  182. }
  183. }
  184. static struct at_urc urc_table[] = {
  185. {"busy p", "\r\n", urc_busy_p_func},
  186. {"busy s", "\r\n", urc_busy_s_func},
  187. {"WIFI CONNECTED", "\r\n", urc_func},
  188. {"WIFI DISCONNECT", "\r\n", urc_func},
  189. };
  190. static int rw007_init(struct at_device *device)
  191. {
  192. struct at_device_rw007 *rw007 = (struct at_device_rw007 *) device->user_data;
  193. /* initialize AT client */
  194. #if RT_VER_NUM >= 0x50100
  195. at_client_init(rw007->client_name, rw007->recv_line_num, rw007->recv_line_num);
  196. #else
  197. at_client_init(rw007->client_name, rw007->recv_line_num);
  198. #endif
  199. device->client = at_client_get(rw007->client_name);
  200. if (device->client == RT_NULL)
  201. {
  202. LOG_E("get AT client(%s) failed.", rw007->client_name);
  203. return -RT_ERROR;
  204. }
  205. /* register URC data execution function */
  206. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  207. #ifdef AT_USING_SOCKET
  208. rw007_socket_init(device);
  209. #endif
  210. /* add rw007 device to the netdev list */
  211. device->netdev = rw007_netdev_add(rw007->device_name);
  212. if (device->netdev == RT_NULL)
  213. {
  214. LOG_E("get netdev(%s) failed.", rw007->device_name);
  215. return -RT_ERROR;
  216. }
  217. /* initialize rw007 device network */
  218. return rw007_net_init(device);
  219. }
  220. static int rw007_deinit(struct at_device *device)
  221. {
  222. // TODO add netdev operation
  223. device->is_init = RT_FALSE;
  224. return RT_EOK;
  225. }
  226. /* reset eap8266 device and initialize device network again */
  227. static int rw007_reset(struct at_device *device)
  228. {
  229. int result = RT_EOK;
  230. struct at_client *client = device->client;
  231. /* send "AT+RST" commonds to rw007 device */
  232. result = at_obj_exec_cmd(client, RT_NULL, "AT+RST");
  233. rt_thread_delay(1000);
  234. /* waiting 10 seconds for rw007 device reset */
  235. device->is_init = RT_FALSE;
  236. if (at_client_obj_wait_connect(client, RW007_WAIT_CONNECT_TIME))
  237. {
  238. return -RT_ETIMEOUT;
  239. }
  240. /* initialize rw007 device network */
  241. rw007_net_init(device);
  242. device->is_init = RT_TRUE;
  243. return result;
  244. }
  245. /* change eap8266 wifi ssid and password information */
  246. static int rw007_wifi_info_set(struct at_device *device, struct at_device_ssid_pwd *info)
  247. {
  248. int result = RT_EOK;
  249. struct at_response *resp = RT_NULL;
  250. if (info->ssid == RT_NULL || info->password == RT_NULL)
  251. {
  252. LOG_E("input wifi ssid(%s) and password(%s) error.", info->ssid, info->password);
  253. return -RT_ERROR;
  254. }
  255. resp = at_create_resp(128, 0, 20 * RT_TICK_PER_SECOND);
  256. if (resp == RT_NULL)
  257. {
  258. LOG_E("no memory for resp create.");
  259. return -RT_ENOMEM;
  260. }
  261. /* connect to input wifi ap */
  262. if (at_obj_exec_cmd(device->client, resp, "AT+CWJAP=\"%s\",\"%s\"", info->ssid, info->password) != RT_EOK)
  263. {
  264. LOG_E("%s device wifi connect failed, check ssid(%s) and password(%s).",
  265. device->name, info->ssid, info->password);
  266. result = -RT_ERROR;
  267. }
  268. if (resp)
  269. {
  270. at_delete_resp(resp);
  271. }
  272. return result;
  273. }
  274. static int rw007_control(struct at_device *device, int cmd, void *arg)
  275. {
  276. int result = -RT_ERROR;
  277. RT_ASSERT(device);
  278. switch (cmd)
  279. {
  280. case AT_DEVICE_CTRL_POWER_ON:
  281. case AT_DEVICE_CTRL_POWER_OFF:
  282. case AT_DEVICE_CTRL_LOW_POWER:
  283. case AT_DEVICE_CTRL_SLEEP:
  284. case AT_DEVICE_CTRL_WAKEUP:
  285. case AT_DEVICE_CTRL_NET_CONN:
  286. case AT_DEVICE_CTRL_NET_DISCONN:
  287. case AT_DEVICE_CTRL_GET_SIGNAL:
  288. case AT_DEVICE_CTRL_GET_GPS:
  289. case AT_DEVICE_CTRL_GET_VER:
  290. LOG_W("not support the control command(%d).", cmd);
  291. break;
  292. case AT_DEVICE_CTRL_RESET:
  293. result = rw007_reset(device);
  294. break;
  295. case AT_DEVICE_CTRL_SET_WIFI_INFO:
  296. result = rw007_wifi_info_set(device, (struct at_device_ssid_pwd *) arg);
  297. break;
  298. default:
  299. LOG_E("input error control command(%d).", cmd);
  300. break;
  301. }
  302. return result;
  303. }
  304. const struct at_device_ops rw007_device_ops =
  305. {
  306. rw007_init,
  307. rw007_deinit,
  308. rw007_control,
  309. };
  310. static int rw007_device_class_register(void)
  311. {
  312. struct at_device_class *class = RT_NULL;
  313. class = (struct at_device_class *) rt_calloc(1, sizeof(struct at_device_class));
  314. if (class == RT_NULL)
  315. {
  316. LOG_E("no memory for device class create.");
  317. return -RT_ENOMEM;
  318. }
  319. /* fill rw007 device class object */
  320. #ifdef AT_USING_SOCKET
  321. rw007_socket_class_register(class);
  322. #endif
  323. class->device_ops = &rw007_device_ops;
  324. return at_device_class_register(class, AT_DEVICE_CLASS_RW007);
  325. }
  326. INIT_DEVICE_EXPORT(rw007_device_class_register);
  327. #endif /* AT_DEVICE_USING_RW007 */