Download picasa web albums photos automatically. This application requires mpod mother board. See also http://mbed.org/users/geodenx/notebook/mpod/
Dependencies: BlinkLed HTTPClient EthernetInterface FatFileSystemCpp MSCFileSystem mbed-rtos mbed
Download picasa web albums photos automatically.
This application requires mpod mother board.
Picasaウェブアルバムから、自動的に写真をダウンロードして、ディジタルフォトフレームに表示します。
動作させるには mpod マザーボード が必要です。
プログラムの中で、ご自分のアルバムのRSSファイルへのURLを指定してからご利用下さい。
main.cpp
- Committer:
- togayan
- Date:
- 2012-08-24
- Revision:
- 2:531722036c0a
- Parent:
- 0:dfd5cfea7112
- Child:
- 3:ffbb2b22099a
File content as of revision 2:531722036c0a:
#include "mbed.h"
#include "MSCFileSystem.h"
#include "EthernetInterface.h"
#include "HTTPClient.h"
#include "HTTPFile.h"
#include "BlinkLed.h"
#include "tinyxml2.h"
using namespace tinyxml2;
int GetFile(const char *path, const char *url);
int addNewLine(const char* dstPath, const char* srcPath);
int summarizeRss(const char* dstPath, const char* srcPath);
int removePhotos();
const char* getExtensionFromUrl(const char* url);
EthernetInterface eth;
HTTPClient http;
MSCFileSystem usb("usb");
BlinkLed led1(LED1, 0.02);
BlinkLed led2(LED2, 0.2);
BlinkLed ethGreen(p26, 0.02);
BlinkLed ethYellow(p25, 0.2);
DigitalOut fsusb30s(p9);
Timer timer;
/***** Please specify "albumRssUrl" *****/
const char* albumRssUrl = "http://picasaweb.google.com/data/feed/base/user/*****/albumid/*****?alt=rss&kind=photo&authkey=*****&hl=ja";
const char* albumRssPath = "/usb/album.xml";
const char* tempPath = "/usb/temp.xml";
const char* summaryPath = "/usb/summary.xml";
int main()
{
printf("\n\n================================\n");
printf("mpod Picasa Photo frame\n");
printf("================================\n\n");
// FSUSB30 switches to HSD1 (mbed)
printf("USB host was switched to HSD1(mbed).\n\n");
fsusb30s = 0; // HSD1
// Network setup
printf("Setup EtherNet with DHCP.\n");
eth.init(); //Use DHCP
eth.connect();
// Obtain original lastBuildDate
char lastBuildDateOriginal[32] = {0};
{
XMLDocument docOriginal;
if(XML_SUCCESS != docOriginal.LoadFile(summaryPath))
{
strcpy(lastBuildDateOriginal, "No original summary.xml in USB memory");
}
else
{
XMLElement* lastBuildDateOriginalElement = docOriginal.FirstChildElement("rss")->FirstChildElement("channel")->FirstChildElement("lastBuildDate");
if(NULL == lastBuildDateOriginalElement)
{
strcpy(lastBuildDateOriginal, "No \"lastBuildDate\" element in original RSS");
}
else
{
strcpy(lastBuildDateOriginal, lastBuildDateOriginalElement->GetText());
}
}
}
printf("\nlastBuildDate (original): %s\n", lastBuildDateOriginal);
// Download Album
GetFile(albumRssPath, albumRssUrl);
// Summarize RSS
addNewLine(tempPath, albumRssPath);
summarizeRss(summaryPath, tempPath);
// Obtain current lastBuildDate
char lastBuildDateCurrent[32] = {0};
XMLDocument docCurrent;
if(XML_SUCCESS != docCurrent.LoadFile(summaryPath))
{
fsusb30s = 1; // HSD2
error("No current summary.xml in USB memory.\n");
}
XMLElement* lastBuildDateCurrentElement = docCurrent.FirstChildElement("rss")->FirstChildElement("channel")->FirstChildElement("lastBuildDate");
if(NULL == lastBuildDateCurrentElement)
{
fsusb30s = 1; // HSD2
error("No \"lastBuildDate\" element in current RSS.\n");
}
strcpy(lastBuildDateCurrent, lastBuildDateCurrentElement->GetText());
printf("\nlastBuildDate (current) : %s\n", lastBuildDateCurrent);
if( strcmp(lastBuildDateOriginal, lastBuildDateCurrent) != 0 )
{
printf("lastBuildDate (original) != lastBuildDate (current)\n");
if(removePhotos() < 0)
{
fsusb30s = 1; // HSD2
error("No \"DCIM\" folder in MSD.\n");
}
char photoUrl[256] = {0};
char photoPath[32] = {0};
int photoNo = 1;
XMLElement* itemElement = docCurrent.FirstChildElement("rss")->FirstChildElement("channel")->FirstChildElement("item");
if(NULL == itemElement)
{
fsusb30s = 1; // HSD2
error("No \"enclosure\" element in current RSS.\n");
}
strcpy(photoUrl, itemElement->FirstChildElement("enclosure")->Attribute("url"));
const char* extension = getExtensionFromUrl(photoUrl);
sprintf(photoPath, "/usb/DCIM/%08d.%s", photoNo, extension);
GetFile(photoPath, photoUrl);
++photoNo;
while( (itemElement = itemElement->NextSiblingElement( "item" ) ) != NULL )
{
strcpy(photoUrl, itemElement->FirstChildElement("enclosure")->Attribute("url"));
sprintf(photoPath, "/usb/DCIM/%08d.jpg", photoNo);
GetFile(photoPath, photoUrl);
++photoNo;
}
}
else
{
printf("lastBuildDate (original) == lastBuildDate (current)\n");
}
// Wait for the completion of writing to USB Mass Storage Device.
wait(1);
// FSUSB30 switches to HSD2 (External Device)
printf("\nUSB host was switched to HSD2(External Device).\n");
fsusb30s = 1; // HSD2
// blink LED
led1.startBlink();
ethGreen.startBlink();
while(true){}
}
int GetFile(const char *path, const char *url)
{
led2.startBlink();
ethYellow.startBlink();
printf("\nGetting %s\n", url);
timer.stop();
timer.reset();
timer.start();
HTTPFile file(path);
HTTPResult retGet = http.get(url, &file);
if (retGet != HTTP_OK)
{
fsusb30s = 1; // HSD2
error("Error in http.get in GetFile(): %d\n", retGet);
}
file.clear();
timer.stop();
printf("timer.read_ms(): %d\n", timer.read_ms());
led2.finishBlink();
ethYellow.finishBlink();
return (0);
}
int addNewLine(const char* dstPath, const char* srcPath)
{
FILE* fpSrc = fopen(srcPath, "r");
if (fpSrc == NULL)
{
return -1;
}
FILE* fpDst = fopen(dstPath, "w");
if (fpDst == NULL)
{
return -1;
}
int src;
int previous = '\0';
while( (src = fgetc(fpSrc)) != EOF )
{
if(previous == '>' && src == '<')
{
fputc('\n', fpDst);
}
fputc(src, fpDst);
previous = src;
}
fclose(fpDst);
fclose(fpSrc);
return 0;
}
int summarizeRss(const char* dstPath, const char* srcPath)
{
FILE* fpSrc = fopen(srcPath, "r");
if (fpSrc == NULL)
{
return -1;
}
FILE* fpDst = fopen(dstPath, "w");
if (fpDst == NULL)
{
return -1;
}
char* ptn[] =
{
"<?xml",
"<rss",
"<channel",
"<lastBuildDate",
"<item",
"<enclosure",
"</item",
"</channel",
"</rss"
};
int ptnSize = sizeof(ptn) / sizeof(char*);
char buff[1024] = {0};
while( fgets(buff, 1024, fpSrc) != NULL )
{
for(int i = 0; i < ptnSize; ++i)
{
if( strncmp(buff, ptn[i], strlen(ptn[i])) == 0 )
{
fputs(buff, fpDst);
break;
}
}
}
fclose(fpDst);
fclose(fpSrc);
return 0;
}
int removePhotos()
{
if(DirHandle* dir = opendir("/usb/DCIM"))
{
int ret = 0;
while(struct dirent* ent = dir->readdir())
{
char filename[32] = {0};
sprintf(filename, "/usb/DCIM/%s", ent->d_name);
printf("remove %s\n", filename);
remove(filename);
++ret;
}
return ret;
}
else
{
return -1;
}
}
const char* getExtensionFromUrl(const char* url)
{
const char* tail = url;
while('\0' != *tail)
{
++tail;
}
for(const char* p = tail; p >= url; --p)
{
if ('/' == *p)
{
return tail;
}
if ( '.' == *p )
{
return p+1;
}
}
return tail;
}
Satoshi Togawa