Overview
Comment: | refactor tenki |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
70991b55c336efe6d230977e2f952829 |
User & Date: | lexi on 2019-05-01 01:03:44 |
Other Links: | manifest | tags |
Context
2019-05-03
| ||
15:21 | add vpn tool check-in: 75223838e1 user: lexi tags: trunk | |
2019-05-01
| ||
01:03 | refactor tenki check-in: 70991b55c3 user: lexi tags: trunk | |
2019-04-30
| ||
23:26 | add tenki check-in: ae8a97d783 user: lexi tags: trunk | |
Changes
Added tenki/make.sh version [f7f3655bf1].
1 +#!/bin/bash 2 +if test -e apikey; then 3 + cc -Ofast -Dds_apikey="\"$(cat apikey)\"" tenki.c -lssl -otenki 4 +else 5 + echo "tenki requires an API key. get one from dark sky and put it in a file in this directory named 'apikey' before you try to build" 6 +fi
Deleted tenki/makefile version [d561bb7339].
1 -tenki: tenki.cc 2 - $(CC) -Ofast tenki.cc -o tenki -lssl
Added tenki/tenki.c version [b2cd504148].
1 +/* [ʞ] tenki.c 2 + * ~ lexi hale <lexi@hale.su> 3 + * > ./make.sh 4 + * © affero general public license 5 + 6 + * tenki is a client for the Dark Sky API. it is a 7 + * bail-early stream parser which retrieves a fixed set 8 + * of keys (this set may be easily changed in the code) 9 + * and prints them as a formatted string to stdout. it 10 + * was designed purely as a polybar plugin to display my 11 + * local weather, but it could be just as easily be 12 + * reworked for many other purposes 13 + * 14 + * you need to get an api key from dark sky before you 15 + * compile tenki, and place it in the file apikey - it's 16 + * segregated from the main code this way to allow it to 17 + * be excluded from version control. 18 + * 19 + * the default language of the results is Japanese; you 20 + * can change this by changing the macro ds_lang from 21 + * "ja" to your language code of choice. the ds_exclude 22 + * macro is used to minimize the bandwidth tenki uses by 23 + * instructing the dark sky server not to send those 24 + * fields back; if you want to access information in any 25 + * of them, you need to remove them from ds_exclude. 26 + * delete the #define entirely if you wish to access all 27 + * of the excluded fields. 28 + * 29 + * the function main() contains most of the code you 30 + * will likely wish to alter. it contains a variable 31 + * "paths" which is used to specify which fields of the 32 + * returned json object you wish the parser to extract. 33 + * each path is a "p-string of p-strings" - that is, its 34 + * first character is an integer which specifies the 35 + * depth of the path, and each "directory" is specified 36 + * with a string prefixed with the number of characters 37 + * in it. so the path "a/bc/def" would be encoded 38 + * "\3\1a\2bc\3def" - \3 for the three constituents "a" 39 + * "bc" and "def", \1 for the strlen of "a", \2 for the 40 + * strlen of "bc", etc. shoutout to the C standards 41 + * committee for forcing me to do this horrible thing. 42 + * 43 + * in conclusion, i should have written this in scheme. 44 + **/ 45 + 46 +#define ds_lang "ja" 47 +#define ds_exclude "minutely,hourly,daily,alerts,flags" 48 + 49 +// posix includes 50 +#include <stdlib.h> 51 +#include <stddef.h> 52 +#include <stdint.h> 53 +#include <unistd.h> 54 + 55 +// libc includes 56 +#include <stdio.h> 57 +#include <string.h> 58 + 59 +// networking includes 60 +#include <sys/socket.h> 61 +#include <netinet/in.h> 62 +#include <netdb.h> 63 +#include <openssl/ssl.h> 64 + 65 +#ifndef ds_apikey 66 +# error missing api key; compile with make.sh 67 +# define ds_apikey "" // tidy up errors 68 +#endif 69 + 70 +#ifdef ds_exclude 71 +# define _http "?exclude=" ds_exclude "&" 72 +#else 73 +# define _http "?" 74 +#endif 75 +#define http _http "lang=" ds_lang " HTTP/1.1\r\nHost: api.darksky.net\r\n\r\n" 76 +#define start "GET /forecast/" ds_apikey "/" 77 + 78 +#define min(x,y) (x>y?y:x) 79 +#define len(x) (sizeof(x)/sizeof(*x)) 80 + 81 +typedef enum bool { false, true } bool; 82 + 83 +SSL_CTX* sc; 84 +bool head(size_t* len, char* txt, char** body) { 85 + char* hend = strstr(txt, "\r\n\r\n"); 86 + if (hend == NULL) return false; 87 + #define ctlhead "\r\nContent-Length:" 88 + char* ctl = strstr(txt, ctlhead); 89 + if (ctl == NULL || ctl > hend) return false; 90 + ctl += len(ctlhead); 91 + *len = 0; 92 + while(*ctl != '\r') { 93 + if (*ctl >= '0' && *ctl <= '9') *len*=10,*len+=*ctl-'0'; 94 + ++ctl; 95 + } 96 + *len+=(hend-txt)+4; 97 + *body = hend+4; 98 + return true; 99 +} 100 +size_t get(char* resp, size_t max, const char* msg, size_t total, char** body){ 101 + 102 + int port = 443; 103 + const char* host = "api.darksky.net"; 104 + //printf("req: %s\n", msg); 105 + struct hostent* api; 106 + struct sockaddr_in api_addr; 107 + int sockfd, bytes; 108 + size_t sent, recd; 109 + 110 + sockfd = socket(AF_INET, SOCK_STREAM, 0); 111 + if (sockfd < 0) exit(2); 112 + SSL *con = SSL_new(sc); 113 + SSL_set_fd(con, sockfd); 114 + 115 + api = gethostbyname(host); 116 + if (api == NULL) exit(3); 117 + 118 + memset(&api_addr, 0, sizeof(api_addr)); 119 + api_addr.sin_family = AF_INET; 120 + api_addr.sin_port = htons(port); 121 + memcpy(&api_addr.sin_addr.s_addr, api -> h_addr, api -> h_length); 122 + 123 + if (connect(sockfd,(struct sockaddr*)&api_addr,sizeof(api_addr))) 124 + exit(4); 125 + int err = SSL_connect(con); 126 + 127 + 128 + sent = 0; 129 + do { 130 + bytes = SSL_write(con,msg+sent,total-sent); 131 + if (bytes < 0) exit (4); 132 + if (bytes == 0) break; 133 + ++sent; 134 + } while (sent < total); 135 + recd = 0; 136 + size_t resplen = max; 137 + bool rhead = false; 138 + do { 139 + bytes = SSL_read(con,resp+recd,min(resplen-recd,15000)); 140 + if (bytes < 0) exit (5); 141 + if (bytes == 0) break; 142 + if(!rhead)rhead=head(&resplen, resp, body); 143 + recd += bytes; 144 + } while (recd < resplen - 1); 145 + 146 + close(sockfd); 147 + SSL_shutdown(con); 148 + 149 + return recd; 150 +} 151 +size_t pos(char* msg, const char* lat, const char* lng) { 152 + char* cur = msg + len(start) - 1; 153 + size_t latl = strlen(lat); 154 + size_t longl = strlen(lng); 155 + strcpy(cur, lat); cur += latl; 156 + *cur++=','; 157 + strcpy(cur, lng); cur += longl; 158 + strcpy(cur, http); cur += len(http); 159 + *cur--=0; 160 + return cur-msg; 161 +} 162 +bool estrc(size_t sz, const char* str1, const char* str2) { 163 + for(size_t i = 0;i<sz;++i) { 164 + if(*str1 == *str2) { 165 + ++str1; ++str2; 166 + } else if (*str2 =='\\') { 167 + ++str2; 168 + if(*str1 == *str2) { 169 + ++str1; ++str2; 170 + } else return false; 171 + } else { 172 + return false; 173 + } 174 + } 175 + return true; 176 +} 177 +typedef struct pstr { 178 + size_t sz; 179 + const char* a; 180 +} pstr; 181 +typedef union jsv { 182 + float f; 183 + pstr s; 184 +} jsv; 185 +/* void printkey(const char* key) { 186 + size_t len = *key++; 187 + for (size_t i = 0; i<len; ++i) { 188 + printf("/%.*s",*key,key+1); 189 + key += *key + 1; 190 + }; 191 + printf("\n"); 192 +} */ 193 +void pplt(const char* str, const char* const end, const char** keys, const char** const keyend, jsv* values) { 194 + // initialize parser state 195 + size_t depth = 0; 196 + const char* fld = NULL; 197 + const char* path[32]; 198 + path[0] = NULL; 199 + 200 + while(*str++!='{'); //cheat 201 + init: { 202 + if (keys > keyend) return; 203 + if (str > end) return; 204 + /* print_path: { 205 + printf("current path: /"); 206 + for (size_t i = 0; i < depth; ++i) { 207 + printf("%.*s/",strchr(path[i],'"')-path[i],path[i]); 208 + } 209 + printf("\n"); 210 + printf("current key: "); 211 + printkey(*keys); 212 + } */ 213 + parse_char: { 214 + switch(*str++) { 215 + case ' ': case '\t': case '\n': 216 + goto parse_char; 217 + case '"': 218 + path[depth] = str; 219 + goto path_find_quote_end; 220 + case '}': 221 + if (depth == 0) return; 222 + depth--; 223 + while(*str!=',') ++str; ++str; 224 + goto init; 225 + default: 226 + printf("found illegal char %c\n", *(str-1)); 227 + exit(6); 228 + } 229 + } 230 + path_find_quote_end: { 231 + switch (*str++) { 232 + case '\\': ++str; goto path_find_quote_end; 233 + case '"': goto read_value; 234 + default: goto path_find_quote_end; 235 + } 236 + } 237 + read_value: { 238 + if (*str++!=':') { 239 + printf("illegal char\n"); 240 + exit(6); 241 + } 242 + bool iskey; 243 + const char* key = *keys; 244 + jsv* value; 245 + if (depth + 1 != *key++) { 246 + iskey = false; 247 + goto comp; 248 + } else for (size_t i = 0; i <= depth; ++i) { 249 + if (estrc(*key, key+1, path[i])) { 250 + key += *key + 1; 251 + } else { 252 + iskey = false; 253 + goto comp; 254 + } 255 + } 256 + iskey = true; 257 + value = values; 258 + ++keys; ++values; 259 + comp: if (*str == '{') { 260 + ++depth; ++str; 261 + goto init; 262 + } else if (*str == '"') { 263 + goto copy_str_value; 264 + } else if (*str == '[') { 265 + goto skip_array; 266 + } else if ((*str >= '0' && *str <= '9') || *str=='-') { 267 + goto copy_int_value; 268 + } else { 269 + printf("illegal character found in value %c\n", *str); 270 + exit(6); 271 + } 272 + 273 + copy_str_value: { 274 + fld = ++str; 275 + while (*++str != '"') if (*str == '\\') { ++str; continue; } 276 + if (iskey) { 277 + value -> s.sz = str - fld; 278 + value -> s.a = fld; 279 + } 280 + while (*++str != ','); 281 + ++str; goto init; 282 + } 283 + skip_array: { 284 + size_t ard = 0; 285 + skip_loop: switch (*++str) { 286 + case '{': case '[': ++ard; goto skip_loop; 287 + case '"': goto skip_str; 288 + case '}': if (ard == 0) { 289 + printf("bad json\n"); 290 + exit(7); 291 + } else { --ard; goto skip_loop; } 292 + case ']': if (ard == 0) { 293 + if (*++str == ',') { ++str; goto init; } 294 + else goto init; 295 + } else { --ard; } 296 + default: goto skip_loop; 297 + } 298 + skip_str: while (*str != '"') if (*str == '\\') { str += 2; continue; } else ++str; goto skip_loop; 299 + } 300 + copy_int_value: { 301 + if (!iskey) { 302 + while(*str++!=',') if (str > end) return; 303 + goto init; 304 + } 305 + value -> f = 0; 306 + bool neg; 307 + if (*str == '-') { neg=true; ++str; } else neg=false; 308 + while(*str >= '0' && *str <= '9') { 309 + value -> f *= 10; 310 + value -> f += *str - '0'; 311 + ++str; 312 + } 313 + if(*str == '.') { 314 + float fac = 0.1; 315 + float val = 0; 316 + while(*++str >= '0' && *str <= '9') { 317 + val += (((float)(*str - '0')) * fac); 318 + fac *= 0.1; 319 + } 320 + value -> f += val; 321 + } 322 + if(neg) value -> f *= -1; 323 + if (*str == ',') { 324 + ++str; goto init; 325 + } else { 326 + printf("illegal character %.*s\n",15,str); 327 + exit(6); 328 + } 329 + } 330 + } 331 + } 332 +} 333 + 334 +int main(int argc, char** argv) { 335 + if (argc != 3) exit(1); 336 + SSL_load_error_strings(); 337 + SSL_library_init(); 338 + sc = SSL_CTX_new(SSLv23_client_method()); 339 + 340 + char msg[256] = start; 341 + char resp[32368]; 342 + char* body; 343 + 344 + // name the fields to extract from the json stream 345 + // note: MUST BE LISTED IN ORDER THEY APPEAR 346 + // TODO: performance worth lack of flexibility? 347 + const char* paths[] = { 348 + "\2\x9""currently\7summary", 349 + "\2\x9""currently\xfprecipIntensity", 350 + "\2\x9""currently\xbtemperature", 351 + "\2\x9""currently\x9windspeed", 352 + }; 353 + 354 + //copy the latitude and longitude into the request 355 + size_t msgsz = pos(msg, argv[1], argv[2]); 356 + //msgsz = size of what we're going to transmit 357 + 358 + //for (;;) { 359 + size_t rspsz = get(resp, sizeof(resp), msg, msgsz, &body); 360 + // if paths contains the keys, this contains the values 361 + jsv values[len(paths)]; 362 + 363 + parse: { 364 + pplt(body, body + (rspsz - (resp - body)), paths, paths+len(paths), values); 365 + 366 + pstr summary = values[0].s; 367 + float pcpint = values[1].f, 368 + temp = values[2].f, 369 + windspd = values[3].f; 370 + 371 + printf("%.1f° %%{F#ff9bbb}%.*s\n", 372 + summary.sz, 373 + summary.a, 374 + temp); 375 + } 376 + // dark sky's API allows us to make 1000 free requests a day. 377 + // let's try not to get too near that. 378 + // hours in day 24 - minutes in day 24 * 60 = 1440 379 + // so once a minute is almost half again too many 380 + // 1440 / 2 = 720 leaving reasonable refresh time without 381 + // going too near the limit. so we aim for one update 382 + // every two minutes. 383 + // sleep(60 * 2); 384 +// } 385 + 386 + return 0; 387 +}
Deleted tenki/tenki.cc version [eaa2ec3cc1].
1 -#include <stdio.h> 2 -#include <stdlib.h> 3 -#include <unistd.h> 4 -#include <string.h> 5 -#include <sys/socket.h> 6 -#include <netinet/in.h> 7 -#include <netdb.h> 8 -#include <stdint.h> 9 -#include <openssl/ssl.h> 10 - 11 -#define ds_apikey "a6aa0337fafd8b8fcfafe84a403ed24f" 12 -#define ds_lang "ja" 13 -#define ds_exclude "minutely,hourly,daily,alerts,flags" 14 - 15 -#define req "GET /forecast/" 16 -#define http "?exclude=" ds_exclude "&lang=" ds_lang " HTTP/1.1\r\nHost: api.darksky.net\r\n\r\n" 17 - 18 -#define len(x) (sizeof(x)/sizeof(*x)) 19 -#define start req ds_apikey "/" 20 -#define min(x,y) (x>y?y:x) 21 - 22 -SSL_CTX* sc; 23 -bool head(size_t* len, char* txt, char** body) { 24 - char* hend = strstr(txt, "\r\n\r\n"); 25 - if (hend == nullptr) return false; 26 - #define ctlhead "\r\nContent-Length:" 27 - char* ctl = strstr(txt, ctlhead); 28 - if (ctl == nullptr or ctl > hend) return false; 29 - ctl += len(ctlhead); 30 - *len = 0; 31 - while(*ctl != '\r') { 32 - if (*ctl >= '0' and *ctl <= '9') *len*=10,*len+=*ctl-'0'; 33 - ++ctl; 34 - } 35 - *len+=(hend-txt)+4; 36 - *body = hend+4; 37 - return true; 38 -} 39 -size_t get(char* resp, size_t max, const char* msg, size_t total, char** body){ 40 - 41 - int port = 443; 42 - const char* host = "api.darksky.net"; 43 - //printf("req: %s\n", msg); 44 - struct hostent* api; 45 - struct sockaddr_in api_addr; 46 - int sockfd, bytes; 47 - size_t sent, recd; 48 - 49 - sockfd = socket(AF_INET, SOCK_STREAM, 0); 50 - if (sockfd < 0) exit(2); 51 - SSL *con = SSL_new(sc); 52 - SSL_set_fd(con, sockfd); 53 - 54 - //printf("getting host\n"); 55 - api = gethostbyname(host); 56 - if (api == nullptr) exit(3); 57 - 58 - memset(&api_addr, 0, sizeof(api_addr)); 59 - api_addr.sin_family = AF_INET; 60 - api_addr.sin_port = htons(port); 61 - memcpy(&api_addr.sin_addr.s_addr, api -> h_addr, api -> h_length); 62 - 63 - //printf("connecting\n"); 64 - if (connect(sockfd,(struct sockaddr*)&api_addr,sizeof(api_addr))) 65 - exit(4); 66 - int err = SSL_connect(con); 67 - 68 - 69 - sent = 0; 70 -// printf("writing\n"); 71 - do { 72 - // printf("writing byte %x\n",*(msg+sent)); 73 - bytes = SSL_write(con,msg+sent,total-sent); 74 - if (bytes < 0) exit (4); 75 - if (bytes == 0) break; 76 - ++sent; 77 - } while (sent < total); 78 -// printf("receiving\n"); 79 - recd = 0; 80 - size_t resplen = max; 81 - bool rhead = false; 82 - do { 83 - // printf("\n\nreading - addr %x; max %d\n",resp+recd,resplen-recd); 84 - bytes = SSL_read(con,resp+recd,min(resplen-recd,15000)); 85 - if (bytes < 0) exit (5); 86 - if (bytes == 0) break; 87 - if(!rhead)rhead=head(&resplen, resp, body); 88 - // printf("got %d bytes: %s", bytes, resp+recd); 89 - recd += bytes; 90 - } while (recd < resplen - 1); 91 - 92 - close(sockfd); 93 - SSL_shutdown(con); 94 - 95 - return recd; 96 -} 97 -size_t pos(char* msg, const char* lat, const char* lng) { 98 - char* cur = msg + len(start) - 1; 99 - size_t latl = strlen(lat); 100 - size_t longl = strlen(lng); 101 - strcpy(cur, lat); cur += latl; 102 - *cur++=','; 103 - strcpy(cur, lng); cur += longl; 104 - strcpy(cur, http); cur += len(http); 105 - *cur--=0; 106 - return cur-msg; 107 -} 108 -bool estrc(size_t sz, const char* str1, const char* str2) { 109 - for(size_t i = 0;i<sz;++i) { 110 - if(*str1 == *str2) { 111 - ++str1; ++str2; 112 - } else if (*str2 =='\\') { 113 - ++str2; 114 - if(*str1 == *str2) { 115 - ++str1; ++str2; 116 - } else return false; 117 - } else { 118 - return false; 119 - } 120 - } 121 - return true; 122 -} 123 -struct pstr { 124 - size_t sz; 125 - const char* a; 126 -}; 127 -union jsv { 128 - float f; 129 - pstr s; 130 -}; 131 -/* void printkey(const char* key) { 132 - size_t len = *key++; 133 - for (size_t i = 0; i<len; ++i) { 134 - printf("/%.*s",*key,key+1); 135 - key += *key + 1; 136 - }; 137 - printf("\n"); 138 -} */ 139 -void pplt(const char* str, const char* const end, const char** keys, const char** const keyend, jsv* values) { 140 - // initialize parser state 141 - size_t depth = 0; 142 - const char* fld = nullptr; 143 - const char* path[32]; 144 - path[0] = nullptr; 145 - 146 - while(*str++!='{'); //cheat 147 - init: { 148 - if (keys > keyend) return; 149 - if (str > end) return; 150 - /* print_path: { 151 - printf("current path: /"); 152 - for (size_t i = 0; i < depth; ++i) { 153 - printf("%.*s/",strchr(path[i],'"')-path[i],path[i]); 154 - } 155 - printf("\n"); 156 - printf("current key: "); 157 - printkey(*keys); 158 - } */ 159 - parse_char: { 160 - switch(*str++) { 161 - case ' ': case '\t': case '\n': 162 - goto parse_char; 163 - case '"': 164 - path[depth] = str; 165 - goto path_find_quote_end; 166 - case '}': 167 - if (depth == 0) return; 168 - depth--; 169 - while(*str!=',') ++str; ++str; 170 - goto init; 171 - default: 172 - printf("found illegal char %c\n", *(str-1)); 173 - exit(6); 174 - } 175 - } 176 - path_find_quote_end: { 177 - switch (*str++) { 178 - case '\\': ++str; goto path_find_quote_end; 179 - case '"': goto read_value; 180 - default: goto path_find_quote_end; 181 - } 182 - } 183 - read_value: { 184 - if (*str++!=':') { 185 - printf("illegal char\n"); 186 - exit(6); 187 - } 188 - bool iskey; 189 - const char* key = *keys; 190 - jsv* value; 191 - if (depth + 1 != *key++) { 192 - iskey = false; 193 - goto comp; 194 - } else for (size_t i = 0; i <= depth; ++i) { 195 - if (estrc(*key, key+1, path[i])) { 196 - key += *key + 1; 197 - } else { 198 - iskey = false; 199 - goto comp; 200 - } 201 - } 202 - iskey = true; 203 - value = values; 204 - ++keys; ++values; 205 - comp: if (*str == '{') { 206 - ++depth; ++str; 207 - goto init; 208 - } else if (*str == '"') { 209 - goto copy_str_value; 210 - } else if (*str == '[') { 211 - goto skip_array; 212 - } else if ((*str >= '0' and *str <= '9') or *str=='-') { 213 - goto copy_int_value; 214 - } else { 215 - printf("illegal character found in value %c\n", *str); 216 - exit(6); 217 - } 218 - 219 - copy_str_value: { 220 - fld = ++str; 221 - while (*++str != '"') if (*str == '\\') { ++str; continue; } 222 - if (iskey) { 223 - value -> s.sz = str - fld; 224 - value -> s.a = fld; 225 - } 226 - while (*++str != ','); 227 - ++str; goto init; 228 - } 229 - skip_array: { 230 - size_t ard = 0; 231 - skip_loop: switch (*++str) { 232 - case '{': case '[': ++ard; goto skip_loop; 233 - case '"': goto skip_str; 234 - case '}': if (ard == 0) { 235 - printf("bad json\n"); 236 - exit(7); 237 - } else { --ard; goto skip_loop; } 238 - case ']': if (ard == 0) { 239 - if (*++str == ',') { ++str; goto init; } 240 - else goto init; 241 - } else { --ard; } 242 - default: goto skip_loop; 243 - } 244 - skip_str: while (*str != '"') if (*str == '\\') { str += 2; continue; } else ++str; goto skip_loop; 245 - } 246 - copy_int_value: { 247 - if (!iskey) { 248 - while(*str++!=',') if (str > end) return; 249 - goto init; 250 - } 251 - value -> f = 0; 252 - bool neg; 253 - if (*str == '-') { neg=true; ++str; } else neg=false; 254 - while(*str >= '0' and *str <= '9') { 255 - value -> f *= 10; 256 - value -> f += *str - '0'; 257 - ++str; 258 - } 259 - if(*str == '.') { 260 - float fac = 0.1; 261 - float val = 0; 262 - while(*++str >= '0' and *str <= '9') { 263 - val += (((float)(*str - '0')) * fac); 264 - fac *= 0.1; 265 - } 266 - value -> f += val; 267 - } 268 - if(neg) value -> f *= -1; 269 - if (*str == ',') { 270 - ++str; goto init; 271 - } else { 272 - printf("illegal character %.*s\n",15,str); 273 - exit(6); 274 - } 275 - } 276 - } 277 - } 278 -} 279 -int main(int argc, char** argv) { 280 - if (argc != 3) exit(1); 281 - SSL_load_error_strings(); 282 - SSL_library_init(); 283 - sc = SSL_CTX_new(SSLv23_client_method()); 284 - 285 - char msg[256] = start; 286 - char resp[32368]; 287 - char* body; 288 - 289 - // name the fields to extract from the json stream 290 - // note: MUST BE LISTED IN ORDER THEY APPEAR 291 - // paths are encoded as sequences of pstrings 292 - // initial value indicates depth of path 293 - // TODO: performance worth lack of flexibility? 294 - const char* paths[] = { 295 - "\2\x9""currently\7summary", 296 - "\2\x9""currently\xfprecipIntensity", 297 - "\2\x9""currently\xbtemperature", 298 - "\2\x9""currently\x9windspeed", 299 - }; 300 - 301 - size_t msgsz = pos(msg, argv[1], argv[2]); 302 - //msgsz = size of transmit 303 - //for (;;) { 304 - size_t rspsz = get(resp, sizeof(resp), msg, msgsz, &body); 305 - // if paths contains the keys, this contains the values 306 - jsv values[len(paths)]; 307 - 308 - parse: { 309 - pplt(body, body + (rspsz - (resp - body)), paths, paths+len(paths), values); 310 - 311 - pstr summary = values[0].s; 312 - float pcpint = values[1].f, 313 - temp = values[2].f, 314 - windspd = values[3].f; 315 - 316 - printf("%.1f° %%{F#ff9bbb}%.*s\n", 317 - summary.sz, 318 - summary.a, 319 - temp); 320 - } 321 - // dark sky's API allows us to make 1000 free requests a day. 322 - // let's try not to get too near that. 323 - // hours in day 24 - minutes in day 24 * 60 = 1440 324 - // so once a minute is almost half again too many 325 - // 1440 / 2 = 720 leaving reasonable refresh time without 326 - // going too near the limit. so we aim for one update 327 - // every two minutes. 328 - // sleep(60 * 2); 329 -// } 330 - 331 - return 0; 332 -}