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

action.cpp

Committer:
okini3939
Date:
2011-06-03
Revision:
19:69b77f9e0446
Parent:
18:9286e5010c14

File content as of revision 19:69b77f9e0446:

/** @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 26
const struct MNE_str mne_str[CF_MNE_NUM] = {
    {MNE_DEF, "DEF"},
    {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;
    // right value
    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] >= s->timer_set[keynum];
        } else {
            value = s->timer_cnt[keynum];
        }
        break;
    case 'c': // Counter
        if (keynum >= COUNTER_NUM) break;
        if (conf.actions[i].expression == EXP_NULL) {
             value = s->count_cnt[keynum] >= s->count_set[keynum];
        } else {
             value = s->count_cnt[keynum];
        }
        break;
    }

    // expression
    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 / 10) % (int)check;
    case EXP_NMOD:
        return ! (((int)value / 10)  % (int)check);
    }

    return value != 0;
}

void exec_action (int i, int reg, eMNEMONIC sr) {
    int keynum;

    keynum = conf.actions[i].keynum;

    switch (conf.actions[i].key) {
    case 'P': // Pachube
        if (sr == MNE_OUT && reg)
          if (conf.ipaddr[0] && conf.pachube_apikey[0] && conf.pachube_feedid[0]) {
            pachube(csv);
        }
        break;

    case 'S': // Weather Stations
        if (sr == MNE_OUT && reg)
          if (conf.ipaddr[0] && conf.stations_id[0] && conf.stations_pin[0]) {
            weatherstations();
        }
        break;

    case 'W': // Twitter
        if (sr == MNE_OUT && reg)
          if (conf.ipaddr[0] && conf.twitter_user[0] && conf.twitter_pwd[0]) {
              twitter(keynum);
        }
        break;

    case 'X': // XBee
        if (sr == MNE_OUT && 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) {
            if (! sensor.timer_flg[keynum]) {
                // set timer
                sensor.timer_cnt[keynum] = 0;
            }
            sensor.timer_flg[keynum] = reg;
        } else
        if (sr == MNE_RST && reg) {
            sensor.timer_cnt[keynum] = 0;
        }
        break;

    case 'c': // Counter
        if (keynum >= COUNTER_NUM) break;
        if (sr == MNE_OUT && reg) {
            if (sensor.count_rev[keynum]) {
                sensor.count_cnt[keynum] --;
            } else {
                sensor.count_cnt[keynum] ++;
            }
        } else
        if (sr == MNE_RST && reg) {
            sensor.count_cnt[keynum] = 0;
        }
    case 'r': // Counter (reverse)
        if (keynum >= COUNTER_NUM) break;
        if (sr == MNE_OUT) {
            sensor.count_rev[keynum] = reg;
        }
        break;
    }

#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 sensor_tmp;

    // input
    sensor.sec = time(NULL) + (60 * 60 * 9);
    sensor.input[0] = conf.inputtype ? *aimoist > 0.5 : 0;
    sensor.input[1] = swin2;
    sensor_tmp = sensor;

    // mnemonic decode
    for(i = 0; i < conf.actionscount; i ++) {
        switch (conf.actions[i].mnemonic) {
        case MNE_LD:
            stack.push(reg);
            reg = check_exp(&sensor, i);
            ena = 1;
            break;
        case MNE_LDI:
            stack.push(reg);
            reg = ! check_exp(&sensor, i);
            ena = 1;
            break;
        case MNE_LDP:
            stack.push(reg);
            reg = check_exp(&sensor, i) && ! check_exp(&sensor_old, i);
            ena = 1;
            break;
        case MNE_LDF:
            stack.push(reg);
            reg = ! check_exp(&sensor, i) && check_exp(&sensor_old, i);
            ena = 1;
            break;

        case MNE_ALD:
            stack.push(reg);
            reg = check_exp(&sensor, i);
            ena = enable;
            break;
        case MNE_ALDI:
            stack.push(reg);
            reg = ! check_exp(&sensor, i);
            ena = enable;
            break;
        case MNE_ALDP:
            stack.push(reg);
            reg = check_exp(&sensor, i) && ! check_exp(&sensor_old, i);
            ena = enable;
            break;
        case MNE_ALDF:
            stack.push(reg);
            reg = ! check_exp(&sensor, i) && check_exp(&sensor_old, i);
            ena = enable;
            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(&reg);
            break;
        case MNE_MPP:
            stack.pop(&reg);
            break;

        case MNE_OUT:
        case MNE_SET:
        case MNE_RST:
            if (ena) exec_action(i, reg, conf.actions[i].mnemonic);
            break;
        }
    }

    // output
    led3 = swout1 = sensor.output[0];
    led4 = swout2 = sensor.output[1];
    sensor_old = sensor_tmp;

#ifdef DEBUG
    printf("timer0=%d(%d) timer1=%d(%d)\r\n", sensor.timer_cnt[0], sensor.timer_set[0], sensor.timer_cnt[1], sensor.timer_set[1]);
#endif
    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) {
        // expression
        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) {
            // load
            buf[i] = c;
            i ++;
            continue;
        }
        buf[i] = 0;
        
        if (i == 0 || buf[0] == '#' || buf[0] == ';') {
            // comment
            i = 0;
            continue;
        }

        // mnemonic
        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;
    }

    // init
    for (i = 0; i < count; i ++) {
      if (conf.actions[i].mnemonic == MNE_DEF) {
        switch (conf.actions[i].key) {
        case 't': // Timer
            sensor.timer_set[conf.actions[i].keynum] = conf.actions[i].value * 10;
            break;

        case 'c': // Counter
            sensor.count_set[conf.actions[i].keynum] = conf.actions[i].value;
            break;
        }
      }
    }

    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
}