Software over the Air (wired in this case) update. This program demonstrates the SW Update library.

Dependencies:   mbed HTTPClient SWUpdate mbed-rtos Watchdog EthernetInterface

Demonstrator for the SWUpdate Library library.

Steps to test and use it

  1. Revise the test program for your environment. The following lines may need to be changed:
    • const char *url = "http://192.168.1.201/mbed";
    • const char *name = "SWUp";
    • pc.baud(460800); fast, because I like a snappy terminal!
  2. Enable debug to monitor progress.
    • HTTPClient.cpp: Remove leading "" on line #define DEBUG "HTCL"
    • HTTPFile.cpp: Remove leading "" on line #define DEBUG "HTfi"
  3. Compile this program.
  4. Copy the bin file to the mbed (if this is the very first execution of this program).
  5. Save the bin file to an accessible web server (simplifying the filename is ok).
  6. Create the companion text file, which contains the version, checksum, and size of the binary. Save on the web server.
  7. Use a serial program (e.g. Tera Term), set for a matching baud-rate as configured in the program (e.g. 460.8K).
  8. Reset the mbed so the program runs.
    1. Program prints its startup banner, which includes the compile time date(and time) stamp.
  9. Press 's', which is the command for 's'oftware update check.
  10. SWUpdate library queries the server for the .txt file, assesses if there is a newer version.
    1. SWUpdate downloads the new version.
    2. SWUpdate compares the size and checksum to assess validity.
    3. SWUpdate removes all other .bin files if the new version is good.
  11. Reports the installation of the new version and reboots to activate it.

Sample Report - Debug Enabled

SW Update: Mar  8 2015, 16:57:43
***
Initializing network interface...
Connecting to network...
Ethernet connected as   192.168.1.119
Connected at 100 Mb/s

User now presses 's' to initiate the software update check.

SoftwareUpdateCheck (http://192.168.1.201/mbed) (SWUp)
[INF HTCL  94] url: http://192.168.1.201/mbed/SWUp.txt, timeout: 15000
[INF HTCL  88] url: http://192.168.1.201/mbed/SWUp.txt, timeout: 15000
[INF HTCL 148] connect(http://192.168.1.201/mbed/SWUp.txt,0,...,15000)
[INF HTCL 170] parse: [http://192.168.1.201/mbed/SWUp.txt]
... 

The server should have two files (of interest):

  • SWUp.bin
  • SWUp.txt First it sought the SWUp.txt file to assess if the currently installed version is old.

...
[DBG HTCL 412] Receiving data
[DBG HTCL 461] Retrieving 16 bytes
[INF HTCL 464] write 16,16: 26,3947,80472

[DBG HTCL 502] Completed HTTP transaction
...

It determines that the local version is out of date, so it prepares to pull down the newer version.

...
[INF HTfi  18] HTTPFile /local/SWUp26.BIN
[INF HTCL  88] url: http://192.168.1.201/mbed/SWUp.bin, timeout: 15000
[INF HTCL 148] connect(http://192.168.1.201/mbed/SWUp.bin,0,...,15000)
...

It forms the command to get the binary, and sends that to the server.

...
[DBG HTCL 557] send(GET /mbed/SWUp.bin HTTP/1.1
Host: 192.168.1.201:80
Connection: keep-alive
,77)
...

In response to that "GET" command, the server replies.

...
[DBG HTCL 374] Read header : Content-Length: 80472
[INF HTfi  66] setDataLen(80472)
...

Soon after this, the console shows the streaming process of pulling down the data and writing it to a file. As the data is binary, the console shows a combination of text and binary. Some of this garbage fools the terminal program (which was running in VT100 mode) into continuing to show binary.

...
[DBG HTCL 546] Read 213 bytes
[INF HTCL 464] write 213,78679: ¥àIÕ¥$à
[INF HTfi  40] write(213,¥àIÕ¥$à) m_len(80472), chunk 0
[INF HTfi  43]   writ:213, ftell: 1998
...

Eventually, we get to the end of this.

...
[INF HTfi  45] closing
[INF HTfi  24] close()
[DBG HTCL 502] Completed HTTP transaction
  Update installed, rebooting ...

And the new version is installed and activated. When the SWUpdate is working as intended, debug can be disabled.

Debug Disabled

This text is all emitted from the sample program, not the SWUpdate library, after 's' is pressed to initiate the software update check.

SoftwareUpdateCheck (http://192.168.1.201/mbed) (SWUp)
  Update installed, rebooting ...

SW Update: Mar  8 2015, 17:47:50
***
Initializing network interface...
Connecting to network...
Ethernet connected as   192.168.1.119
Connected at 100 Mb/s
Committer:
WiredHome
Date:
Sun Jul 14 01:43:17 2019 +0000
Revision:
3:2c9d1d0a89de
Parent:
1:04cb8d33b910
Minor update to clarify when selected file is missing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:a97a04fc949f 1 //
WiredHome 0:a97a04fc949f 2 // Software Update Test Program
WiredHome 0:a97a04fc949f 3 //
WiredHome 1:04cb8d33b910 4 // Mostly minimized to what is needed to demonstrate the SWUpdate library:
WiredHome 1:04cb8d33b910 5 // * EthernetInterface
WiredHome 1:04cb8d33b910 6 // * HTTPClient
WiredHome 1:04cb8d33b910 7 // * SWUpdate
WiredHome 0:a97a04fc949f 8 //
WiredHome 1:04cb8d33b910 9 // Additional items that I do not do without (but are not absolutely necessary):
WiredHome 1:04cb8d33b910 10 // * EthernetStatus - to know the state of the connection.
WiredHome 1:04cb8d33b910 11 // * Watchdog - because they are always a good idea.
WiredHome 1:04cb8d33b910 12 // * mbed-rtos - required by the EthernetInterface (I think)
WiredHome 1:04cb8d33b910 13 //
WiredHome 1:04cb8d33b910 14 //
WiredHome 1:04cb8d33b910 15 //
WiredHome 1:04cb8d33b910 16 //
WiredHome 1:04cb8d33b910 17 #include "mbed.h" // mbed: ver 95, rtos: 64
WiredHome 1:04cb8d33b910 18 #include "EthernetInterface.h" // ver 47
WiredHome 0:a97a04fc949f 19 #include "RawSerial.h" // for console i/o
WiredHome 0:a97a04fc949f 20
WiredHome 0:a97a04fc949f 21 // My custom libraries
WiredHome 0:a97a04fc949f 22 #include "HTTPClient.h" // ver 33
WiredHome 0:a97a04fc949f 23 #include "SWUpdate.h" // ver 20
WiredHome 0:a97a04fc949f 24 #include "Watchdog.h" // ver 4
WiredHome 1:04cb8d33b910 25 #include "EthStatus.h" // connection state and speed...
WiredHome 1:04cb8d33b910 26
WiredHome 1:04cb8d33b910 27 // ===================================================
WiredHome 1:04cb8d33b910 28 // SWUpdate
WiredHome 1:04cb8d33b910 29 // ===================================================
WiredHome 1:04cb8d33b910 30 // Server url to where the Software will be found.
WiredHome 1:04cb8d33b910 31 const char *url = "http://192.168.1.201/mbed";
WiredHome 1:04cb8d33b910 32
WiredHome 1:04cb8d33b910 33 // Base filename for the software (e.g. if you save it as "abcdefg.bin", use "abcdefg" here)
WiredHome 1:04cb8d33b910 34 // Remember: some servers are case-sensitive!
WiredHome 1:04cb8d33b910 35 const char *name = "SWUp";
WiredHome 1:04cb8d33b910 36 // ===================================================
WiredHome 0:a97a04fc949f 37
WiredHome 0:a97a04fc949f 38
WiredHome 0:a97a04fc949f 39
WiredHome 1:04cb8d33b910 40 // Banner that is sent to the console on reboot - shows build date/time.
WiredHome 0:a97a04fc949f 41 const char * PROG_INFO = "SW Update: " __DATE__ ", " __TIME__;
WiredHome 0:a97a04fc949f 42
WiredHome 0:a97a04fc949f 43 EthernetInterface eth;
WiredHome 0:a97a04fc949f 44 Watchdog wd;
WiredHome 0:a97a04fc949f 45
WiredHome 0:a97a04fc949f 46 RawSerial pc(USBTX, USBRX);
WiredHome 0:a97a04fc949f 47 LocalFileSystem local("local");
WiredHome 0:a97a04fc949f 48
WiredHome 0:a97a04fc949f 49 HTTPClient http;
WiredHome 0:a97a04fc949f 50
WiredHome 0:a97a04fc949f 51 extern "C" void mbed_reset();
WiredHome 0:a97a04fc949f 52
WiredHome 1:04cb8d33b910 53
WiredHome 0:a97a04fc949f 54 void SoftwareUpdateCheck(void)
WiredHome 0:a97a04fc949f 55 {
WiredHome 0:a97a04fc949f 56 pc.printf("SoftwareUpdateCheck (%s) (%s)\r\n", url, name);
WiredHome 0:a97a04fc949f 57 SWUpdate_T su = SoftwareUpdate(url, name, DEFER_REBOOT);
WiredHome 0:a97a04fc949f 58 if (SWUP_OK == su) {
WiredHome 0:a97a04fc949f 59 pc.printf(" Update installed, rebooting ...\r\n");
WiredHome 0:a97a04fc949f 60 Thread::wait(3000);
WiredHome 0:a97a04fc949f 61 mbed_reset();
WiredHome 0:a97a04fc949f 62 } else if (SWUP_SAME_VER == su) {
WiredHome 0:a97a04fc949f 63 pc.printf(" no update available.\r\n");
WiredHome 0:a97a04fc949f 64 } else {
WiredHome 3:2c9d1d0a89de 65 pc.printf(" update failed %04X - %s\r\n", (int)su, SoftwareUpdateGetHTTPErrorMsg(su));
WiredHome 0:a97a04fc949f 66 }
WiredHome 0:a97a04fc949f 67 }
WiredHome 0:a97a04fc949f 68
WiredHome 0:a97a04fc949f 69
WiredHome 1:04cb8d33b910 70 // I like to see what address it gets, and when it loses the connection.
WiredHome 0:a97a04fc949f 71 void ShowIPAddress(bool show)
WiredHome 0:a97a04fc949f 72 {
WiredHome 0:a97a04fc949f 73 char buf[16];
WiredHome 0:a97a04fc949f 74
WiredHome 0:a97a04fc949f 75 if (show)
WiredHome 0:a97a04fc949f 76 sprintf(buf, "%15s", eth.getIPAddress());
WiredHome 0:a97a04fc949f 77 else
WiredHome 0:a97a04fc949f 78 sprintf(buf, "%15s", "---.---.---.---");
WiredHome 0:a97a04fc949f 79 pc.printf("Ethernet connected as %s\r\n", buf);
WiredHome 0:a97a04fc949f 80 }
WiredHome 0:a97a04fc949f 81
WiredHome 0:a97a04fc949f 82
WiredHome 3:2c9d1d0a89de 83 void ShowMenu() {
WiredHome 3:2c9d1d0a89de 84 pc.printf("Menu:\r\n");
WiredHome 3:2c9d1d0a89de 85 pc.printf(" r - reset\r\n");
WiredHome 3:2c9d1d0a89de 86 pc.printf(" s - software update check\r\n");
WiredHome 3:2c9d1d0a89de 87 pc.printf("\r\n");
WiredHome 3:2c9d1d0a89de 88 }
WiredHome 3:2c9d1d0a89de 89
WiredHome 1:04cb8d33b910 90 // Only 2 items in this menu - check for software updates and reset!
WiredHome 0:a97a04fc949f 91 void CheckConsoleInput(void)
WiredHome 0:a97a04fc949f 92 {
WiredHome 0:a97a04fc949f 93 if (pc.readable()) {
WiredHome 0:a97a04fc949f 94 int c = pc.getc();
WiredHome 0:a97a04fc949f 95 switch (c) {
WiredHome 0:a97a04fc949f 96 case 'r':
WiredHome 0:a97a04fc949f 97 mbed_reset();
WiredHome 0:a97a04fc949f 98 break;
WiredHome 0:a97a04fc949f 99 case 's':
WiredHome 0:a97a04fc949f 100 SoftwareUpdateCheck();
WiredHome 0:a97a04fc949f 101 break;
WiredHome 0:a97a04fc949f 102 default:
WiredHome 0:a97a04fc949f 103 pc.printf("unknown command '%c'\r\n", c);
WiredHome 3:2c9d1d0a89de 104 ShowMenu();
WiredHome 0:a97a04fc949f 105 break;
WiredHome 0:a97a04fc949f 106 }
WiredHome 0:a97a04fc949f 107 }
WiredHome 0:a97a04fc949f 108 }
WiredHome 0:a97a04fc949f 109
WiredHome 1:04cb8d33b910 110 // Friendlier interface to find out if it is currently connected.
WiredHome 0:a97a04fc949f 111 bool NetworkIsConnected(void)
WiredHome 0:a97a04fc949f 112 {
WiredHome 0:a97a04fc949f 113 return get_link_status();
WiredHome 0:a97a04fc949f 114 }
WiredHome 0:a97a04fc949f 115
WiredHome 0:a97a04fc949f 116
WiredHome 0:a97a04fc949f 117 int main()
WiredHome 0:a97a04fc949f 118 {
WiredHome 1:04cb8d33b910 119 pc.baud(460800); // fast, because I like a snappy terminal!
WiredHome 0:a97a04fc949f 120 pc.printf("\r\n%s\r\n", PROG_INFO);
WiredHome 0:a97a04fc949f 121
WiredHome 0:a97a04fc949f 122 if (wd.WatchdogCausedReset()) {
WiredHome 0:a97a04fc949f 123 pc.printf("**** Watchdog Event caused reset ****\r\n");
WiredHome 0:a97a04fc949f 124 }
WiredHome 1:04cb8d33b910 125 wd.Configure(30.0); // nothing should take more than 30 s (we hope).
WiredHome 0:a97a04fc949f 126
WiredHome 0:a97a04fc949f 127 pc.printf("***\r\n");
WiredHome 0:a97a04fc949f 128 pc.printf("Initializing network interface...\r\n");
WiredHome 0:a97a04fc949f 129 if (0 == eth.init()) { //Use DHCP
WiredHome 0:a97a04fc949f 130 do {
WiredHome 0:a97a04fc949f 131 pc.printf("Connecting to network...\r\n");
WiredHome 0:a97a04fc949f 132 if (0 == eth.connect()) {
WiredHome 0:a97a04fc949f 133 ShowIPAddress(true);
WiredHome 0:a97a04fc949f 134 int speed = get_connection_speed();
WiredHome 0:a97a04fc949f 135 pc.printf("Connected at %d Mb/s\r\n", speed);
WiredHome 3:2c9d1d0a89de 136 ShowMenu();
WiredHome 0:a97a04fc949f 137 while (NetworkIsConnected()) {
WiredHome 0:a97a04fc949f 138 Thread::wait(500);
WiredHome 0:a97a04fc949f 139 CheckConsoleInput();
WiredHome 0:a97a04fc949f 140 wd.Service();
WiredHome 0:a97a04fc949f 141 }
WiredHome 0:a97a04fc949f 142 pc.printf("lost connection.\r\n");
WiredHome 0:a97a04fc949f 143 ShowIPAddress(false);
WiredHome 0:a97a04fc949f 144 eth.disconnect();
WiredHome 0:a97a04fc949f 145 }
WiredHome 0:a97a04fc949f 146 else {
WiredHome 0:a97a04fc949f 147 pc.printf(" ... failed to connect.\r\n");
WiredHome 0:a97a04fc949f 148 }
WiredHome 0:a97a04fc949f 149 CheckConsoleInput();
WiredHome 0:a97a04fc949f 150 }
WiredHome 0:a97a04fc949f 151 while (1);
WiredHome 0:a97a04fc949f 152 }
WiredHome 0:a97a04fc949f 153 else {
WiredHome 0:a97a04fc949f 154 pc.printf(" ... failed to initialize, rebooting...\r\n");
WiredHome 0:a97a04fc949f 155 mbed_reset();
WiredHome 0:a97a04fc949f 156 }
WiredHome 0:a97a04fc949f 157 }