#include <u.h>
#include <libc.h>
#include <json.h>
/*
* Weather forecast via forecast.io. Get a key from
* https://developer.forecast.io/register and stick it in
* $home/lib/darksky
* Relies on 9son: https://bitbucket.org/bedo/9son
*/
void parse(void);
char *wday[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
};
char *mon[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
void
main(int argc, char *argv[])
{
char *apibase, *options, resp[32*1024], *mtpt, buf[128], key[64];
int i, j, n, index, ai, ci, di, hi, mi, datai;
int aflag, currently, daily, hourly, minutely, summ, sumh, sumd;
int conn, ctlfd, fd;
char *keyfile, *herefile;
float here[2], precip;
Tm *tm;
Jparser p;
apibase = "https://api.forecast.io/forecast";
aflag = currently = daily = hourly = minutely = summ = sumh = sumd = 0;
herefile = "/lib/sky/here";
keyfile = smprint("%s/lib/darksky", getenv("home"));
// options = "exclude=minutely,hourly&units=auto";
options = "units=auto";
mtpt = "/mnt/web";
ARGBEGIN {
case 'a':
aflag = 1;
break;
case 'c':
currently = 1;
break;
case 'm':
minutely = 1;
break;
case 'h':
hourly = 1;
break;
case 'd':
daily = 1;
break;
case 'M':
minutely = 1;
summ = 1;
break;
case 'H':
hourly = 1;
sumh = 1;
break;
case 'D':
daily = 1;
sumd = 1;
break;
}ARGEND
if (!aflag && !currently && !daily && !hourly && !minutely)
currently = minutely = hourly = daily = sumh = sumd = 1;
if((fd = open(keyfile, OREAD)) <= 0)
sysfatal("couldn't get key: %r");
if((n = read(fd, key, 32)) <= 0)
sysfatal("couldn't get key: %r");
if(n<32)
sysfatal("bad key, len %d", n);
close(fd);
if((fd = open(herefile, OREAD)) <= 0)
sysfatal("couldn't find our location: %r");
if(read(fd, buf, 128) <= 0)
sysfatal("couldn't find our location: %r");
close(fd);
here[0]=atof(strtok(buf, " "));
here[1]=atof(strtok(nil, " "));
snprint(buf, sizeof buf, "%s/clone", mtpt);
if((ctlfd = open(buf, ORDWR)) < 0)
sysfatal("couldn't open %s: %r", buf);
if((n = read(ctlfd, buf, sizeof buf-1)) < 0)
sysfatal("reading clone: %r");
if(n == 0)
sysfatal("short read on clone");
buf[n] = '\0';
conn = atoi(buf);
if(fprint(ctlfd, "url %s/%s/%2.4f,-%2.4f?%s", apibase, key,
here[0], here[1], options) <= 0)
sysfatal("get ctl write: %r");
snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn);
if((fd = open(buf, OREAD)) < 0)
sysfatal("open %s: %r", buf);
readn(fd, resp, sizeof resp);
Jinit(&p);
if(Jtokenise(&p, resp) < 0)
sysfatal("JSON tokenization error: %r");
if(p.tokens[0].type != JObj)
sysfatal("Darksky didn't return an object.");
ai = Jfind(&p, 0, "alerts");
if(ai>1) {
print("ALERT:\n");
for(i=0, j=ai+1 ; i < p.tokens[ai].nsub ; i++) {
index = Jfind(&p, j, "title");
print(" %s\n",Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "expires");
tm = localtime(atol(Jtokstr(&p.tokens[index])));
print(" Expires %s, %s %d %d:%02.2d.\n", wday[tm->wday],
mon[tm->mon], tm->mday, tm->hour, tm->min);
index = Jfind(&p, j, "uri");
print(" For more information, see %s\n",
Jtokstr(&p.tokens[index]));
j=Jnext(&p, j);
}
} else if(aflag)
print("No alerts.\n");
if(currently) {
ci = Jfind(&p, 0, "currently");
print("Conditions as of ");
index = Jfind(&p, ci, "time");
print("%s", ctime(atol(Jtokstr(&p.tokens[index]))));
index = Jfind(&p, ci, "summary");
print(" %s, ", Jtokstr(&p.tokens[index]));
index = Jfind(&p, ci, "temperature");
print("%s°\n", Jtokstr(&p.tokens[index]));
}
if (minutely) {
mi = Jfind(&p, 0, "minutely");
// if(!summ)
// print("Forecast for the next hour:\n");
index = Jfind(&p, mi, "summary");
print(" %s\n", Jtokstr(&p.tokens[index]));
if(!summ) {
print(" ");
datai = Jfind(&p, mi, "data");
for(i=0, j=datai+1 ; i < p.tokens[datai].nsub ; i++) {
index = Jfind(&p, j, "precipProbability");
precip = atof(Jtokstr(&p.tokens[index]))*100;
switch((int)precip/8) {
case 0: print(" "); break;
case 1: print("▁"); break;
case 2: print("▂"); break;
case 3: print("▃"); break;
case 4: print("▄"); break;
case 5: print("▅"); break;
case 6: print("▆"); break;
case 7: print("▇"); break;
case 8: print("█"); break;
}
j=Jnext(&p, j);
}
print("\n");
}
}
if (hourly) {
hi = Jfind(&p, 0, "hourly");
// if(!sumh)
// print("Hourly forecast:\n");
index = Jfind(&p, hi, "summary");
print(" %s\n", Jtokstr(&p.tokens[index]));
if(!sumh) {
datai = Jfind(&p, hi, "data");
for(i=0, j=datai+1 ; i < p.tokens[datai].nsub ; i++) {
index = Jfind(&p, j, "time");
tm=localtime(atol(Jtokstr(&p.tokens[index])));
print("→ %d:%02.2d:\n", tm->hour, tm->min);
index = Jfind(&p, j, "temperature");
print(" %0s°, ", Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "summary");
print(" %s\n", Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "precipProbability");
precip = atof(Jtokstr(&p.tokens[index]))*100;
if(precip != 0) {
print(" %2.0f%% chance of ", precip);
index = Jfind(&p, j, "precipType");
print("%s.\n", Jtokstr(&p.tokens[index]));
}
j=Jnext(&p, j);
}
}
}
if (daily) {
di = Jfind(&p, 0, "daily");
// if(!sumd)
// print("Extended forecast:\n");
index = Jfind(&p, di, "summary");
print(" %s\n", Jtokstr(&p.tokens[index]));
if(!sumd) {
datai = Jfind(&p, di, "data");
for(i=0, j=datai+1 ; i < p.tokens[datai].nsub ; i++) {
index = Jfind(&p, j, "time");
tm=localtime(atol(Jtokstr(&p.tokens[index])));
print("→ %s, %s %d, %d:\n", wday[tm->wday],
mon[tm->mon], tm->mday, tm->year+1900);
index = Jfind(&p, j, "summary");
print(" %s\n", Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "temperatureMax");
print(" High: %s°", Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "temperatureMin");
print(" Low: %s°\n", Jtokstr(&p.tokens[index]));
index = Jfind(&p, j, "precipProbability");
precip = atof(Jtokstr(&p.tokens[index]))*100;
if(precip != 0) {
print(" %2.0f%% chance of ", precip);
index = Jfind(&p, j, "precipType");
print("%s.\n", Jtokstr(&p.tokens[index]));
}
j=Jnext(&p, j);
}
}
}
exits(0);
}
|