Download NHK English news podcast automatically. XML Parser "spxml" is used. This application requires mpod mother board. See also http://mbed.org/users/geodenx/notebook/mpod/
Dependencies: BlinkLed HTTPClient EthernetInterface FatFileSystemCpp MSCFileSystem spxml mbed-rtos mbed
Fork of mpod_nhk_english by
Download NHK English news podcast automatically.
XML Parser "spxml" is used.
This application requires mpod mother board.
See also http://mbed.org/users/geodenx/notebook/mpod/
main.cpp@5:e87211ff9c23, 2012-08-20 (annotated)
- Committer:
- togayan
- Date:
- Mon Aug 20 13:50:00 2012 +0000
- Revision:
- 5:e87211ff9c23
- Parent:
- 4:7dae52cf560f
- Child:
- 6:84749589b532
Refactoring
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
togayan | 0:1855a008f28e | 1 | #include "mbed.h" |
togayan | 0:1855a008f28e | 2 | #include "MSCFileSystem.h" |
togayan | 0:1855a008f28e | 3 | #include "EthernetInterface.h" |
togayan | 0:1855a008f28e | 4 | #include "HTTPClient.h" |
togayan | 0:1855a008f28e | 5 | #include "HTTPFile.h" |
togayan | 0:1855a008f28e | 6 | #include "BlinkLed.h" |
togayan | 4:7dae52cf560f | 7 | #include "spdomparser.hpp" |
togayan | 4:7dae52cf560f | 8 | #include "spxmlnode.hpp" |
togayan | 4:7dae52cf560f | 9 | #include "spxmlhandle.hpp" |
togayan | 0:1855a008f28e | 10 | |
togayan | 0:1855a008f28e | 11 | int GetFile(const char *path, const char *url); |
togayan | 0:1855a008f28e | 12 | |
togayan | 0:1855a008f28e | 13 | EthernetInterface eth; |
togayan | 0:1855a008f28e | 14 | HTTPClient http; |
togayan | 0:1855a008f28e | 15 | MSCFileSystem usb("usb"); |
togayan | 3:07562878d3c3 | 16 | BlinkLed led1(LED1, 0.02); |
togayan | 3:07562878d3c3 | 17 | BlinkLed led2(LED2, 0.2); |
togayan | 3:07562878d3c3 | 18 | BlinkLed ethGreen(p26, 0.02); |
togayan | 3:07562878d3c3 | 19 | BlinkLed ethYellow(p25, 0.2); |
togayan | 0:1855a008f28e | 20 | DigitalOut fsusb30s(p9); |
togayan | 0:1855a008f28e | 21 | Timer timer; |
togayan | 0:1855a008f28e | 22 | |
togayan | 0:1855a008f28e | 23 | const char* rssUrl = "http://www3.nhk.or.jp/rj/podcast/rss/english.xml"; |
togayan | 0:1855a008f28e | 24 | const char* rssPath = "/usb/english.xml"; |
togayan | 0:1855a008f28e | 25 | const char* mp3Path = "/usb/english.mp3"; |
togayan | 0:1855a008f28e | 26 | |
togayan | 0:1855a008f28e | 27 | int main() |
togayan | 0:1855a008f28e | 28 | { |
togayan | 5:e87211ff9c23 | 29 | printf("\n\n===========================================\n"); |
togayan | 5:e87211ff9c23 | 30 | printf("mpod NHK English news Downloader with spxml\n"); |
togayan | 5:e87211ff9c23 | 31 | printf("===========================================\n\n"); |
togayan | 0:1855a008f28e | 32 | |
togayan | 0:1855a008f28e | 33 | // FSUSB30 switches to HSD1 (mbed) |
togayan | 1:1637e625b21b | 34 | printf("USB host was switched to HSD1(mbed).\n\n"); |
togayan | 1:1637e625b21b | 35 | fsusb30s = 0; // HSD1 |
togayan | 0:1855a008f28e | 36 | |
togayan | 0:1855a008f28e | 37 | // Network setup |
togayan | 0:1855a008f28e | 38 | printf("Setup EtherNet with DHCP.\n"); |
togayan | 0:1855a008f28e | 39 | eth.init(); //Use DHCP |
togayan | 0:1855a008f28e | 40 | eth.connect(); |
togayan | 0:1855a008f28e | 41 | |
togayan | 1:1637e625b21b | 42 | // Obtain original lastBuildDate |
togayan | 3:07562878d3c3 | 43 | char lastBuildDateOriginal[128] = {0}; |
togayan | 0:1855a008f28e | 44 | { |
togayan | 5:e87211ff9c23 | 45 | FILE * fpOriginal = fopen ( rssPath, "r" ); |
togayan | 5:e87211ff9c23 | 46 | if( NULL == fpOriginal ) { |
togayan | 5:e87211ff9c23 | 47 | printf( "cannot not open %s\n", rssPath ); |
togayan | 5:e87211ff9c23 | 48 | sprintf(lastBuildDateOriginal, "cannot not open original %s", rssPath ); |
togayan | 5:e87211ff9c23 | 49 | } |
togayan | 5:e87211ff9c23 | 50 | else |
togayan | 2:0da3a4508b46 | 51 | { |
togayan | 5:e87211ff9c23 | 52 | fseek(fpOriginal, 0, SEEK_END); // seek to end of file |
togayan | 5:e87211ff9c23 | 53 | unsigned int size = ftell(fpOriginal); |
togayan | 5:e87211ff9c23 | 54 | fseek(fpOriginal, 0, SEEK_SET); // seek to head of file |
togayan | 5:e87211ff9c23 | 55 | |
togayan | 5:e87211ff9c23 | 56 | char * source = NULL; |
togayan | 5:e87211ff9c23 | 57 | source = ( char * ) malloc ( size + 1 ); |
togayan | 5:e87211ff9c23 | 58 | fread ( source, size, sizeof ( char ), fpOriginal ); |
togayan | 5:e87211ff9c23 | 59 | fclose ( fpOriginal ); |
togayan | 5:e87211ff9c23 | 60 | source[ size ] = 0; |
togayan | 5:e87211ff9c23 | 61 | |
togayan | 5:e87211ff9c23 | 62 | SP_XmlDomParser parser; |
togayan | 5:e87211ff9c23 | 63 | parser.append( source, strlen( source ) ); |
togayan | 5:e87211ff9c23 | 64 | free( source ); |
togayan | 5:e87211ff9c23 | 65 | |
togayan | 5:e87211ff9c23 | 66 | SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() ); |
togayan | 5:e87211ff9c23 | 67 | |
togayan | 5:e87211ff9c23 | 68 | SP_XmlCDataNode * lastBuildDateNode = rootHandle.getChild( "channel" ).getChild( "lastBuildDate" ).getChild(0).toCData(); |
togayan | 5:e87211ff9c23 | 69 | if( NULL != lastBuildDateNode ) |
togayan | 5:e87211ff9c23 | 70 | { |
togayan | 5:e87211ff9c23 | 71 | printf( "Find /rss/channel/lastBuildDate/text()\n"); |
togayan | 5:e87211ff9c23 | 72 | printf("text() of lastBuildDate: %s\n", lastBuildDateNode->getText()); |
togayan | 5:e87211ff9c23 | 73 | strcpy(lastBuildDateOriginal, lastBuildDateNode->getText()); |
togayan | 5:e87211ff9c23 | 74 | } else { |
togayan | 5:e87211ff9c23 | 75 | printf( "Cannot found /rss/channel/lastBuildDate/text()\n" ); |
togayan | 5:e87211ff9c23 | 76 | sprintf(lastBuildDateOriginal, "Cannot found /rss/channel/lastBuildDate/text()"); |
togayan | 5:e87211ff9c23 | 77 | } |
togayan | 2:0da3a4508b46 | 78 | } |
togayan | 0:1855a008f28e | 79 | } |
togayan | 3:07562878d3c3 | 80 | printf("\nlastBuildDate (original): %s\n", lastBuildDateOriginal); |
togayan | 0:1855a008f28e | 81 | |
togayan | 1:1637e625b21b | 82 | // Download RSS |
togayan | 0:1855a008f28e | 83 | GetFile(rssPath, rssUrl); |
togayan | 1:1637e625b21b | 84 | |
togayan | 1:1637e625b21b | 85 | // Obtain current lastBuildDate |
togayan | 3:07562878d3c3 | 86 | char lastBuildDateCurrent[128] = {0}; |
togayan | 3:07562878d3c3 | 87 | char mp3Url[256] = {0}; |
togayan | 3:07562878d3c3 | 88 | char mp3Length[32] = {0}; |
togayan | 0:1855a008f28e | 89 | { |
togayan | 5:e87211ff9c23 | 90 | FILE * fpCurrent = fopen ( rssPath, "r" ); |
togayan | 5:e87211ff9c23 | 91 | if( NULL == fpCurrent ) { |
togayan | 2:0da3a4508b46 | 92 | fsusb30s = 1; // HSD2 |
togayan | 2:0da3a4508b46 | 93 | error("No current english.xml in USB memory.\n"); |
togayan | 2:0da3a4508b46 | 94 | } |
togayan | 5:e87211ff9c23 | 95 | else |
togayan | 2:0da3a4508b46 | 96 | { |
togayan | 5:e87211ff9c23 | 97 | fseek(fpCurrent, 0, SEEK_END); // seek to end of file |
togayan | 5:e87211ff9c23 | 98 | unsigned int size = ftell(fpCurrent); |
togayan | 5:e87211ff9c23 | 99 | fseek(fpCurrent, 0, SEEK_SET); // seek to head of file |
togayan | 5:e87211ff9c23 | 100 | |
togayan | 5:e87211ff9c23 | 101 | char * source = NULL; |
togayan | 5:e87211ff9c23 | 102 | source = ( char * ) malloc ( size + 1 ); |
togayan | 5:e87211ff9c23 | 103 | fread ( source, size, sizeof ( char ), fpCurrent ); |
togayan | 5:e87211ff9c23 | 104 | fclose ( fpCurrent ); |
togayan | 5:e87211ff9c23 | 105 | source[ size ] = 0; |
togayan | 5:e87211ff9c23 | 106 | |
togayan | 5:e87211ff9c23 | 107 | SP_XmlDomParser parser; |
togayan | 5:e87211ff9c23 | 108 | parser.append( source, strlen( source ) ); |
togayan | 5:e87211ff9c23 | 109 | free( source ); |
togayan | 5:e87211ff9c23 | 110 | |
togayan | 5:e87211ff9c23 | 111 | SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() ); |
togayan | 5:e87211ff9c23 | 112 | |
togayan | 5:e87211ff9c23 | 113 | SP_XmlCDataNode * lastBuildDateNode = rootHandle.getChild( "channel" ).getChild( "lastBuildDate" ).getChild(0).toCData(); |
togayan | 5:e87211ff9c23 | 114 | if( NULL != lastBuildDateNode ) |
togayan | 5:e87211ff9c23 | 115 | { |
togayan | 5:e87211ff9c23 | 116 | printf( "Find /rss/channel/lastBuildDate/text()\n"); |
togayan | 5:e87211ff9c23 | 117 | printf("text() of lastBuildDate: %s\n", lastBuildDateNode->getText()); |
togayan | 5:e87211ff9c23 | 118 | strcpy(lastBuildDateCurrent, lastBuildDateNode->getText()); |
togayan | 5:e87211ff9c23 | 119 | } else { |
togayan | 5:e87211ff9c23 | 120 | fsusb30s = 1; // HSD2 |
togayan | 5:e87211ff9c23 | 121 | error("No \"lastBuildDate\" element in current RSS.\n"); |
togayan | 5:e87211ff9c23 | 122 | } |
togayan | 5:e87211ff9c23 | 123 | |
togayan | 5:e87211ff9c23 | 124 | SP_XmlElementNode * enclosureNode = rootHandle.getChild( "channel" ).getChild( "item" ).getChild("enclosure").toElement(); |
togayan | 5:e87211ff9c23 | 125 | if( NULL != enclosureNode ) |
togayan | 5:e87211ff9c23 | 126 | { |
togayan | 5:e87211ff9c23 | 127 | strcpy(mp3Url, enclosureNode->getAttrValue("url")); |
togayan | 5:e87211ff9c23 | 128 | strcpy(mp3Length, enclosureNode->getAttrValue("length")); |
togayan | 5:e87211ff9c23 | 129 | } else { |
togayan | 5:e87211ff9c23 | 130 | fsusb30s = 1; // HSD2 |
togayan | 5:e87211ff9c23 | 131 | error("No \"lastBuildDate\" element in current RSS.\n"); |
togayan | 5:e87211ff9c23 | 132 | } |
togayan | 5:e87211ff9c23 | 133 | |
togayan | 2:0da3a4508b46 | 134 | } |
togayan | 0:1855a008f28e | 135 | } |
togayan | 3:07562878d3c3 | 136 | printf("\nlastBuildDate (current) : %s\n", lastBuildDateCurrent); |
togayan | 0:1855a008f28e | 137 | |
togayan | 2:0da3a4508b46 | 138 | // Determine the necessity of downloading new MP3. |
togayan | 2:0da3a4508b46 | 139 | bool flgDownloadMp3 = false; |
togayan | 3:07562878d3c3 | 140 | if ( strcmp(lastBuildDateOriginal, lastBuildDateCurrent) == 0 ) |
togayan | 0:1855a008f28e | 141 | { |
togayan | 3:07562878d3c3 | 142 | printf("lastBuildDate (original) == lastBuildDate (current)\n"); |
togayan | 0:1855a008f28e | 143 | FILE* mp3fp = fopen(mp3Path, "r"); // check an existance of english.mp3 |
togayan | 0:1855a008f28e | 144 | if (mp3fp != NULL) |
togayan | 0:1855a008f28e | 145 | { |
togayan | 2:0da3a4508b46 | 146 | fseek(mp3fp, 0, SEEK_END); // seek to end of file |
togayan | 3:07562878d3c3 | 147 | if (ftell(mp3fp) != atol(mp3Length)) |
togayan | 2:0da3a4508b46 | 148 | { |
togayan | 3:07562878d3c3 | 149 | printf("MP3 file size is invalid.\n"); |
togayan | 2:0da3a4508b46 | 150 | flgDownloadMp3 = true; |
togayan | 2:0da3a4508b46 | 151 | } |
togayan | 0:1855a008f28e | 152 | fclose(mp3fp); |
togayan | 0:1855a008f28e | 153 | } |
togayan | 0:1855a008f28e | 154 | else |
togayan | 0:1855a008f28e | 155 | { |
togayan | 3:07562878d3c3 | 156 | printf("However, no enlish.mp3 in USB memory\n"); |
togayan | 2:0da3a4508b46 | 157 | flgDownloadMp3 = true; |
togayan | 0:1855a008f28e | 158 | } |
togayan | 0:1855a008f28e | 159 | } |
togayan | 0:1855a008f28e | 160 | else |
togayan | 0:1855a008f28e | 161 | { |
togayan | 3:07562878d3c3 | 162 | printf("lastBuildDate (original) != lastBuildDate (current)\n"); |
togayan | 2:0da3a4508b46 | 163 | flgDownloadMp3 = true; |
togayan | 0:1855a008f28e | 164 | } |
togayan | 0:1855a008f28e | 165 | |
togayan | 2:0da3a4508b46 | 166 | // Download new MP3 |
togayan | 2:0da3a4508b46 | 167 | if(flgDownloadMp3 == true) |
togayan | 2:0da3a4508b46 | 168 | { |
togayan | 3:07562878d3c3 | 169 | GetFile(mp3Path, mp3Url); |
togayan | 2:0da3a4508b46 | 170 | } |
togayan | 2:0da3a4508b46 | 171 | |
togayan | 2:0da3a4508b46 | 172 | // Wait for the completion of writing to USB Mass Storage Device. |
togayan | 2:0da3a4508b46 | 173 | wait(1); |
togayan | 2:0da3a4508b46 | 174 | |
togayan | 1:1637e625b21b | 175 | // FSUSB30 switches to HSD2 (External Device) |
togayan | 3:07562878d3c3 | 176 | printf("\nUSB host was switched to HSD2(External Device).\n"); |
togayan | 1:1637e625b21b | 177 | fsusb30s = 1; // HSD2 |
togayan | 0:1855a008f28e | 178 | |
togayan | 0:1855a008f28e | 179 | // blink LED |
togayan | 0:1855a008f28e | 180 | led1.startBlink(); |
togayan | 3:07562878d3c3 | 181 | ethGreen.startBlink(); |
togayan | 0:1855a008f28e | 182 | |
togayan | 0:1855a008f28e | 183 | while(true){} |
togayan | 0:1855a008f28e | 184 | } |
togayan | 0:1855a008f28e | 185 | |
togayan | 0:1855a008f28e | 186 | int GetFile(const char *path, const char *url) |
togayan | 0:1855a008f28e | 187 | { |
togayan | 2:0da3a4508b46 | 188 | led2.startBlink(); |
togayan | 3:07562878d3c3 | 189 | ethYellow.startBlink(); |
togayan | 3:07562878d3c3 | 190 | printf("\nGetting %s\n", url); |
togayan | 0:1855a008f28e | 191 | |
togayan | 0:1855a008f28e | 192 | timer.stop(); |
togayan | 0:1855a008f28e | 193 | timer.reset(); |
togayan | 0:1855a008f28e | 194 | timer.start(); |
togayan | 0:1855a008f28e | 195 | |
togayan | 2:0da3a4508b46 | 196 | HTTPFile file(path); |
togayan | 0:1855a008f28e | 197 | HTTPResult retGet = http.get(url, &file); |
togayan | 2:0da3a4508b46 | 198 | if (retGet != HTTP_OK) |
togayan | 2:0da3a4508b46 | 199 | { |
togayan | 1:1637e625b21b | 200 | fsusb30s = 1; // HSD2 |
togayan | 0:1855a008f28e | 201 | error("Error in http.get in GetFile(): %d\n", retGet); |
togayan | 0:1855a008f28e | 202 | } |
togayan | 0:1855a008f28e | 203 | file.clear(); |
togayan | 0:1855a008f28e | 204 | |
togayan | 0:1855a008f28e | 205 | timer.stop(); |
togayan | 3:07562878d3c3 | 206 | printf("timer.read_ms(): %d\n", timer.read_ms()); |
togayan | 2:0da3a4508b46 | 207 | |
togayan | 2:0da3a4508b46 | 208 | led2.finishBlink(); |
togayan | 3:07562878d3c3 | 209 | ethYellow.finishBlink(); |
togayan | 0:1855a008f28e | 210 | return (0); |
togayan | 0:1855a008f28e | 211 | } |