ソースコード
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <syslog.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/time.h>
#define BCM2708_PERI_BASE 0x3F000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
//#define HOST "open.live.bbc.co.uk"
#define HOST "天気予報サーバアドレス"
#define RSSSIZE 8096
#define PAGE "RSSファイル名"
#define PORT 80
#define USERAGENT "HTMLGET 1.0"
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
int mem_fd;
void *gpio_map;
// I/O access
volatile unsigned *gpio;
void setup_io();
int create_tcp_socket();
int speakweather();
char *get_ip(char *host);
char *build_get_query(char *host, char *page);
int get_weather(char *rssbuf, int *index, char *title);
int main(int argc, char **argv)
{
if (daemon(1,0) == -1) {
syslog(LOG_USER|LOG_INFO,"failed to launch daemon.\n");
return -1;
}
chdir("/home/pi/cpp/speakweather");
struct tm *s_time;
time_t the_time;
static int timecount=0;
setup_io();
INP_GPIO(4);
INP_GPIO(17);
OUT_GPIO(17);
while(1){
if(GET_GPIO(4) > 0 && timecount==0){
(void) time(&the_time);
s_time=localtime(&the_time);
if(s_time->tm_hour>=6 && s_time->tm_hour<12){
GPIO_SET = 1<<17;
if(speakweather()!=0){
syslog(LOG_USER|LOG_INFO,"speakweather error.");
break;
}
GPIO_CLR = 1<<17;
timecount=60;
}
}else if(timecount>0){
timecount--;
}
sleep(1);
}
GPIO_CLR = 1<<17;
return 0;
}
int speakweather()
{
struct sockaddr_in *remote;
int sock;
int tmpres;
char *ip;
char *get;
char totalbuf[RSSSIZE+1];
char buf[BUFSIZ+1];
char titlebuf[BUFSIZ+1];
char todayweekday[100];
char todayweekdayjp[100];
char host[]=HOST;
char page[]=PAGE;
char *tempchar;
int titlenum;
int index;
time_t timer;
struct tm *date;
timer = time(NULL);
date = localtime(&timer);
strftime(todayweekday, sizeof(todayweekday), "%A", date);
if (strcmp(todayweekday,"Sunday")==0){
strcpy(todayweekdayjp,"日");
}else
if (strcmp(todayweekday,"Monday")==0){
strcpy(todayweekdayjp,"月");
}else
if (strcmp(todayweekday,"Tuesday")==0){
strcpy(todayweekdayjp,"火");
}else
if (strcmp(todayweekday,"Wednesday")==0){
strcpy(todayweekdayjp,"水");
}else
if (strcmp(todayweekday,"Thursday")==0){
strcpy(todayweekdayjp,"木");
}else
if (strcmp(todayweekday,"Friday")==0){
strcpy(todayweekdayjp,"金");
}else{
strcpy(todayweekdayjp,"土");
}
sock = create_tcp_socket();
ip = get_ip(host);
remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
remote->sin_family = AF_INET;
tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
if( tmpres < 0)
{
syslog(LOG_USER|LOG_INFO,"Can't set remote->sin_addr.s_addr");
return -1;
}else if(tmpres == 0){
syslog(LOG_USER|LOG_INFO,"%s is not a valid IP addressn", ip);
return -1;
}
remote->sin_port = htons(PORT);
if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
syslog(LOG_USER|LOG_INFO,"Could not connect");
return -1;
}
get = build_get_query(host, page);
//Send the query to the server
int sent = 0;
while(sent < strlen(get))
{
tmpres = send(sock, get+sent, strlen(get)-sent, 0);
if(tmpres == -1){
syslog(LOG_USER|LOG_INFO,"Can't send query");
}
sent += tmpres;
}
//now it is time to receive the page
memset(buf, 0, sizeof(buf));
memset(totalbuf, 0, sizeof(totalbuf));
char * htmlcontent;
while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){
if(strlen(totalbuf)+strlen(buf) < RSSSIZE){
strcat(totalbuf, buf);
}
memset(buf, 0, tmpres);
}
if(tmpres < 0)
{
syslog(LOG_USER|LOG_INFO,"Error receiving data");
}
htmlcontent = totalbuf;
while(get_weather(htmlcontent, &index, titlebuf)==0){
if(strstr(titlebuf, todayweekdayjp)!=NULL){
printf("%s\n",titlebuf);
system("aplay tenki.wav > /dev/null 2>&1");
if(strstr(titlebuf,"雨")!=NULL){
system("aplay ame.wav > /dev/null 2>&1");
system("aplay kasa.wav > /dev/null 2>&1");
}else
if(strstr(titlebuf,"雪")!=NULL){
system("aplay yuki.wav > /dev/null 2>&1");
}else
if(strstr(titlebuf,"曇")!=NULL){
system("aplay kumori.wav > /dev/null 2>&1");
}else
if(strstr(titlebuf,"晴")!=NULL){
system("aplay hare.wav > /dev/null 2>&1");
}
break;
}
htmlcontent += index + 15;
}
free(get);
free(remote);
free(ip);
close(sock);
return 0;
}
int create_tcp_socket()
{
int sock;
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
syslog(LOG_USER|LOG_INFO,"Can't create TCP socket");
exit(1);
}
return sock;
}
char *get_ip(char *host)
{
struct hostent *hent;
int iplen = 15; //XXX.XXX.XXX.XXX
char *ip = (char *)malloc(iplen+1);
memset(ip, 0, iplen+1);
if((hent = gethostbyname(host)) == NULL)
{
syslog(LOG_USER|LOG_INFO,"Can't get IP");
exit(1);
}
if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
{
syslog(LOG_USER|LOG_INFO,"Can't resolve host");
exit(1);
}
return ip;
}
char *build_get_query(char *host, char *page)
{
char *query;
char *getpage = page;
char tpl[] = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
if(getpage[0] == '/'){
getpage = getpage + 1;
syslog(LOG_USER|LOG_INFO,"Removing leading \"/\", converting %s to %s\n", page, getpage);
}
// -5 is to consider the %s %s %s in tpl and the ending \0
query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
sprintf(query, tpl, getpage, host, USERAGENT);
return query;
}
int get_weather(char *rssbuf, int *index, char *title)
{
char* ret;
char* retend;
ret = strstr(rssbuf, "<title>");
if(ret!=NULL){
ret+=7;
retend = strstr(ret, "</title>");
if(retend!=NULL && retend-ret<BUFSIZ){
strncpy(title, ret, retend-ret);
*index=retend-rssbuf;
return 0;
}
}
return -1;
}
//
// Set up a memory regions to access GPIO
//
void setup_io()
{
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
syslog(LOG_USER|LOG_INFO,"can't open /dev/mem ");
exit(-1);
}
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (gpio_map == MAP_FAILED) {
syslog(LOG_USER|LOG_INFO,"mmap error %d", (int)gpio_map);//errno also set!
exit(-1);
}
// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map;
} // setup_io