Advertisement
Guest User

Untitled

a guest
Jun 24th, 2018
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.20 KB | None | 0 0
  1. /* OTA example
  2.  
  3. This example code is in the Public Domain (or CC0 licensed, at your option.)
  4.  
  5. Unless required by applicable law or agreed to in writing, this
  6. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  7. CONDITIONS OF ANY KIND, either express or implied.
  8. */
  9. #include <string.h>
  10. #include <sys/socket.h>
  11. #include <netdb.h>
  12.  
  13.  
  14. #include <stdlib.h>
  15.  
  16. #include "freertos/FreeRTOS.h"
  17. #include "freertos/task.h"
  18. #include "freertos/event_groups.h"
  19.  
  20. #include "esp_system.h"
  21. #include "esp_wifi.h"
  22. #include "esp_event_loop.h"
  23. #include "esp_log.h"
  24. #include "esp_ota_ops.h"
  25.  
  26. #include "nvs.h"
  27. #include "nvs_flash.h"
  28.  
  29. #include "lwip/err.h"
  30. #include "lwip/sockets.h"
  31. #include "lwip/sys.h"
  32. #include "lwip/netdb.h"
  33. #include "lwip/dns.h"
  34.  
  35. #include "esp_tls.h"
  36. //#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
  37. //#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
  38.  
  39.  
  40. #define EXAMPLE_WIFI_SSID "SecureUpdate"
  41. #define EXAMPLE_WIFI_PASS "EmsecExercise42018"
  42.  
  43. #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP
  44. #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT
  45. #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME
  46. #define BUFFSIZE 1024
  47. #define TEXT_BUFFSIZE 1024
  48.  
  49. /*************************************************************************************/
  50.  
  51. /* Constants that aren't configurable in menuconfig */
  52. #define WEB_SERVER "emsec.cispa.saarland"
  53. #define WEB_PORT "443"
  54. #define WEB_URL "https://emsec.cispa.saarland/files/image.bin"
  55.  
  56. //static const char *TAG = "example";
  57.  
  58. static const char *REQUEST = "GET " WEB_URL " HTTP/1.0\r\n"
  59. "Host: "WEB_SERVER"\r\n"
  60. "User-Agent: esp-idf/1.0 esp32\r\n"
  61. "\r\n";
  62.  
  63. /* Root cert for howsmyssl.com, taken from server_root_cert.pem
  64.  
  65. The PEM file was extracted from the output of this command:
  66. openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
  67.  
  68. The CA root cert is the last cert given in the chain of certs.
  69.  
  70. To embed it in the app binary, the PEM file is named
  71. in the component.mk COMPONENT_EMBED_TXTFILES variable.
  72. */
  73. extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start");
  74. extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end");
  75. /*************************************************************************************/
  76.  
  77. static const char *TAG = "ota";
  78. /*an ota data write buffer ready to write to the flash*/
  79. static char ota_write_data[BUFFSIZE + 1] = { 0 };
  80. /*an packet receive buffer*/
  81. static char text[BUFFSIZE + 1] = { 0 };
  82. /* an image total length*/
  83. static int binary_file_length = 0;
  84. /*socket id*/
  85. static int socket_id = -1;
  86.  
  87. /* FreeRTOS event group to signal when we are connected & ready to make a request */
  88. static EventGroupHandle_t wifi_event_group;
  89.  
  90. /* The event group allows multiple bits for each event,
  91. but we only care about one event - are we connected
  92. to the AP with an IP? */
  93. const int CONNECTED_BIT = BIT0;
  94.  
  95. static esp_err_t event_handler(void *ctx, system_event_t *event)
  96. {
  97. switch (event->event_id) {
  98. case SYSTEM_EVENT_STA_START:
  99. esp_wifi_connect();
  100. break;
  101. case SYSTEM_EVENT_STA_GOT_IP:
  102. xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
  103. break;
  104. case SYSTEM_EVENT_STA_DISCONNECTED:
  105. /* This is a workaround as ESP32 WiFi libs don't currently
  106. auto-reassociate. */
  107. esp_wifi_connect();
  108. xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
  109. break;
  110. default:
  111. break;
  112. }
  113. return ESP_OK;
  114. }
  115.  
  116. static void initialise_wifi(void)
  117. {
  118. tcpip_adapter_init();
  119. wifi_event_group = xEventGroupCreate();
  120. ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
  121. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  122. ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
  123. ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
  124. wifi_config_t wifi_config = {
  125. .sta = {
  126. .ssid = EXAMPLE_WIFI_SSID,
  127. .password = EXAMPLE_WIFI_PASS,
  128. },
  129. };
  130. ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
  131. ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
  132. ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
  133. ESP_ERROR_CHECK( esp_wifi_start() );
  134. }
  135.  
  136. /*read buffer by byte still delim ,return read bytes counts*/
  137. static int read_until(char *buffer, char delim, int len)
  138. {
  139. // /*TODO: delim check,buffer check,further: do an buffer length limited*/
  140. int i = 0;
  141. while (buffer[i] != delim && i < len) {
  142. ++i;
  143. }
  144. return i + 1;
  145. }
  146.  
  147. /* resolve a packet from http socket
  148. * return true if packet including \r\n\r\n that means http packet header finished,start to receive packet body
  149. * otherwise return false
  150. * */
  151. static bool read_past_http_header(char text[], int total_len, esp_ota_handle_t update_handle)
  152. {
  153. /* i means current position */
  154. int i = 0, i_read_len = 0;
  155. while (text[i] != 0 && i < total_len) {
  156. i_read_len = read_until(&text[i], '\n', total_len);
  157. // if we resolve \r\n line,we think packet header is finished
  158. if (i_read_len == 2) {
  159. int i_write_len = total_len - (i + 2);
  160. memset(ota_write_data, 0, BUFFSIZE);
  161. /*copy first http packet body to write buffer*/
  162. memcpy(ota_write_data, &(text[i + 2]), i_write_len);
  163.  
  164. esp_err_t err = esp_ota_write( update_handle, (const void *)ota_write_data, i_write_len);
  165. if (err != ESP_OK) {
  166. ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err));
  167. return false;
  168. } else {
  169. ESP_LOGI(TAG, "esp_ota_write header OK");
  170. binary_file_length += i_write_len;
  171. }
  172. return true;
  173. }
  174. i += i_read_len;
  175. }
  176. return false;
  177. }
  178.  
  179. static bool connect_to_http_server()
  180. {
  181. char buf[512];
  182. int ret, len;
  183. /*
  184. ESP_LOGI(TAG, "Server IP: %s Server Port:%s", EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT);
  185.  
  186. int http_connect_flag = -1;
  187. struct sockaddr_in sock_info;
  188.  
  189. socket_id = socket(AF_INET, SOCK_STREAM, 0);
  190. if (socket_id == -1) {
  191. ESP_LOGE(TAG, "Create socket failed!");
  192. return false;
  193. }
  194.  
  195. // set connect info
  196. memset(&sock_info, 0, sizeof(struct sockaddr_in));
  197. sock_info.sin_family = AF_INET;
  198. sock_info.sin_addr.s_addr = inet_addr(EXAMPLE_SERVER_IP);
  199. sock_info.sin_port = htons(atoi(EXAMPLE_SERVER_PORT));
  200.  
  201. */
  202.  
  203. /*************************************************************************************/
  204. int cipher_list[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0};
  205. mbedtls_ssl_conf_ciphersuites(&conf, cipher_list);
  206.  
  207. esp_tls_cfg_t cfg = {
  208. .cacert_pem_buf = server_root_cert_pem_start,
  209. .cacert_pem_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
  210. };
  211.  
  212. struct esp_tls *tls = esp_tls_conn_http_new(WEB_URL, &cfg);
  213.  
  214. if(tls != NULL) {
  215. ESP_LOGI(TAG, "Connection established...");
  216. } else {
  217. ESP_LOGE(TAG, "Connection failed...");
  218. goto exit;
  219. }
  220.  
  221. size_t written_bytes = 0;
  222. do {
  223. ret = esp_tls_conn_write(tls,
  224. REQUEST + written_bytes,
  225. strlen(REQUEST) - written_bytes);
  226. if (ret >= 0) {
  227. ESP_LOGI(TAG, "%d bytes written", ret);
  228. written_bytes += ret;
  229. } else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
  230. ESP_LOGE(TAG, "esp_tls_conn_write returned 0x%x", ret);
  231. goto exit;
  232. }
  233. } while(written_bytes < strlen(REQUEST));
  234.  
  235. ESP_LOGI(TAG, "Reading HTTP response...");
  236.  
  237. do
  238. {
  239. len = sizeof(buf) - 1;
  240. bzero(buf, sizeof(buf));
  241. ret = esp_tls_conn_read(tls, (char *)buf, len);
  242.  
  243. if(ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ)
  244. continue;
  245.  
  246. if(ret < 0)
  247. {
  248. ESP_LOGE(TAG, "esp_tls_conn_read returned -0x%x", -ret);
  249. break;
  250. }
  251.  
  252. if(ret == 0)
  253. {
  254. ESP_LOGI(TAG, "connection closed");
  255. break;
  256. }
  257.  
  258. len = ret;
  259. ESP_LOGD(TAG, "%d bytes read", len);
  260. /* Print response directly to stdout as it is read */
  261. for(int i = 0; i < len; i++) {
  262. putchar(buf[i]);
  263. }
  264. } while(1);
  265.  
  266. exit:
  267. esp_tls_conn_delete(tls);
  268. putchar('\n'); // JSON output doesn't have a newline at end
  269.  
  270. static int request_count;
  271. ESP_LOGI(TAG, "Completed %d requests", ++request_count);
  272.  
  273. for(int countdown = 10; countdown >= 0; countdown--) {
  274. ESP_LOGI(TAG, "%d...", countdown);
  275. vTaskDelay(1000 / portTICK_PERIOD_MS);
  276. }
  277. ESP_LOGI(TAG, "Starting again!");
  278. return true;
  279. }
  280.  
  281. /*************************************************************************************/
  282.  
  283. /*
  284. // connect to http server
  285. http_connect_flag = connect(socket_id, (struct sockaddr *)&sock_info, sizeof(sock_info));
  286. if (http_connect_flag == -1) {
  287. ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno);
  288. close(socket_id);
  289. return false;
  290. } else {
  291. ESP_LOGI(TAG, "Connected to server");
  292. return true;
  293. }
  294. return false;
  295. */
  296.  
  297. static void __attribute__((noreturn)) task_fatal_error()
  298. {
  299. ESP_LOGE(TAG, "Exiting task due to fatal error...");
  300. close(socket_id);
  301. (void)vTaskDelete(NULL);
  302.  
  303. while (1) {
  304. ;
  305. }
  306. }
  307.  
  308. static void ota_example_task(void *pvParameter)
  309. {
  310. esp_err_t err;
  311. /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
  312. esp_ota_handle_t update_handle = 0 ;
  313. const esp_partition_t *update_partition = NULL;
  314.  
  315. ESP_LOGI(TAG, "Starting OTA example...");
  316.  
  317. const esp_partition_t *configured = esp_ota_get_boot_partition();
  318. const esp_partition_t *running = esp_ota_get_running_partition();
  319.  
  320. if (configured != running) {
  321. ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
  322. configured->address, running->address);
  323. ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
  324. }
  325. ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
  326. running->type, running->subtype, running->address);
  327.  
  328. /* Wait for the callback to set the CONNECTED_BIT in the
  329. event group.
  330. */
  331. xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
  332. false, true, portMAX_DELAY);
  333. ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server....");
  334.  
  335. /*connect to http server*/
  336. if (connect_to_http_server()) {
  337. ESP_LOGI(TAG, "Connected to http server");
  338. } else {
  339. ESP_LOGE(TAG, "Connect to http server failed!");
  340. task_fatal_error();
  341. }
  342.  
  343. /*send GET request to http server*/
  344. const char *GET_FORMAT =
  345. "GET %s HTTP/1.0\r\n"
  346. "Host: %s:%s\r\n"
  347. "User-Agent: esp-idf/1.0 esp32\r\n\r\n";
  348.  
  349. char *http_request = NULL;
  350. int get_len = asprintf(&http_request, GET_FORMAT, EXAMPLE_FILENAME, EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT);
  351. if (get_len < 0) {
  352. ESP_LOGE(TAG, "Failed to allocate memory for GET request buffer");
  353. task_fatal_error();
  354. }
  355. int res = send(socket_id, http_request, get_len, 0);
  356. free(http_request);
  357.  
  358. if (res < 0) {
  359. ESP_LOGE(TAG, "Send GET request to server failed");
  360. task_fatal_error();
  361. } else {
  362. ESP_LOGI(TAG, "Send GET request to server succeeded");
  363. }
  364.  
  365. update_partition = esp_ota_get_next_update_partition(NULL);
  366. ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
  367. update_partition->subtype, update_partition->address);
  368. assert(update_partition != NULL);
  369.  
  370. err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
  371. if (err != ESP_OK) {
  372. ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
  373. task_fatal_error();
  374. }
  375. ESP_LOGI(TAG, "esp_ota_begin succeeded");
  376.  
  377. bool resp_body_start = false, socket_flag = true, http_200_flag = false;
  378. /*deal with all receive packet*/
  379. while (socket_flag) {
  380. memset(text, 0, TEXT_BUFFSIZE);
  381. memset(ota_write_data, 0, BUFFSIZE);
  382. int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0);
  383. if (buff_len < 0) { /*receive error*/
  384. ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno);
  385. task_fatal_error();
  386. } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/
  387. // only start ota when server response 200 state code
  388. if (strstr(text, "200") == NULL && !http_200_flag) {
  389. ESP_LOGE(TAG, "ota url is invalid or bin is not exist");
  390. task_fatal_error();
  391. }
  392. http_200_flag = true;
  393. memcpy(ota_write_data, text, buff_len);
  394. resp_body_start = read_past_http_header(text, buff_len, update_handle);
  395. } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/
  396. memcpy(ota_write_data, text, buff_len);
  397. err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len);
  398. if (err != ESP_OK) {
  399. ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err));
  400. task_fatal_error();
  401. }
  402. binary_file_length += buff_len;
  403. ESP_LOGI(TAG, "Have written image length %d", binary_file_length);
  404. } else if (buff_len == 0) { /*packet over*/
  405. socket_flag = false;
  406. ESP_LOGI(TAG, "Connection closed, all packets received");
  407. close(socket_id);
  408. } else {
  409. ESP_LOGE(TAG, "Unexpected recv result");
  410. }
  411. }
  412.  
  413. ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length);
  414.  
  415. if (esp_ota_end(update_handle) != ESP_OK) {
  416. ESP_LOGE(TAG, "esp_ota_end failed!");
  417. task_fatal_error();
  418. }
  419. err = esp_ota_set_boot_partition(update_partition);
  420. if (err != ESP_OK) {
  421. ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
  422. task_fatal_error();
  423. }
  424. ESP_LOGI(TAG, "Prepare to restart system!");
  425. esp_restart();
  426. return ;
  427. }
  428.  
  429. void app_main()
  430. {
  431. // Initialize NVS.
  432. esp_err_t err = nvs_flash_init();
  433. if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
  434. // OTA app partition table has a smaller NVS partition size than the non-OTA
  435. // partition table. This size mismatch may cause NVS initialization to fail.
  436. // If this happens, we erase NVS partition and initialize NVS again.
  437. ESP_ERROR_CHECK(nvs_flash_erase());
  438. err = nvs_flash_init();
  439. }
  440. ESP_ERROR_CHECK( err );
  441.  
  442. initialise_wifi();
  443. xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
  444. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement