Plan 9 from Bell Labs’s /usr/web/sources/contrib/anothy/src/cmd/darksky.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.