Software Update via Ethernet - the mbed application can pull down an updated application binary from a web server and activate that binary. This library works only with the LPC1768, as it relies on the magic-chip boot-loader mechanism.

Dependents:   WattEye X10Svr PUB_SWUpdate

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SWUpdate.h Source File

SWUpdate.h

Go to the documentation of this file.
00001 /// @file 
00002 /// Automatic Software Update via the network.
00003 ///
00004 /// Supported Platforms: mbed LPC1768.
00005 /// 
00006 /// This library provides a reasonably simple interface to updating sofware
00007 /// semi-automatically via the network. It does that by querying a web server 
00008 /// upon which you have placed an updated version of the embedded software 
00009 /// application. Upon finding something there, it will determine if it is
00010 /// a different version than the one you current have installed and it
00011 /// will try to download the software. If that succeeds, then it can
00012 /// optionally reboot to activate the new software.
00013 ///
00014 /// @code
00015 /// +-----------+
00016 /// | Compiler  |
00017 /// +-----------+
00018 ///      V                           +------------------+
00019 /// +-----------+                    |Web Server        |
00020 /// |myprog.bin |------------------->| /mbed/myprog.bin |
00021 /// +-----------+        +-----------|                  |
00022 ///                      V           |                  |
00023 ///                +-----------+     |                  |
00024 ///                |perl script|---->| /mbed/myprog.txt |
00025 ///                +-----------+     +------------------+
00026 ///                                           A
00027 /// +---------------+                         #
00028 /// |mbed appliance |<====== network =========#======...
00029 /// +---------------+
00030 ///
00031 ///     mbed                       server    
00032 ///      |                           |
00033 ///      +-- http Get(myprog.txt) -->|
00034 ///      |<-- file(myprog.txt) ------+
00035 ///      |                           |
00036 ///      |---+                       |
00037 ///      |  v58 newer than v57       |
00038 ///      |<--+                       |
00039 ///      |                           |
00040 ///      +-- http Get(myprog.bin) -->|
00041 ///      |<-- file(myprog.bin) ------+
00042 ///      |<-- file(myprog.bin) ------+
00043 ///      |<-- file(myprog.bin) ------+
00044 ///      | (save as myprog58.bin)    |
00045 ///      |                           |
00046 ///      |---+                       |
00047 ///      | integrity ck ok?          |
00048 ///      |<--+                       |
00049 ///      |                           |
00050 ///      |---+                       |
00051 ///      | unlink other .bin files   |
00052 ///      | and reboot                |
00053 ///      |<--+                       |
00054 ///      |                           |
00055 /// @endcode
00056 ///
00057 /// While the name shown in the examples here is "myprog", this is unimportant.
00058 /// Your application will have a name of your choosing, which you will 
00059 /// use in the API.
00060 ///
00061 /// @note Your binary file name should not exceed 6 characters. This leaves
00062 ///     room for a 2-digit sequence number. Since this is using the local
00063 ///     file system, it does not support long filenames when accessed from
00064 ///     the mbed. So, SomeLongFile23.bin becomes somefi~1.bin and is then 
00065 ///     erased, leaving no file.
00066 ///
00067 /// @note This was tested with firmware version 16457. Others may/not work.
00068 ///     To check your version, open the mbed.htm file in a text editor,
00069 ///     and look for "&firmware=16457&"
00070 ///
00071 /// Local File System Files:
00072 ///
00073 /// The files of interest on the local file system are as follows:
00074 ///
00075 ///   @li myprog58.bin - The actual application binary file that is currently
00076 ///             executing. In this case, this is the 58th version that
00077 ///             has been installed. You can go to 99 after which you might
00078 ///             want to start over.
00079 ///   @li myprog.ver - A text file, maintained by this software update
00080 ///             application, that was downloaded from the server with
00081 ///             application version 58. 
00082 ///
00083 /// If "myprog.ver" does not exist, it will assume that the server has a 
00084 /// newer application, so it will be downloaded and activated (even if all
00085 /// it does is to replace the existing myprog58.bin file).
00086 ///
00087 /// Web Server Files:
00088 ///
00089 /// The files on the web server are as follows. 
00090 ///
00091 ///   @li myprog.bin - The latest version of the application binary file. 
00092 ///             Note that this file does not have any version number
00093 ///             embedded into its filename as is the case on the local
00094 ///             file system.
00095 ///   @li myprog.txt - A corresponding text file. The root name must match
00096 ///             that of the binary file.
00097 ///
00098 /// The myprog.txt file shall have 3 comma-separated numbers in it.
00099 ///   version,checksum,filesize (e.g. "58,41384,107996").
00100 ///
00101 ///   @li version is a simple number. If the number is different than
00102 ///             what is stored on the local file system, then the program
00103 ///             will be updated (even if the server number is lower).
00104 ///             This bidirectional "update" can let you downgrade.
00105 ///   @li checksum is the decimal representation of a simple 16-bit checksum.
00106 ///   @li filesize is the decimal representation of the size of the file.
00107 ///
00108 /// Variations:
00109 ///
00110 ///   Within that single web server folder, you could have several apps - 
00111 ///     @li Sensor.bin, Sensor.txt
00112 ///     @li SensrB.bin, SensrB.txt
00113 ///     @li SensrD.bin, SensrD.txt
00114 ///
00115 ///   In this example, perhaps your first version was called SensorNode, but
00116 ///   with a small hardware design change, you have a new "model B" version.
00117 ///   This example also assumes that you have a need to maintain two separate
00118 ///   applications, one for each hardware version.
00119 ///
00120 /// Creating the Version and Integrity Check data:
00121 ///
00122 /// You can create the server "myprog.txt" file with this perl script (not
00123 /// every detail is shown, but it should be easy to figure out).
00124 /// @code
00125 /// # Read current .txt file
00126 /// open (FT, "<$txt") || die("Can't read $txt.");
00127 /// $ver = <FT>; chomp $ver; close FT;
00128 /// $ver =~ s/(\d+),.*/$1/;
00129 /// print "Current Version is {$ver}\n";
00130 /// 
00131 /// # Read the [assumed new] .bin file
00132 /// open (FB, "<$bin") || die("Can't read $bin.");
00133 /// binmode FB;
00134 /// while (sysread(FB, $c, 1))
00135 ///     {
00136 ///     $cksum = ($cksum + ord($c)) & 0xFFFF;
00137 ///     $byteCount++;
00138 ///     }
00139 /// close FB;
00140 /// # Advance version number and write the new .txt file
00141 /// $ver++; print "$ver Checksum is $cksum over $byteCount bytes.\n";
00142 /// open (FT, ">$txt") || die("Can't write update to $txt.");
00143 /// printf(FT "%d,%d,%d\n", $ver, $cksum,$byteCount);
00144 /// close FT;
00145 /// @endcode
00146 ///
00147 
00148 #ifndef SWUPDATE_H
00149 #define SWUPDATE_H
00150 
00151 #include "mbed.h"
00152 #include "HTTPClient.h"
00153 
00154 // This defines the maximum string length for a fully qualified
00155 // filename. Usually, this will be pretty short 
00156 // (e.g. "/local/myprog.bin"), which should be 19 max with 8.3 filename.
00157 #define SW_MAX_FQFN 20
00158 
00159 // This defines the maximum string length for the url, including
00160 // the base filename of interest.
00161 #define SW_MAX_URL 150
00162 
00163 /// After downloading, the user can choose what happens next.
00164 typedef enum {
00165     DEFER_REBOOT,   ///< Do not reboot to activate the new firmware.
00166     AUTO_REBOOT     ///< Automatically reboot to activate the new firmware.
00167 } Reboot_T;
00168 
00169 /// Value return code from the SoftwareUpdate API.
00170 ///
00171 /// Various things can go wrong in the software update process. The return
00172 /// value indicates the error.
00173 ///
00174 typedef enum {
00175     SWUP_OK               = 0x00,   ///< Software Update succeeded as planned.
00176     SWUP_SAME_VER         = 0x01,   ///< Online version is the same as the installed version.
00177     SWUP_HTTP_BIN         = 0x02,   ///< HTTP get returned an error while trying to fetch the bin file.
00178     SWUP_OLD_STUCK        = 0x03,   ///< Old file could not be removed.
00179     SWUP_VER_STUCK        = 0x04,   ///< Old version number could not be updated.
00180     SWUP_VWRITE_FAILED    = 0x05,   ///< Can't open for write the version tracking file.
00181     SWUP_INTEGRITY_FAILED = 0x06,   ///< Integrity check of downloaded file failed.
00182     SWUP_HTTP_VER         = 0x07,   ///< HTTP get returned an error while trying to fetch the version file.
00183     SWUP_NO_SPACE         = 0x08,   ///< No space on file system for new version.
00184     SWUP_NO_FILE          = 0x09,   ///< Specified file on the server does not exist
00185 } SWUpdate_T;
00186 
00187 
00188 /// To perform the software update, we simply give this API the web 
00189 /// server URL that is hosting the embedded software. We also give it 
00190 /// the "root" name of the file of interest, which permits you to
00191 /// have different applications served from the same location. 
00192 /// 
00193 /// Note that the root name can be a long filename, as is typically 
00194 /// produced from the cloud-based build process. This name will
00195 /// be truncated to the first 6 characters when installed on the
00196 /// mbed local file system, in order to retain space for a 2-digit
00197 /// version number.
00198 ///
00199 /// One optional parameter lets you decide what happens if a new 
00200 /// version is installed - automatically reboot to launch it, or
00201 /// return to the calling program which may perform a more orderly
00202 /// reboot.
00203 ///
00204 /// @code
00205 ///     ...
00206 ///     if (NowIsTheTimeToCheckForSoftwareUpdates()) {
00207 ///         if (SWUP_OK == SoftwareUpdate("http://192.168.1.200/path/to/file", "myprog_LPC1768", DEFER_REBOOT)) {
00208 ///             printf("Software updated, rebooting now...\r\n");
00209 ///             wait_ms(5000);
00210 ///             mbed_reset();
00211 ///         }
00212 ///     }
00213 ///     ...
00214 /// @endcode
00215 ///
00216 /// @param[in] url is a pointer to a text string of the url from which to download.
00217 /// @param[in] name is the base filename of the binary file.
00218 /// @param[in] action determines whether to automatically reboot to activate the new bin.
00219 /// @return SWUpdate_T code indicating if the update succeeded, otherwise it returns a bitmask
00220 ///         of failure flags. Also, note that if it succeeded, and it was set for AUTO_REBOOT
00221 ///         that it will not return from this function.
00222 ///
00223 SWUpdate_T SoftwareUpdate(const char *url, const char * name, Reboot_T action = AUTO_REBOOT);
00224 
00225 /// Get the HTTP transaction return code.
00226 ///
00227 /// If something goes wrong with the communications with the server, SoftwareUpdate will
00228 /// respond with an SWUP_HTTP_VER or SWUP_HTTP_BIN return value. To learn more about 
00229 /// what went wrong, this API will provide the actual return code from the HTTP transaction.
00230 ///
00231 /// @returns @ref HTTPResult code from the server transaction.
00232 ///
00233 HTTPResult SoftwareUpdateGetHTTPErrorCode(void);
00234 
00235 /// Get the error message from a return code
00236 ///
00237 /// @param[in] r is the result code to translate into a message
00238 /// @returns a pointer to a text string of the message
00239 ///
00240 const char * SoftwareUpdateGetHTTPErrorMsg(SWUpdate_T r);
00241 
00242 /// Get the installed software version number.
00243 ///
00244 /// If the installed version has a version number, retrieve that number and return it.
00245 ///
00246 /// @param name is the base filename of the binary file.
00247 /// @returns the installed version number, or -1 if it cannot be identified.
00248 ///
00249 int GetSoftwareVersionNumber(const char * name);
00250 
00251 #endif // SWUPDATE_H