World Wide Data Logger using mbed.
Dependencies: mbed ThermistorPack Pachube ConfigFile EthernetNetIf TextLCD SDFileSystem
Diff: main.cpp
- Revision:
- 0:798c62ea70a3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Apr 04 21:33:25 2011 +0000 @@ -0,0 +1,315 @@ +/** + * ============================================================================= + * TORAGI 2011/04 : WEB Data Logger + * ============================================================================= + * Copyright (c) 2010-2011 Shinichiro Nakamura + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================= + */ + +#include "mbed.h" +#include "PachubeV2CSV.h" +#include "EthernetNetIf.h" +#include "HTTPClient.h" +#include "ThermistorMCP9701.h" +#include "TextLCD.h" +#include "appconf.h" +#include "SDFileSystem.h" + +/* + * Definitions for a configuration file. + */ +#define CONFIG_FILENAME "/local/PACHUBE.CFG" +#define DATACSV_FILENAME "/sd/DATA.CSV" +const int PACHUBE_CODE_OK = 200; + +LocalFileSystem localfs("local"); +SDFileSystem sdfs(p5, p6, p7, p8, "sd"); +TextLCD lcd(p24, p26, p27, p28, p29, p30); +EthernetNetIf netif; +BusOut led(LED1, LED2, LED3, LED4); +ThermistorMCP9701 thermistor1(p16); +ThermistorMCP9701 thermistor2(p17); +ThermistorMCP9701 thermistor3(p18); +ThermistorMCP9701 thermistor4(p19); +ThermistorMCP9701 thermistor5(p20); +static appconf_t appconf; + +/** + * Display a splash screen. + */ +void splash(void) { + lcd.cls(); + lcd.locate(0, 0); + lcd.printf(" TORAGI 2011/04 "); + lcd.locate(0, 1); + lcd.printf("WEB Data Logger "); + wait(2); + + lcd.cls(); + lcd.locate(0, 0); + lcd.printf(" Starting up... "); + lcd.locate(0, 1); + lcd.printf(" Wait a moment. "); + wait(2); +} + +/** + * Convert double to char. + * + * @param val Value. + * @param buf A pointer to a buffer. + * @param bufsiz The buffer size. + */ +void convertDoubleToChar(double val, char *buf, size_t bufsiz) { + snprintf(buf, bufsiz, "%f", val); +} + +/** + * Post to the feed on Pachube. + * + * @param web Pointer to a Pachube object. + * @param feed_id Feed ID. + * @param stream_no Stream number. + * @param value value. + * + * @return Pachube code. + */ +int web_post(PachubeV2CSV *web, int feed_id, int stream_no, double value) { + char value_text[16]; + convertDoubleToChar(value, value_text, sizeof(value_text)); + char stream_no_text[8]; + stream_no_text[0] = "0123456789"[stream_no]; + stream_no_text[1] = '\0'; + return web->updateDataStream(feed_id, stream_no_text, std::string(value_text)); +} + +/** + * Write to the file. + * + * @param v1 value no. 1. + * @param v2 value no. 2. + * @param v3 value no. 3. + * @param v4 value no. 4. + * @param v5 value no. 5. + * + * @return Return 0 if it succeed. + */ +int file_write(int v1, int v2, int v3, int v4, int v5) { + FILE *fp = fopen(DATACSV_FILENAME, "a"); + if (fp == NULL) { + return -1; + } + fprintf(fp, "%d, %d, %d, %d, %d\n", v1, v2, v3, v4, v5); + fclose(fp); + return 0; +} + +/** + * Entry point. + */ +int main() { + + /* + * Splash. + */ + splash(); + wait(5); + + /* + * Initialize ethernet interface. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Initializing..."); + lcd.locate(0, 1); + lcd.printf("Ethernet: "); + EthernetErr ethErr = netif.setup(); + if (ethErr) { + lcd.printf("[NG]"); + error("Ethernet setup failed. Done with code %d.\n", ethErr); + } + lcd.printf("[OK]"); + wait(3); + + /* + * Read configuration variables from a file. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Reading..."); + lcd.locate(0, 1); + lcd.printf("Setup: "); + appconf_init(&appconf); + if (appconf_read(CONFIG_FILENAME, &appconf) != 0) { + lcd.printf("[NG]"); + error("Failure to read a configuration file.\n"); + } + lcd.printf("[OK]"); + wait(3); + + /* + * Initialize objects. + */ + PachubeV2CSV web(appconf.apikey); + const int feed_id = atoi(appconf.feedid); + + /* + * Check the pachube feautures. + */ + { + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Checking Pachube"); + lcd.locate(0, 1); + lcd.printf("Status:"); + int errcnt = 0; + if (web_post(&web, feed_id, 0, thermistor1.read()) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 1, thermistor2.read()) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 2, thermistor3.read()) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 3, thermistor4.read()) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 4, thermistor5.read()) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (errcnt == 5) { + lcd.printf("[NG]"); + error("Inavlid pachube configuration.\n"); + } + lcd.printf("[OK]"); + wait(3); + } + + int cnt = 0; + do { + /* + * Sense. + */ + lcd.cls(); + double v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0; + for (int i = 0; i < appconf.interval; i++) { + led = 1 << (i % 4); + // printf("%d/%d\n", i + 1, appconf.interval); + v1 += thermistor1.read(); + v2 += thermistor2.read(); + v3 += thermistor3.read(); + v4 += thermistor4.read(); + v5 += thermistor5.read(); + lcd.locate(0, 0); + lcd.printf("| 0| 1| 2| 3| 4|"); + lcd.locate(0, 1); + lcd.printf("|%-2.0f|%-2.0f|%-2.0f|%-2.0f|%-2.0f|", + v1 / (i + 1), + v2 / (i + 1), + v3 / (i + 1), + v4 / (i + 1), + v5 / (i + 1)); + wait(1); + } + v1 /= appconf.interval; + v2 /= appconf.interval; + v3 /= appconf.interval; + v4 /= appconf.interval; + v5 /= appconf.interval; + cnt++; + + /* + * Post. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Posting No.%d", cnt); + lcd.locate(0, 1); + lcd.printf("Status:"); + int errcnt = 0; + if (web_post(&web, feed_id, 0, v1) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 1, v2) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 2, v3) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 3, v4) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (web_post(&web, feed_id, 4, v5) == PACHUBE_CODE_OK) { + lcd.printf("o"); + } else { + lcd.printf("x"); + errcnt++; + } + if (errcnt == 5) { + lcd.printf("[NG]"); + } + lcd.printf("[OK]"); + wait(1); + + /* + * Write. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Writing No.%d", cnt); + lcd.locate(0, 1); + lcd.printf("Status: "); + if (file_write(v1, v2, v3, v4, v5) == 0) { + lcd.printf("[OK]"); + } else { + lcd.printf("[NG]"); + } + wait(1); + } while (1); +}