The FirmwareUpdater is a mbed firmware update library with HTTP server on cloud.
Dependents: FirmwareUpdater_TestProgram geigercounter04 firm LPC1768_up_frim
Revision 0:f9bdb06ab672, committed 2010-11-03
- Comitter:
- shintamainjp
- Date:
- Wed Nov 03 12:57:51 2010 +0000
- Child:
- 1:0305a8120f06
- Commit message:
- Initial version.
Changed in this revision
FirmwareUpdater.cpp | Show annotated file Show diff for this revision Revisions of this file |
FirmwareUpdater.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FirmwareUpdater.cpp Wed Nov 03 12:57:51 2010 +0000 @@ -0,0 +1,249 @@ +/** + * ============================================================================= + * Firmware updater (Version 0.0.1) + * ============================================================================= + * Copyright (c) 2010 Shinichiro Nakamura (CuBeatSystems) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================= + */ + +#include "FirmwareUpdater.h" + +#include <stdio.h> +#include <stdarg.h> + +extern "C" void mbed_reset(); + +const std::string FirmwareUpdater::EXT_BIN = ".bin"; +const std::string FirmwareUpdater::EXT_BINTMP = ".b__"; +const std::string FirmwareUpdater::EXT_TXT = ".txt"; +const std::string FirmwareUpdater::EXT_TXTTMP = ".t__"; + +/** + * Create. + * + * @param url URL for firmware. Do not include a target file name. + * @param name An application name. Do not include a extention. + * @param log True if logging. + */ +FirmwareUpdater::FirmwareUpdater(std::string url, std::string name, bool log) + : url(url), name(name), log(log), local("local") { + client.setTimeout(10000); + + /* + * A file name on the mbed local file system should keep '8 + 3' types of name. + */ + if (name.length() > 8) { + printf("Invalid firmware name '%s' found. The maximum length is 8.\n", name.c_str()); + LOG("Invalid firmware name '%s' found. The maximum length is 8.\n", name.c_str()); + } +} + +/** + * Dispose. + */ +FirmwareUpdater::~FirmwareUpdater() { +} + +/** + * Get a URL. + * + * @return URL. + */ +const std::string FirmwareUpdater:: getURL() const { + return url; +} + +/** + * Get a name. + * + * @return name. + */ +const std::string FirmwareUpdater:: getName() const { + return name; +} + +/** + * Checking a new firmware. + * Compare versions of the software between local storage on mbed and on webserver. + * + * @return Return 0 if a new firmware exists. + */ +int FirmwareUpdater::exist() { + int ver_local, ver_server; + + /* + * Fetch the version from a local. + */ + { + std::string file_local = "/local/" + name + EXT_TXT; + FILE *fp = fopen(file_local.c_str(), "rb"); + if (fp == NULL) { + LOG("Local firmware version file '%s' open failed.\n", file_local.c_str()); + return -1; + } + if (fscanf(fp, "%d", &ver_local) != 1) { + LOG("Local firmware version file '%s' is invalid.\n", file_local.c_str()); + return -2; + } + fclose(fp); + LOG("Local firmware version is %d. (%s)\n", ver_local, file_local.c_str()); + } + /* + * Fetch the version from a server. + */ + { + std::string file_server = url + "/" + name + EXT_TXT; + HTTPText text; + HTTPResult r = client.get(file_server.c_str(), &text); + if (r != HTTP_OK) { + LOG("Server firmware version file '%s' open failed.\n", file_server.c_str()); + return -3; + } + if (sscanf(text.gets(), "%d", &ver_server) != 1) { + LOG("Server firmware version file '%s' is invalid.\n", file_server.c_str()); + return -4; + } + LOG("Server firmware version is %d. (%s)\n", ver_server, file_server.c_str()); + } + + return (ver_local < ver_server) ? 0 : 1; +} + +/** + * Execute update. + * + * @return Return 0 if it succeed. + */ +int FirmwareUpdater::execute() { + /* + * Fetch the files. + */ + std::string serv_txt = url + "/" + name + EXT_TXT; + std::string serv_bin = url + "/" + name + EXT_BIN; + std::string file_txttmp = "/local/" + name + EXT_TXTTMP; + std::string file_bintmp = "/local/" + name + EXT_BINTMP; + if (fetch(serv_txt, file_txttmp) != 0) { + return -1; + } + if (fetch(serv_bin, file_bintmp) != 0) { + return -2; + } + /* + * Copy it. + */ + std::string file_txt = "/local/" + name + EXT_TXT; + std::string file_bin = "/local/" + name + EXT_BIN; + if (copy(file_txttmp, file_txt) != 0) { + return -3; + } + if (copy(file_bintmp, file_bin) != 0) { + return -4; + } + /* + * Delete the temporary files. + */ + remove(file_txttmp.c_str()); + remove(file_bintmp.c_str()); + return 0; +} + +/** + * Reset system. + */ +void FirmwareUpdater::reset() { + mbed_reset(); +} + +/** + * Fetch a file. + * + * @param src_url URL of a source file. + * @param local_file Local file name. + * + * @return Return 0 if it succeed. + */ +int FirmwareUpdater::fetch(std::string src_url, std::string local_file) { + /* + * Fetch the source file from URL to a temporary file on local. + */ + HTTPFile file(local_file.c_str()); + int r = client.get(src_url.c_str(), &file); + if (r != HTTP_OK) { + LOG("Fetch '%s' from '%s' failed.\n", local_file.c_str(), src_url.c_str()); + return -1; + } + LOG("Fetch '%s' from '%s' succeed.\n", local_file.c_str(), src_url.c_str()); + return 0; +} + +/** + * Copy a file. + * + * @param local_file1 Source file. + * @param local_file2 Destination file. + * + * @return Return 0 if it succeed. + */ +int FirmwareUpdater::copy(std::string local_file1, std::string local_file2) { + + LOG("File copying... (%s->%s)\n", local_file1.c_str(), local_file2.c_str()); + + FILE *rp = fopen(local_file1.c_str(), "rb"); + if (rp == NULL) { + LOG("File '%s' open failed.\n", local_file1.c_str()); + return -1; + } + remove(local_file2.c_str()); + FILE *wp = fopen(local_file2.c_str(), "wb"); + if (wp == NULL) { + LOG("File '%s' open failed.\n", local_file2.c_str()); + fclose(rp); + return -2; + } + int c; + while ((c = fgetc(rp)) != EOF) { + fputc(c, wp); + } + fclose(rp); + fclose(wp); + LOG("File copied. (%s->%s)\n", local_file1.c_str(), local_file2.c_str()); + return 0; +} + +/** + * Output a message to a log file. + * + * @param format ... + */ +void FirmwareUpdater::LOG(const char* format, ...) { + if (log) { + FILE *fplog = fopen("/local/update.log", "a"); + if (fplog != NULL) { + char buf[BUFSIZ]; + va_list p; + va_start(p, format); + vsnprintf(buf, sizeof(buf) - 1, format, p); + fprintf(fplog, "%s", buf); + va_end(p); + fclose(fplog); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FirmwareUpdater.h Wed Nov 03 12:57:51 2010 +0000 @@ -0,0 +1,152 @@ +/** + * ============================================================================= + * Firmware updater (Version 0.0.1) + * ============================================================================= + * Copyright (c) 2010 Shinichiro Nakamura (CuBeatSystems) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================= + */ + +#ifndef FIRMWARE_UPDATER_H +#define FIRMWARE_UPDATER_H + +#include "mbed.h" +#include "HTTPClient.h" +#include "LocalFileSystem.h" +#include <string> + +/** + * @code + * #include "mbed.h" + * #include "FirmwareUpdater.h" + * #include "EthernetNetIf.h" + * + * EthernetNetIf eth; + * FirmwareUpdater fwup("http://mbed.org/media/uploads/shintamainjp/", "firmware", true); + * + * // There are 2 files for the firmware. + * // 1. firmware.txt : firmware version file. + * // 2. firmware.bin : firmware binary file. + * + * int main() { + * eth.setup(); + * if (fwup.exist() == 0) { + * printf("Found a new firmware.\n"); + * if (fwup.execute() == 0) { + * printf("Update succeed.\n"); + * printf("Resetting this system...\n\n\n\n\n"); + * fwup.reset(); + * } else { + * printf("Update failed!\n"); + * } + * } + * } + * @endcode + */ +class FirmwareUpdater { +public: + /** + * Create. + * + * @param url URL for firmware. Do not include a target file name. + * @param name An application name. Do not include a extention. + * @param log True if logging. + */ + FirmwareUpdater(std::string url, std::string name, bool log = false); + + /** + * Dispose. + */ + ~FirmwareUpdater(); + + /** + * Get a URL. + * + * @return URL. + */ + const std::string getURL() const; + + /** + * Get a name. + * + * @return name. + */ + const std::string getName() const; + + /** + * Checking a new firmware. + * Compare versions of the software between local storage on mbed and on webserver. + * + * @return Return 0 if a new firmware exists. + */ + int exist(); + + /** + * Execute update. + * + * @return Return 0 if it succeed. + */ + int execute(); + + /** + * Reset system. + */ + void reset(); +private: + static const std::string EXT_BIN; + static const std::string EXT_BINTMP; + static const std::string EXT_TXT; + static const std::string EXT_TXTTMP; + const std::string url; + const std::string name; + const bool log; + LocalFileSystem local; + HTTPClient client; + + /** + * Fetch a file. + * + * @param src_url URL of a source file. + * @param local_file Local file name. + * + * @return Return 0 if it succeed. + */ + int fetch(std::string src_url, std::string local_file); + + /** + * Copy a file. + * + * @param local_file1 Source file. + * @param local_file2 Destination file. + * + * @return Return 0 if it succeed. + */ + int copy(std::string local_file1, std::string local_file2); + + /** + * Output a message to a log file. + * + * @param format ... + */ + void LOG(const char* format, ...); + +}; + +#endif