Hi,
I haven't ran the FOTA download library in a while and I was just testing it. I don't seem to be getting any of the FOTA_DOWNLOAD_EVT events. I am running nRF SDK v1.2.1. I also have the LWM2M carrier library running, not sure if that affects this at all.
Normally I use the success event (FOTA_DOWNLOAD_EVT_FINISHED) to trigger a system reboot. However, this event is not firing and thus I can't trigger the reboot.
I also just ran and got a failure because it couldn't open a socket. Which I normally handle by reporting to another connected device that the update has failed, however, that event also isn't firing.
I have attached my source code that uses the fota_download library.
Here are the logs during an error:
[00:00:11.617,065] <inf> download_client: Attempting to connect over IPv4
[00:00:11.761,932] <inf> download_client: Connected to <hidden>
[00:00:11.771,331] <inf> download_client: Downloading: modem-fw/mfw_nrf9160_update_from_1.1.1_to_1.1.2.bin [0]
[00:00:12.075,683] <wrn> download_client: Copying 280 payload bytes
[00:00:13.077,453] <inf> download_client: Downloaded 4096/14822 bytes (27%)
[00:00:13.085,174] <err> dfu_target_modem: Failed to open Modem DFU socket.
[00:00:13.093,078] <err> fota_download: dfu_target_init error -1
[00:00:13.100,036] <inf> download_client: Fragment refused, download stopped.
Does the LWM2M carrier library running cause any issues with the fota_download library? I did get a successful update but for some reason the events didn't fire.
Thanks,
Jack
/* modem_upgrade.c Implement Modem FW Upgrade */ #include <zephyr.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <net/fota_download.h> #include <modem_info.h> #include <dfu/mcuboot.h> #include <hal/nrf_regulators.h> #include "modem_upgrade.h" #include "cloud.h" #include "uart_comm.h" #include "cmd.h" // Variables ========================================================== static struct k_delayed_work fota_work; static struct download_client dlc; static char fw_host[HTTP_HEADER_SIZE]; static char fw_file[HTTP_HEADER_SIZE]; // Internal Function Prototypes ====================================== static void fota_dl_handler(enum fota_download_evt_id evt_id); static void modem_fota_work(struct k_work *unused); static int check_for_fw_update(char* apiHost, char* apiVersion); static void parse_fota_response(char* fotaResponse, int* upgradeAvailable, char* fwHost, char* fwFile, char* responseCode); static void parse_http_header(char *input, char *key, char *value); // Public Functions ================================================== int MODEM_UPGRADE_init(void) { printf("Initializing modem FOTA\n"); k_work_init(&fota_work, modem_fota_work); int err = fota_download_init(fota_dl_handler); if (err != 0) { printf("Error initializing fota download: %d\n", err); } err = modem_info_init(); if (err != 0) { printf("Error initializing modem info: %d\n", err); } printf("Modem FOTA Initialized\n"); return 0; } int MODEM_UPGRADE_check_for_upgrade(char* dcdApiHost, char* apiVersion) { int response = check_for_fw_update(dcdApiHost, apiVersion); if (response == 1) { printf("Modem FW Upgrade available...\n"); return 1; } else if (response == 0) { printf("No Modem FW Upgrade available...\n"); CLOUD_lteOff(); return 0; } else { CLOUD_lteOff(); return -1; } } int MODEM_UPGRADE_do_upgrade(void) { printf("Running modem FOTA\n"); k_work_submit(&fota_work); return 0; } int MODEM_UPGRADE_get_version(char* modemVersion) { char buffer[MODEM_VERSION_MAX_LENGTH]; int length = modem_info_string_get(MODEM_INFO_FW_VERSION, buffer); memcpy(modemVersion, buffer, length); modemVersion[length] = '\0'; return 0; } // Private Functions =================================================== static void fota_dl_handler(enum fota_download_evt_id evt_id) { switch (evt_id) { case FOTA_DOWNLOAD_EVT_ERROR: printf("Received error from fota_download\n"); UART_sendMessage(MSG_CMD_MODEM_FOTA_FAILED, NULL, 0); break; case FOTA_DOWNLOAD_EVT_FINISHED: printf("FOTA download complete. rebooting...\n"); sys_reboot(0); break; default: break; } } static void modem_fota_work(struct k_work *unused) { int retval; retval = fota_download_start(fw_host, fw_file); if (retval != 0) { printf("fota_download_start() failed, err %d\n", retval); } } static int check_for_fw_update(char* apiHost, char* apiVersion) { char fwVersion[MODEM_VERSION_MAX_LENGTH]; MODEM_UPGRADE_get_version(fwVersion); char request_buffer[HTTP_BUFF_SIZE]; char response_buffer[HTTP_BUFF_SIZE]; char response_code[4]; int usedSize = sprintf(request_buffer, "GET /api/%s/modem/fota HTTP/1.1\r\n" "Host: %s\r\n" "modem-fw-version: %s\r\n" "Connection: close\r\n\r\n", apiVersion, apiHost, fwVersion); CLOUD_lteConnect(); CLOUD_sendHttpRequest(apiHost, request_buffer, response_buffer, HTTP_BUFF_SIZE); int upgradeAvailable = 0; parse_fota_response(response_buffer, &upgradeAvailable, fw_host, fw_file, response_code); if (strcmp(response_code, "200")) { printf("Check for modem FOTA request failed: HTTP %s\n", response_code); return -1; } return upgradeAvailable; } char *strtok(char * str, const char * delim) { static char* p=0; if(str) p=str; else if(!p) return 0; str=p+strspn(p,delim); p=str+strcspn(str,delim); if(p==str) return p=0; p = *p ? *p=0,p+1 : 0; return str; } static void parse_fota_response(char* fotaResponse, int* upgradeAvailable, char* fwHost, char* fwFile, char* responseCode) { char headerKey[HTTP_HEADER_SIZE]; char headerValue[HTTP_HEADER_SIZE]; char *token = NULL; token = strtok(fotaResponse, "\r\n"); while(token) { parse_http_header(token, headerKey, headerValue); if (!strcmp(headerKey, "upgrade-available")) { u8_t b = headerValue[0]; b = b - '0'; *upgradeAvailable = b; } if (!strcmp(headerKey, "fw-host")) { strcpy(fwHost, headerValue); } if (!strcmp(headerKey, "fw-file")) { strcpy(fwFile, headerValue); } if (strstr(headerKey, "HTTP/1.1")) { strncpy(responseCode, headerKey + 9, 3); responseCode[3] = '\0'; } token = strtok(NULL, "\r\n"); if (token == " ") { token = NULL; } } } static void parse_http_header(char *input, char *key, char *value) { int colonReached = 0; int j = 0; int i = 0; for (i = 0; i < strlen(input); i++) { if (input[i] == ':') { colonReached = 1; key[i] = '\0'; i += 2; // skip the colon and the space seperating key: value } if (colonReached) { // start parsing the value with new index at 0 value[j] = input[i]; j++; } else { // parse the key until we hit a colon & space ': ' key[i] = input[i]; } } // If we don't hit a colon, then just add a null terminator on the key if (!colonReached) { key[i] = '\0'; } value[j] = '\0'; }