mbed Weather Platform firmware http://mbed.org/users/okini3939/notebook/mbed-weather-platform-firmware/
Dependencies: EthernetNetIf SDHCFileSystem I2CLEDDisp Agentbed NTPClient_NetServices mbed BMP085 HTTPClient ConfigFile I2CLCD
Revision 18:9286e5010c14, committed 2011-05-31
- Comitter:
- okini3939
- Date:
- Tue May 31 15:40:14 2011 +0000
- Parent:
- 17:7c9d111a5d45
- Child:
- 19:69b77f9e0446
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Stack.lib Tue May 31 15:40:14 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/okini3939/code/Stack/#d76eb9986be8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/action.cpp Tue May 31 15:40:14 2011 +0000 @@ -0,0 +1,417 @@ +/** @file + * @brief mbed Weather Platform + */ +#include "mbed.h" +#include "weather.h" +#include "Stack.h" + + +struct MNE_str { + eMNEMONIC mne; + char str[5]; +}; + +#define CF_MNE_NUM 25 +const struct MNE_str mne_str[CF_MNE_NUM] = { + {MNE_LD, "LD"}, {MNE_LDI, "LDI"}, {MNE_LDP, "LDP"}, {MNE_LDF, "LDF"}, + {MNE_ALD, "@LD"}, {MNE_ALDI, "@LDI"}, {MNE_ALDP, "@LDP"}, {MNE_ALDF, "@LDF"}, + {MNE_OR, "OR"}, {MNE_ORI, "ORI"}, {MNE_ORP, "ORP"}, {MNE_ORF, "ORF"}, + {MNE_AND, "AND"}, {MNE_ANI, "ANI"}, {MNE_ANDP, "ANDP"}, {MNE_ANDF, "ANDF"}, + {MNE_ORB, "ORB"}, {MNE_ANB, "ANB"}, {MNE_INV, "INV"}, + {MNE_MPS, "MPS"}, {MNE_MRD, "MRD"}, {MNE_MPP, "MPP"}, + {MNE_OUT, "OUT"}, {MNE_SET, "SET"}, {MNE_RST, "RST"}, +}; + +struct EXP_str { + eEXPRESSION exp; + char str[3]; +}; + +#define CF_EXP_NUM 10 +const struct EXP_str exp_str[CF_EXP_NUM] = { + {EXP_EQ, "=="}, {EXP_EQ, "="}, {EXP_NE, "!="}, {EXP_NE, "<>"}, + {EXP_LT, "<="}, {EXP_LE, "<"}, {EXP_GT, ">"}, {EXP_GE, ">="}, + {EXP_MOD, "%"}, {EXP_NMOD, "!%"}, +}; + + +int check_exp (Sensor *s, int i) { + int keynum; + float value, check; + struct tm *tim; + + tim = localtime(&s->sec); + keynum = conf.actions[i].keynum; + check = conf.actions[i].value; + + // left value + value = 0; + switch (conf.actions[i].key) { + case 'P': + value = s->pres; + break; + case 'T': + value = s->temp; + break; + case 'H': + value = s->humi; + break; + case 'A': + value = s->anemo; + break; + case 'V': + value = s->vane; + break; + case 'R': + value = s->rain; + break; + case 'L': + value = s->light; + break; + case 'U': + value = s->uv; + break; + case 'M': + value = s->moist; + break; + + case 'y': + value = tim->tm_year + 1900; + break; + case 'm': + value = tim->tm_mon; + break; + case 'd': + value = tim->tm_mday; + break; + case 'h': + value = tim->tm_hour; + break; + case 'i': + value = tim->tm_min; + break; + case 's': + value = tim->tm_sec; + break; + + case '0': + value = 0; + break; + case '1': + value = 1; + break; + + case 'I': // INPUT + if (keynum >= INPUT_NUM) break; + value = s->input[keynum]; + break; + case 'Q': // OUTPUT + if (keynum >= OUTPUT_NUM) break; + value = s->output[keynum]; + break; + case 't': // Timer + if (keynum >= TIMER_NUM) break; + if (conf.actions[i].expression == EXP_NULL) { + value = s->timer_flg[keynum] && s->timer_cnt[keynum] == 0; + } else { + value = s->timer_cnt[keynum]; + } + break; + case 'c': // Counter + if (keynum >= COUNTER_NUM) break; + value = s->count[keynum]; + break; + } + + // expression, right value + switch (conf.actions[i].expression) { + case EXP_EQ: + return value == check; + case EXP_NE: + return value != check; + case EXP_LE: + return value <= check; + case EXP_LT: + return value < check; + case EXP_GE: + return value >= check; + case EXP_GT: + return value > check; + case EXP_MOD: + return (int)value % (int)check; + case EXP_NMOD: + return ! (int)value % (int)check; + } + + return value != 0; +} + +void exec_action (int i, int reg, eMNEMONIC sr) { + static int tw_old = 0; + int keynum; + + keynum = conf.actions[i].keynum; + + switch (conf.actions[i].key) { + case 'P': // Pachube + if (conf.ipaddr[0] && conf.pachube_apikey[0] && conf.pachube_feedid[0] && reg) { + pachube(csv); + } + break; + + case 'S': // Weather Stations + if (conf.ipaddr[0] && conf.stations_id[0] && conf.stations_pin[0] && reg) { + weatherstations(); + } + break; + + case 'T': // Twitter + if (conf.ipaddr[0] && conf.twitter_user[0] && conf.twitter_pwd[0]) { + if (sr == MNE_OUT && reg) { + twitter(keynum); + } else + if (sr == MNE_SET && reg && tw_old == 0) { + twitter(keynum); + tw_old = 1; + } else + if (reg == 0) { + tw_old = 0; + } + } + break; + + case 'X': // XBee + if (reg) { + xbee.printf(csv); + } + break; + + case 'Q': // OUTPUT + if (keynum >= OUTPUT_NUM) break; + if (sr == MNE_OUT) { + sensor.output[keynum] = reg; + } else + if (sr == MNE_SET && reg) { + sensor.output[keynum] = 1; + } else + if (sr == MNE_RST && reg) { + sensor.output[keynum] = 0; + } + break; + + case 't': // Timer + if (keynum >= TIMER_NUM) break; + if (sr == MNE_OUT) { + // set timer + if (sensor.timer_flg[keynum]) sensor.timer_cnt[keynum] = conf.actions[i].value * 10; + sensor.timer_flg[keynum] = reg; + } else + if (sr == MNE_SET && reg) { + sensor.timer_cnt[keynum] = conf.actions[i].value * 10; + } else + if (sr == MNE_RST && reg) { + sensor.timer_flg[keynum] = 0; + } + break; + + case 'c': // Counter + if (keynum >= COUNTER_NUM) break; + if (sr == MNE_OUT && reg) { + sensor.count[keynum] ++; + } else + if (sr == MNE_RST && reg) { + sensor.count[keynum] = 0; + } + + } + +#ifdef DEBUG + pc.printf("[%c%d] reg=%d sr=%d\r\n", conf.actions[i].key, keynum, reg, sr); +#endif +} + +int action (char enable) { + int i; + char j, reg, ena; + Stack stack(40); + + sensor.sec = time(NULL) + (60 * 60 * 9); + sensor.input[0] = conf.inputtype ? *aimoist > 0.5 : 0; + sensor.input[1] = swin2; + + for(i = 0; i < conf.actionscount; i ++) { + switch (conf.actions[i].mnemonic) { + case MNE_LD: + stack.push(reg); + reg = check_exp(&sensor, i); + ena = enable; + break; + case MNE_LDI: + stack.push(reg); + reg = ! check_exp(&sensor, i); + ena = enable; + break; + case MNE_LDP: + stack.push(reg); + reg = check_exp(&sensor, i) && ! check_exp(&sensor_old, i); + ena = enable; + break; + case MNE_LDF: + stack.push(reg); + reg = ! check_exp(&sensor, i) && check_exp(&sensor_old, i); + ena = enable; + break; + + case MNE_ALD: + stack.push(reg); + reg = check_exp(&sensor, i); + ena = 1; + break; + case MNE_ALDI: + stack.push(reg); + reg = ! check_exp(&sensor, i); + ena = 1; + break; + case MNE_ALDP: + stack.push(reg); + reg = check_exp(&sensor, i) && ! check_exp(&sensor_old, i); + ena = 1; + break; + case MNE_ALDF: + stack.push(reg); + reg = ! check_exp(&sensor, i) && check_exp(&sensor_old, i); + ena = 1; + break; + + case MNE_AND: + reg = reg && check_exp(&sensor, i); + break; + case MNE_ANI: + reg = reg && ! check_exp(&sensor, i); + break; + case MNE_ANDP: + reg = reg && (check_exp(&sensor, i) && ! check_exp(&sensor_old, i)); + break; + case MNE_ANDF: + reg = reg && (! check_exp(&sensor, i) && check_exp(&sensor_old, i)); + break; + + case MNE_OR: + reg = reg || check_exp(&sensor, i); + break; + case MNE_ORI: + reg = reg || ! check_exp(&sensor, i); + break; + case MNE_ORP: + reg = reg || (check_exp(&sensor, i) && ! check_exp(&sensor_old, i)); + break; + case MNE_ORF: + reg = reg || (! check_exp(&sensor, i) && check_exp(&sensor_old, i)); + break; + + case MNE_ANB: + if (stack.pop(&j)) return -1; + reg = reg && j; + break; + case MNE_ORB: + if (stack.pop(&j)) return -1; + reg = reg || j; + break; + + case MNE_INV: + reg = ! reg; + break; + + case MNE_MPS: + stack.push(reg); + break; + case MNE_MRD: + stack.read(®); + break; + case MNE_MPP: + stack.pop(®); + break; + + case MNE_OUT: + case MNE_SET: + case MNE_RST: + if (ena) exec_action(i, reg, conf.actions[i].mnemonic); + break; + } + } + + led3 = swout1 = sensor.output[0]; + led4 = swout2 = sensor.output[1]; +#ifdef DEBUG + printf("timer %d\r\n", sensor.timer_cnt[0]); +#endif + + sensor_old = sensor; + return 0; +} + +void load_exp (int i, char *buf) { + int j, len; + char *tmp; + + conf.actions[i].key = buf[0]; + conf.actions[i].keynum = strtol(&buf[1], &tmp, 10); + conf.actions[i].expression = EXP_NULL; + conf.actions[i].value = 0; + + if (tmp) { + for (j = 0; j < CF_EXP_NUM; j ++) { + len = strlen(exp_str[j].str); + if (strncmp(tmp, exp_str[j].str, len) == 0 && tmp[len] >= '0' && tmp[len] <= '9') { + conf.actions[i].expression = exp_str[j].exp; + conf.actions[i].value = atof(&tmp[len]); + break; + } + } + } +} + +void load_action (char *file) { + FILE *fp; + char c; + int i, j, count, len; + char buf[20]; + + fp = fopen(file, "r"); + if (fp == NULL) return; + + i = 0; + for (count = 0; count < CF_ACTION_NUM;) { + c = fgetc(fp); + if (feof(fp)) break; + + if (c != '\r' && c != '\n' && i < 40 - 1) { + buf[i] = c; + i ++; + continue; + } + buf[i] = 0; + + for (j = 0; j < CF_MNE_NUM; j ++) { + len = strlen(mne_str[j].str); + if (strncmp(buf, mne_str[j].str, len) == 0 && buf[len] == ' ') { + conf.actions[count].mnemonic = mne_str[j].mne; + load_exp(count, &buf[len + 1]); + count ++; + break; + } + if (strncmp(buf, "END", 3) == 0) break; + } + + i = 0; + } + + fclose(fp); + conf.actionscount = count; + +#ifdef DEBUG + for (i = 0; i < count; i ++) { + pc.printf("M=%d [%c%d] E=%d V=%f\r\n", conf.actions[i].mnemonic, conf.actions[i].key, conf.actions[i].keynum, conf.actions[i].expression, conf.actions[i].value); + } +#endif +}
--- a/conf.cpp Fri Apr 08 15:59:29 2011 +0000 +++ b/conf.cpp Tue May 31 15:40:14 2011 +0000 @@ -2,14 +2,9 @@ * @brief mbed Weather Platform */ #include "mbed.h" -#include "conf.h" +#include "weather.h" #include "ConfigFile.h" -extern Serial xbee; -extern Config conf; -extern Sensor sensor, offset, sensor_old; - -void int_counter(); char* chop (char *s) { int i; @@ -24,237 +19,6 @@ return s; } -int check_action (char type) { - int i, j, count; - float value, vold; - time_t sec = time(NULL) + (60 * 60 * 9); - struct tm *tim = localtime(&sec); - - for(i = 0; i < conf.actionscount; i ++) { - if (conf.actions[i].action != type) continue; - - count = 0; - for (j = 0; j < conf.actions[i].count; j ++) { - switch (conf.actions[i].exps[j].key) { - case 'P': - value = sensor.pres; - vold = sensor_old.pres; - break; - case 'T': - value = sensor.temp; - vold = sensor_old.temp; - break; - case 'H': - value = sensor.humi; - vold = sensor_old.humi; - break; - case 'A': - value = sensor.anemo; - vold = sensor_old.anemo; - break; - case 'V': - value = sensor.vane; - vold = sensor_old.vane; - break; - case 'R': - value = sensor.rain; - vold = sensor_old.rain; - break; - case 'L': - value = sensor.light; - vold = sensor_old.light; - break; - case 'U': - value = sensor.uv; - vold = sensor_old.uv; - break; - case 'M': - value = sensor.moist; - vold = sensor_old.moist; - break; - - case 'y': - value = tim->tm_year + 1900; - break; - case 'm': - value = tim->tm_mon; - break; - case 'd': - value = tim->tm_mday; - break; - case 'h': - value = tim->tm_hour; - break; - case 'i': - value = tim->tm_min; - break; - case 's': - value = tim->tm_sec; - break; - - default: - value = 0; - break; - } - - switch (conf.actions[i].exps[j].expression) { - case EXP_EQ: - if (value == conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_NE: - if (value != conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_LE: - if (value <= conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_LT: - if (value < conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_GE: - if (value >= conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_GT: - if (value > conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_MOD: - if ((int)value % (int)conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_NMOD: - if (! (int)value % (int)conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_FALL: - if (value < conf.actions[i].exps[j].value && vold >= conf.actions[i].exps[j].value) { - count ++; - } - break; - case EXP_RISE: - if (value > conf.actions[i].exps[j].value && vold <= conf.actions[i].exps[j].value) { - count ++; - } - break; - - default: - count ++; - break; - } - } - if (count == conf.actions[i].count) { - return conf.actions[i].sub ? conf.actions[i].sub : ' '; - } - } - return 0; -} - -void add_actionsub (struct tExpression *exp, char *buf) { - - exp->key = buf[0]; - - switch (buf[1]) { - case '=': - if (buf[2] == '=') { - exp->expression = EXP_EQ; - exp->value = atof(&buf[3]); - } - break; - - case '!': - if (buf[2] == '=') { - exp->expression = EXP_NE; - exp->value = atof(&buf[3]); - } else - if (buf[2] == '%') { - exp->expression = EXP_NMOD; - exp->value = atof(&buf[3]); - } - break; - - case '<': - if (buf[2] == '=') { - exp->expression = EXP_LE; - exp->value = atof(&buf[3]); - } else { - exp->expression = EXP_LT; - exp->value = atof(&buf[2]); - } - break; - - case '>': - if (buf[2] == '=') { - exp->expression = EXP_GE; - exp->value = atof(&buf[3]); - } else { - exp->expression = EXP_GT; - exp->value = atof(&buf[2]); - } - break; - - case '%': - exp->expression = EXP_MOD; - exp->value = atof(&buf[2]); - break; - - case '_': - exp->expression = EXP_FALL; - exp->value = atof(&buf[2]); - break; - case '^': - exp->expression = EXP_RISE; - exp->value = atof(&buf[2]); - break; - - default: - exp->expression = EXP_NULL; - break; - } -} - -void add_action (char *buf) { - int i, len, count; - char c; - char *tmp = NULL; - - if (conf.actionscount >= CF_ACTION_NUM) return; - -// conf.actions[conf.actionscount].action = atoi(&buf[0]); - conf.actions[conf.actionscount].action = buf[0]; - conf.actions[conf.actionscount].sub = buf[1]; - - count = 0; - strcat(buf, "\n"); - len = strlen(buf); - for (i = 1; i < len; i ++) { - c = buf[i]; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { - buf[i] = 0; - if (count) { - add_actionsub(&conf.actions[conf.actionscount].exps[count - 1], tmp); - } - if (count >= CF_ACTION_EXPS || c == '\n') break; - tmp = &buf[i + 1]; - count ++; - } - } - - conf.actions[conf.actionscount].count = count; - conf.actionscount ++; -} - int config (char *file) { int i; ConfigFile cfg; @@ -371,13 +135,6 @@ conf.inputtype = (enum eINPUTTYPE)atoi(chop(buf)); } - for (i = 0; i < CF_ACTION_NUM; i ++) { - sprintf(key, "ACTION[%d]", i); - if (cfg.getValue(key, buf, sizeof(buf))) { - add_action(chop(buf)); - } - } - if (cfg.getValue("OFFSET[P]", buf, sizeof(buf))) { offset.pres = atof(chop(buf)); }
--- a/conf.h Fri Apr 08 15:59:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** @file - * @brief mbed Weather Platform - */ -#include "mbed.h" -#include "EthernetNetIf.h" -#include "I2CLEDDisp.h" -#include "I2CLCD.h" - -#define CONFIG_FILE "weather.cfg" - - -#define CF_MAXLEN_VALUE 128 -#define CF_ACTION_EXPS 10 -#define CF_ACTION_NUM 10 -#define CF_TWITTER_NUM 5 - -enum eEXPRESSION { - EXP_NULL, - EXP_EQ, - EXP_NE, - EXP_LE, - EXP_LT, - EXP_GE, - EXP_GT, - EXP_MOD, - EXP_NMOD, - EXP_FALL, - EXP_RISE, -}; - -enum eINPUTTYPE { - INPUT_MOIST = 0, - INPUT_FALL = 1, - INPUT_RISE = 2, - INPUT_CPM = 4, -}; - -struct tExpression { - char key; - enum eEXPRESSION expression; - float value; -}; - -struct tAction { - char action; - char sub; - int count; - struct tExpression exps[CF_ACTION_EXPS]; -}; - -struct Sensor { - float pres, temp, humi, light, anemo, vane, rain, uv, moist, temp2; -}; - -struct Config { - int interval; - IpAddr ipaddr, netmask, gateway, nameserver; - char ntpserver[32]; - int filetype, actionscount; - struct tAction actions[CF_ACTION_NUM]; - char pachube_apikey[70], pachube_feedid[8]; - char twitter_user[30], twitter_pwd[30], twitter_mesg[CF_TWITTER_NUM][CF_MAXLEN_VALUE]; - char stations_id[8], stations_pin[34]; - char snmp_commname[30]; - char lcd_mesg[CF_MAXLEN_VALUE]; - enum I2CLCDType lcdtype; - enum I2CLCDConfig lcdconf; - char leddisp_mesg[CF_MAXLEN_VALUE]; - enum eINPUTTYPE inputtype; -}; - -int config (char *);
--- a/func.cpp Fri Apr 08 15:59:29 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -#include "mbed.h" -#include "ConfigFile.h" -#include "SDHCFileSystem.h" -#include "EthernetNetIf.h" -#include "NTPClient.h" -#include "HTTPClient.h" -#include "conf.h" - -#define TIMEZONE 9 -//#define NONBLOCKING -/** @file - * @brief mbed Weather Platform - */ - -#define STATION_URL "http://weather.sugakoubou.com/p" -#define TWITTER_URL "http://api.supertweet.net/1/statuses/update.xml" - -extern Serial pc; -extern int seq; -extern char filename[]; -extern Config conf; -extern DigitalOut led_y, led2; - -extern EthernetNetIf *eth; -extern NTPClient *ntp; -extern HTTPClient *clientP, *clientT; -extern Sensor sensor; - -void writefile (char *buf) { - FILE *fp; - - fp = fopen(filename, "a"); - if (fp) { - fprintf(fp, buf); - fclose(fp); - } else { - led2 = 0; - conf.filetype = 0; - } -} - -void weatherstations () { - char post_data[200]; - HTTPResult ret; - HTTPText postContent("application/x-www-form-urlencoded"); - - led_y = 0; - strcpy(post_data, "fcd="); - strcat(post_data, conf.stations_id); - strcat(post_data, "&pin="); - strcat(post_data, conf.stations_pin); - sprintf(&post_data[strlen(post_data)], "&d0=%.2f&d1=%.2f&d2=%.2f&d3=%.2f&d4=%.2f&d5=%.2f&d6=%.2f&d7=%.2f&d8=%.2f&d9=%.2f", - sensor.pres, sensor.temp, sensor.humi, sensor.anemo, sensor.vane, sensor.rain, sensor.light, sensor.uv, sensor.moist, sensor.temp2); - postContent.puts(post_data); - -#ifdef NONBLOCKING - Net::poll(); - ret = clientP->post(STATION_URL, postContent, NULL, &cb_clientP); - Net::poll(); -#else - ret = clientP->post(STATION_URL, postContent, NULL); -#endif - - if (ret != HTTP_OK && ret != HTTP_PROCESSING) { - pc.printf("error: Weather Statuons %d\r\n", ret); - } -} - -void pachube (char *buf) { - char uri[100]; - HTTPResult ret; - HTTPText csvContent("text/csv"); - - led_y = 0; - clientP->setRequestHeader("X-PachubeApiKey", conf.pachube_apikey); - csvContent.set(buf); - strcpy(uri, "http://api.pachube.com/v1/feeds/"); - strcat(uri, conf.pachube_feedid); - strcat(uri, ".csv?_method=put"); -#ifdef NONBLOCKING - Net::poll(); - ret = clientP->post(uri, csvContent, NULL, &cb_clientP); - Net::poll(); -#else - ret = clientP->post(uri, csvContent, NULL); -#endif - - if (ret != HTTP_OK && ret != HTTP_PROCESSING) { - pc.printf("error: Pachube %d\r\n", ret); - } -} - -void cb_clientP (HTTPResult status) { - if (status != HTTP_OK) { - pc.printf("Pachube failure (%d)\r\n", status); -// pc.printf("Pachube failure (%d, %d)\r\n", status, clientP->getHTTPResponseCode()); - } -} - -char *fmtstr (char *fmt, char *buf, int len) { - int i, j, flg; - char c; - float value; - time_t sec = time(NULL); - struct tm *tim = localtime(&sec); - - j = 0; - for (i = 0; i < strlen(fmt) && j < len; i ++) { - c = fmt[i]; - if (c == '%') { - flg = 0; - i ++; - c = fmt[i]; - - if (c == '.') { - // float format - if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { - flg = fmt[i + 1] - '0'; - i ++; - - c = fmt[i + 1]; - i ++; - } - } - - switch (c) { - case 'P': - value = sensor.pres; - break; - case 'T': - value = sensor.temp; - break; - case 'H': - value = sensor.humi; - break; - case 'A': - value = sensor.anemo; - break; - case 'V': - value = sensor.vane; - break; - case 'R': - value = sensor.rain; - break; - case 'L': - value = sensor.light; - break; - case 'U': - value = sensor.uv; - break; - case 'M': - value = sensor.moist; - break; - - case 'y': - value = tim->tm_year + 1900; - break; - case 'm': - value = tim->tm_mon; - break; - case 'd': - value = tim->tm_mday; - break; - case 'h': - value = tim->tm_hour; - break; - case 'i': - value = tim->tm_min; - break; - case 's': - value = tim->tm_sec; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - // Ascii - c = c - '0'; - if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { - c = (c << 3) | (fmt[i + 1] - '0'); - i ++; - if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { - c = (c << 3) | (fmt[i + 1] - '0'); - i ++; - } - } - buf[j] = c; - j ++; - continue; - - default: - buf[j] = c; - j ++; - continue; - } - - switch (flg) { - case 1: - sprintf(&buf[j], "%.1f", value); - break; - case 2: - sprintf(&buf[j], "%.2f", value); - break; - default: - sprintf(&buf[j], "%02d", (int)value); - break; - } - j = strlen(buf); - } else { - buf[j] = c; - j ++; - } - } - buf[j] = 0; - return buf; -} - -void twitter (int num) { - HTTPMap msg; - HTTPResult ret; - char buf[170]; - - led_y = 0; - fmtstr(conf.twitter_mesg[num], buf, sizeof(buf)); - msg["status"] = buf; - - clientT->basicAuth(conf.twitter_user, conf.twitter_pwd); -#ifdef NONBLOCKING - Net::poll(); - ret = clientT->post(TWITTER_URL, msg, NULL, &cb_clientT); - Net::poll(); -#else - ret = clientT->post(TWITTER_URL, msg, NULL); -#endif - - if (ret != HTTP_OK && ret != HTTP_PROCESSING) { - pc.printf("error: Twitter %d\r\n", ret); - } -} - -void ntpdate () { - ntp = new NTPClient; - Host ntpserver(IpAddr(), 123, conf.ntpserver); - - led_y = 0; -#ifdef NONBLOCKING - Net::poll(); - ntp->setTime(ntpserver, &cb_settime); - Net::poll(); -#else - ntp->setTime(ntpserver); - time_t sec = time(NULL) + (60 * 60 * TIMEZONE); - set_time(sec); -#endif -} - -void cb_settime (NTPResult status) { - if (status == NTP_OK) { - led_y = 0; - time_t sec = time(NULL) + (60 * 60 * TIMEZONE); - set_time(sec); - pc.printf("Ntp success: %s\r\n", ctime(&sec)); - } else { - pc.printf("Ntp failure (%d)\r\n", status); - } -// ntp->close(); -}
--- a/main.cpp Fri Apr 08 15:59:29 2011 +0000 +++ b/main.cpp Tue May 31 15:40:14 2011 +0000 @@ -8,7 +8,7 @@ * @brief mbed Weather Platform */ -#define VERSION "mbed Weather Platform 0.2.1 (C) 2011 Suga koubou Co.,Ltd." +#define VERSION "mbed Weather Platform 0.3.0 (C) 2011 Suga koubou Co.,Ltd." //#define NONBLOCKING // ethernet function non-bloking @@ -22,18 +22,20 @@ #include "NTPClient.h" #include "HTTPClient.h" #include "Agentbed.h" -#include "conf.h" +#include "weather.h" #include "I2CLEDDisp.h" #include "I2CLCD.h" Serial pc(USBTX, USBRX), xbee(p13, p14); -int seq = 0; +volatile int seq = 0; char filename[20]; +char csv[100]; struct Config conf; DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); -LocalFileSystem local("local"); -SDFileSystem sd(p5, p6, p7, p8, "sd"); +LocalFileSystem *local; +SDFileSystem *sd; MSCFileSystem *usb; +DigitalIn sd_cd(p21); // Sensors struct Sensor sensor, offset, sensor_old; @@ -44,13 +46,14 @@ AnalogIn ailight(p16), aiuv(p17); AnalogIn *aimoist; InterruptIn *intcounter; -int count_counter; -unsigned long lastCountTime; +volatile int count_counter; +volatile unsigned long lastCountTime; +DigitalIn swin2(p19); DigitalOut swout1(p29), swout2(p30); I2CLEDDisp *leddisp; I2CLCD *lcd; -int ledpos, ledflg; +volatile int ledpos, ledflg; char ledbuf[200]; Ticker ticker; @@ -61,17 +64,6 @@ DigitalOut led_g2(p24),led_g(p25), led_y(p26); DigitalIn eth_link(P1_25), eth_speed(P1_26); -extern AgentbedClass Agentbed; -extern uint32_t locUpTime; - -void writefile (char *); -void pachube (char *); -char *fmtstr (char *, char *, int); -void twitter (int); -void weatherstations (); -void ntpdate (); -int check_action (char); -void pduReceived (); float get_photo (AnalogIn &ain) { float f; @@ -106,8 +98,10 @@ float t; if (flg) { + // count t = (float)count_counter; } else { + // count/min if (locUpTime > lastCountTime) { t = (float)(locUpTime - lastCountTime) / 6000.0; } else { @@ -120,10 +114,15 @@ return t; } +// Interrupt 10Hz +void isr_timer () { + int i; + static int ledfreq = 0; -void ledscroll () { - + // LED Display scroll if (conf.leddisp_mesg[0]) { + ledfreq ++; + if (ledfreq > LED_FREQ) { int i, addr, len; len = strlen(ledbuf); @@ -140,53 +139,33 @@ if (ledpos >= len + 4) { ledpos = -4; } + + ledfreq = 0; + } } - locUpTime = locUpTime + 40; // 0.4s - led_y = 1; -} - -void action (char *buf) { - int i; - - i = check_action('A'); - if (i) { - swout1 = (i == ' ' ? 1 : i - '0'); - led3 = swout1; - } - i = check_action('B'); - if (i) { - swout2 = (i == ' ' ? 1 : i - '0'); - led4 = swout2; + // timer + for (i = 0; i < TIMER_NUM; i ++) { + if (sensor.timer_flg[i] && sensor.timer_cnt[i]) sensor.timer_cnt[i] --; } - if (check_action('P')) { - if (conf.ipaddr[0] && conf.pachube_apikey[0] && conf.pachube_feedid[0]) { - pachube(buf); - } - } - i = check_action('T'); - if (i) { - if (conf.ipaddr[0] && conf.twitter_user[0] && conf.twitter_pwd[0]) { - twitter(i == ' ' ? 0 : i - '0'); - } - } - if (check_action('S')) { - if (conf.ipaddr[0] && conf.stations_id[0] && conf.stations_pin[0]) { - weatherstations(); - } - } - if (check_action('X')) { - xbee.printf(buf); - } - sensor_old = sensor; + // uptime + locUpTime = locUpTime + 10; + led_y = 1; } void init () { FILE *fp; - if (config("/sd/" CONFIG_FILE) == -1) { + // load config + sd = new SDFileSystem(p5, p6, p7, p8, "sd"); + if (config("/sd/" CONFIG_FILE) == 0) { + load_action("/sd/" ACTION_FILE); + } else { + delete sd; + local = new LocalFileSystem("local"); pc.printf("local strage\r\n", conf.interval); config("/local/" CONFIG_FILE); + load_action("/local/" ACTION_FILE); } pc.printf("\r\nInterval: %d sec\r\n", conf.interval); @@ -253,7 +232,7 @@ if (conf.filetype) { // seq num - + if (conf.filetype == 1) { strcpy(filename, "/sd"); } else @@ -262,7 +241,6 @@ strcpy(filename, "/usb"); } strcat(filename, "/weather.seq"); - // load fp = fopen(filename, "r"); if (fp) { @@ -270,7 +248,8 @@ fclose(fp); } seq ++; - // save + + // save CSV fp = fopen(filename, "w"); if (fp) { fprintf(fp, "%d", seq); @@ -289,6 +268,7 @@ pc.printf("Actions: %d\r\n", conf.actionscount); + // moist sensor or counter if (conf.inputtype & INPUT_FALL) { intcounter = new InterruptIn(p18); intcounter->fall(&int_counter); @@ -307,7 +287,6 @@ int main () { Timer timer; time_t sec; - char buf[100]; swout1 = 0; swout2 = 0; @@ -315,15 +294,18 @@ ledpos = -4; ledflg = 0; strcpy(ledbuf, VERSION); - ticker.attach(&ledscroll, 0.4); + + ticker.attach(&isr_timer, 0.1); // Interrupt 10Hz init(); pc.printf("%s\r\n\r\n", VERSION); if (conf.filetype) { - strcpy(buf, "date,pres(hPa),temp(`C),humi(%%),anemo(m/s),vane(`),rain(mm),light(lx),uv(mW/cm2),moist(kohm),\r\n"); - writefile(buf); + // CSV header + strcpy(csv, "date,pres(hPa),temp(`C),humi(%%),anemo(m/s),vane(`),rain(mm),light(lx),uv(mW/cm2),moist(kohm),\r\n"); + writefile(csv); } - + + // I2C LED Display (print version) if (conf.leddisp_mesg[0]) { ledpos = -4; sec = time(NULL); @@ -353,7 +335,7 @@ led1 = 0; sec = time(NULL); - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&sec)); + strftime(csv, sizeof(csv), "%Y-%m-%d %H:%M:%S", localtime(&sec)); // sensors __disable_irq(); @@ -371,23 +353,27 @@ sensor.light = get_photo(ailight); if (conf.inputtype == INPUT_MOIST) { + // moist sensor sensor.moist = get_moist(*aimoist); } else { + // counter sensor.moist = get_counter(conf.inputtype & INPUT_CPM ? 0 : 1); } sensor.uv = get_uv(aiuv); - sprintf(&buf[strlen(buf)], ",%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\r\n", + sprintf(&csv[strlen(csv)], ",%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\r\n", sensor.pres, sensor.temp, sensor.humi, sensor.anemo, sensor.vane, sensor.rain, sensor.light, sensor.uv, sensor.moist, sensor.temp2); if (conf.filetype) { - // csv - writefile(buf); + // CSV + writefile(csv); } __enable_irq(); - pc.printf(buf); + pc.printf(csv); - action(&buf[20]); + // in/out + action(1); + // I2C LED Display if (conf.leddisp_mesg[0]) { if (ledflg) { ledpos = -4; @@ -395,7 +381,9 @@ } ledflg = 1; } + // I2C LCD if (conf.lcd_mesg[0]) { + char buf[80]; fmtstr(conf.lcd_mesg, buf, sizeof(buf)); lcd->cls(); lcd->puts(buf); @@ -403,10 +391,15 @@ led1 = 1; + // interval (wait) while (timer.read() < conf.interval) { -// wait(1); -// pc.putc('.'); - wait_ms(1); + wait_ms(100); + + // in/out (timer) + if (locUpTime % 100 == 0) + action(0); + + // ethernet LED if (conf.ipaddr[0]) { led_g = eth_link ? 1 : 0; led_g2 = 1; @@ -415,7 +408,8 @@ led_g2 = 0; } Net::poll(); - + + // for debug if (pc.readable()) { int i; i = pc.getc();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/net.cpp Tue May 31 15:40:14 2011 +0000 @@ -0,0 +1,265 @@ +#include "mbed.h" +#include "ConfigFile.h" +#include "SDHCFileSystem.h" +#include "EthernetNetIf.h" +#include "NTPClient.h" +#include "HTTPClient.h" +#include "weather.h" + +/** @file + * @brief mbed Weather Platform + */ + +#define TIMEZONE 9 +//#define NONBLOCKING + +#define STATION_URL "http://weather.sugakoubou.com/p" +#define TWITTER_URL "http://api.supertweet.net/1/statuses/update.xml" + + +void writefile (char *buf) { + FILE *fp; + + fp = fopen(filename, "a"); + if (fp) { + fprintf(fp, buf); + fclose(fp); + } else { + led2 = 0; + conf.filetype = 0; + } +} + +void weatherstations () { + char post_data[200]; + HTTPResult ret; + HTTPText postContent("application/x-www-form-urlencoded"); + + led_y = 0; + strcpy(post_data, "fcd="); + strcat(post_data, conf.stations_id); + strcat(post_data, "&pin="); + strcat(post_data, conf.stations_pin); + sprintf(&post_data[strlen(post_data)], "&d0=%.2f&d1=%.2f&d2=%.2f&d3=%.2f&d4=%.2f&d5=%.2f&d6=%.2f&d7=%.2f&d8=%.2f&d9=%.2f", + sensor.pres, sensor.temp, sensor.humi, sensor.anemo, sensor.vane, sensor.rain, sensor.light, sensor.uv, sensor.moist, sensor.temp2); + postContent.puts(post_data); + +#ifdef NONBLOCKING + Net::poll(); + ret = clientP->post(STATION_URL, postContent, NULL, &cb_clientP); + Net::poll(); +#else + ret = clientP->post(STATION_URL, postContent, NULL); +#endif + + if (ret != HTTP_OK && ret != HTTP_PROCESSING) { + pc.printf("error: Weather Statuons %d\r\n", ret); + } +} + +void pachube (char *buf) { + char uri[100]; + HTTPResult ret; + HTTPText csvContent("text/csv"); + + led_y = 0; + clientP->setRequestHeader("X-PachubeApiKey", conf.pachube_apikey); + csvContent.set(buf); + strcpy(uri, "http://api.pachube.com/v1/feeds/"); + strcat(uri, conf.pachube_feedid); + strcat(uri, ".csv?_method=put"); +#ifdef NONBLOCKING + Net::poll(); + ret = clientP->post(uri, csvContent, NULL, &cb_clientP); + Net::poll(); +#else + ret = clientP->post(uri, csvContent, NULL); +#endif + + if (ret != HTTP_OK && ret != HTTP_PROCESSING) { + pc.printf("error: Pachube %d\r\n", ret); + } +} + +void cb_clientP (HTTPResult status) { + if (status != HTTP_OK) { + pc.printf("Pachube failure (%d)\r\n", status); +// pc.printf("Pachube failure (%d, %d)\r\n", status, clientP->getHTTPResponseCode()); + } +} + +char *fmtstr (char *fmt, char *buf, int len) { + int i, j, flg; + char c; + float value; + time_t sec = time(NULL); + struct tm *tim = localtime(&sec); + + j = 0; + for (i = 0; i < strlen(fmt) && j < len; i ++) { + c = fmt[i]; + if (c == '%') { + flg = 0; + i ++; + c = fmt[i]; + + if (c == '.') { + // float format + if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { + flg = fmt[i + 1] - '0'; + i ++; + + c = fmt[i + 1]; + i ++; + } + } + + switch (c) { + case 'P': + value = sensor.pres; + break; + case 'T': + value = sensor.temp; + break; + case 'H': + value = sensor.humi; + break; + case 'A': + value = sensor.anemo; + break; + case 'V': + value = sensor.vane; + break; + case 'R': + value = sensor.rain; + break; + case 'L': + value = sensor.light; + break; + case 'U': + value = sensor.uv; + break; + case 'M': + value = sensor.moist; + break; + + case 'y': + value = tim->tm_year + 1900; + break; + case 'm': + value = tim->tm_mon; + break; + case 'd': + value = tim->tm_mday; + break; + case 'h': + value = tim->tm_hour; + break; + case 'i': + value = tim->tm_min; + break; + case 's': + value = tim->tm_sec; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // Ascii + c = c - '0'; + if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { + c = (c << 3) | (fmt[i + 1] - '0'); + i ++; + if (fmt[i + 1] >= '0' && fmt[i + 1] <= '9') { + c = (c << 3) | (fmt[i + 1] - '0'); + i ++; + } + } + buf[j] = c; + j ++; + continue; + + default: + buf[j] = c; + j ++; + continue; + } + + switch (flg) { + case 1: + sprintf(&buf[j], "%.1f", value); + break; + case 2: + sprintf(&buf[j], "%.2f", value); + break; + default: + sprintf(&buf[j], "%02d", (int)value); + break; + } + j = strlen(buf); + } else { + buf[j] = c; + j ++; + } + } + buf[j] = 0; + return buf; +} + +void twitter (int num) { + HTTPMap msg; + HTTPResult ret; + char buf[170]; + + led_y = 0; + fmtstr(conf.twitter_mesg[num], buf, sizeof(buf)); + msg["status"] = buf; + + clientT->basicAuth(conf.twitter_user, conf.twitter_pwd); +#ifdef NONBLOCKING + Net::poll(); + ret = clientT->post(TWITTER_URL, msg, NULL, &cb_clientT); + Net::poll(); +#else + ret = clientT->post(TWITTER_URL, msg, NULL); +#endif + + if (ret != HTTP_OK && ret != HTTP_PROCESSING) { + pc.printf("error: Twitter %d\r\n", ret); + } +} + +void ntpdate () { + ntp = new NTPClient; + Host ntpserver(IpAddr(), 123, conf.ntpserver); + + led_y = 0; +#ifdef NONBLOCKING + Net::poll(); + ntp->setTime(ntpserver, &cb_settime); + Net::poll(); +#else + ntp->setTime(ntpserver); + time_t sec = time(NULL) + (60 * 60 * TIMEZONE); + set_time(sec); +#endif +} + +void cb_settime (NTPResult status) { + if (status == NTP_OK) { + led_y = 0; + time_t sec = time(NULL) + (60 * 60 * TIMEZONE); + set_time(sec); + pc.printf("Ntp success: %s\r\n", ctime(&sec)); + } else { + pc.printf("Ntp failure (%d)\r\n", status); + } +// ntp->close(); +}
--- a/snmp.cpp Fri Apr 08 15:59:29 2011 +0000 +++ b/snmp.cpp Tue May 31 15:40:14 2011 +0000 @@ -9,7 +9,7 @@ #include "Agentbed.h" #include "EthernetNetIf.h" #include "ConfigFile.h" -#include "conf.h" +#include "weather.h" AgentbedClass Agentbed; @@ -46,7 +46,7 @@ // RFC1213 local values static char locDescr[] = "mbed Weather Platform"; // read-only (static) static char locObjectID[] = "1.3.6.1.4.1.36582"; // read-only (static) -uint32_t locUpTime = 0; // read-only (static) +volatile uint32_t locUpTime = 0; // read-only (static) static char locContact[] = "<root@weather>"; // should be stored/read from EEPROM - read/write (not done for simplicity) static char locName[] = "weather.mbed"; // should be stored/read from EEPROM - read/write (not done for simplicity) static char locLocation[] = "weather"; // should be stored/read from EEPROM - read/write (not done for simplicity) @@ -57,8 +57,6 @@ SNMP_API_STAT_CODES api_status; SNMP_ERR_CODES status; -extern DigitalOut led_y; -extern Sensor sensor; void pduReceived() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/weather.h Tue May 31 15:40:14 2011 +0000 @@ -0,0 +1,121 @@ +/** @file + * @brief mbed Weather Platform + */ +#include "mbed.h" +#include "EthernetNetIf.h" +#include "I2CLEDDisp.h" +#include "I2CLCD.h" +#include "Agentbed.h" +#include "NTPClient.h" +#include "HTTPClient.h" + +#define DEBUG + +#define CONFIG_FILE "weather.cfg" +#define ACTION_FILE "weather.asm" + +#define CF_MAXLEN_VALUE 128 +#define CF_ACTION_NUM 100 +#define CF_TWITTER_NUM 5 + +#define INPUT_NUM 2 +#define OUTPUT_NUM 4 +#define TIMER_NUM 4 +#define COUNTER_NUM 4 + +#define LED_FREQ 4 // x 0.1s + +enum eMNEMONIC { + MNE_NULL, + MNE_LD, MNE_LDI, MNE_LDP, MNE_LDF, + MNE_ALD, MNE_ALDI, MNE_ALDP, MNE_ALDF, + MNE_OR, MNE_ORI, MNE_ORP, MNE_ORF, + MNE_AND, MNE_ANI, MNE_ANDP, MNE_ANDF, + MNE_ORB, MNE_ANB, + MNE_INV, + MNE_MPS, MNE_MRD, MNE_MPP, + MNE_OUT, MNE_SET, MNE_RST, + MNE_END, +}; + +enum eEXPRESSION { + EXP_NULL, + EXP_EQ, EXP_NE, + EXP_LE, EXP_LT, + EXP_GE, EXP_GT, + EXP_MOD, EXP_NMOD, +}; + +enum eINPUTTYPE { + INPUT_MOIST = 0, + INPUT_FALL = 1, + INPUT_RISE = 2, + INPUT_CPM = 4, +}; + +struct tAction { + enum eMNEMONIC mnemonic; + char key; + int keynum; + enum eEXPRESSION expression; + float value; +}; + +struct Sensor { + float pres, temp, humi, light, anemo, vane, rain, uv, moist, temp2; + time_t sec; + int input[INPUT_NUM], output[OUTPUT_NUM], timer_flg[TIMER_NUM]; + unsigned long timer_cnt[TIMER_NUM]; + unsigned long count[COUNTER_NUM]; +}; + +struct Config { + int interval; + IpAddr ipaddr, netmask, gateway, nameserver; + char ntpserver[32]; + int filetype, actionscount; + struct tAction actions[CF_ACTION_NUM]; + char pachube_apikey[70], pachube_feedid[8]; + char twitter_user[30], twitter_pwd[30], twitter_mesg[CF_TWITTER_NUM][CF_MAXLEN_VALUE]; + char stations_id[8], stations_pin[34]; + char snmp_commname[30]; + char lcd_mesg[CF_MAXLEN_VALUE]; + enum I2CLCDType lcdtype; + enum I2CLCDConfig lcdconf; + char leddisp_mesg[CF_MAXLEN_VALUE]; + enum eINPUTTYPE inputtype; +}; + + +extern char filename[]; +extern char csv[]; +extern AgentbedClass Agentbed; +extern volatile uint32_t locUpTime; +extern Serial xbee; +extern Config conf; +extern Sensor sensor, offset, sensor_old; +extern Serial pc; +extern volatile int seq; +extern DigitalOut led1, led2, led3, led4; +extern AnalogIn *aimoist; +extern DigitalIn swin2; +extern DigitalOut swout1, swout2; +extern EthernetNetIf *eth; +extern NTPClient *ntp; +extern HTTPClient *clientP, *clientT; +extern DigitalOut led_g2, led_g, led_y; + + +int config (char *); +void writefile (char *); +void pachube (char *); +char *fmtstr (char *, char *, int); +void twitter (int); +void weatherstations (); +void ntpdate (); +int check_action (char); +void pduReceived (); +void int_counter(); +int action(char); +void load_action (char *); +