World Wide Data Logger using mbed.

Dependencies:   mbed ThermistorPack Pachube ConfigFile EthernetNetIf TextLCD SDFileSystem

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002  * =============================================================================
00003  * TORAGI 2011/04 : WEB Data Logger
00004  * =============================================================================
00005  * Copyright (c) 2010-2011 Shinichiro Nakamura
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a copy
00008  * of this software and associated documentation files (the "Software"), to deal
00009  * in the Software without restriction, including without limitation the rights
00010  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the Software is
00012  * furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included in
00015  * all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023  * THE SOFTWARE.
00024  * =============================================================================
00025  */
00026 
00027 #include "mbed.h"
00028 #include "PachubeV2CSV.h"
00029 #include "EthernetNetIf.h"
00030 #include "HTTPClient.h"
00031 #include "ThermistorMCP9701.h"
00032 #include "TextLCD.h"
00033 #include "appconf.h"
00034 #include "SDFileSystem.h"
00035 
00036 /*
00037  * Definitions for a configuration file.
00038  */
00039 #define CONFIG_FILENAME "/local/PACHUBE.CFG"
00040 #define DATACSV_FILENAME "/sd/DATA.CSV"
00041 const int PACHUBE_CODE_OK = 200;
00042 
00043 LocalFileSystem localfs("local");
00044 SDFileSystem sdfs(p5, p6, p7, p8, "sd");
00045 TextLCD lcd(p24, p26, p27, p28, p29, p30);
00046 EthernetNetIf netif;
00047 BusOut led(LED1, LED2, LED3, LED4);
00048 ThermistorMCP9701 thermistor1(p16);
00049 ThermistorMCP9701 thermistor2(p17);
00050 ThermistorMCP9701 thermistor3(p18);
00051 ThermistorMCP9701 thermistor4(p19);
00052 ThermistorMCP9701 thermistor5(p20);
00053 static appconf_t appconf;
00054 
00055 /**
00056  * Display a splash screen.
00057  */
00058 void splash(void) {
00059     lcd.cls();
00060     lcd.locate(0, 0);
00061     lcd.printf(" TORAGI 2011/04 ");
00062     lcd.locate(0, 1);
00063     lcd.printf("WEB Data Logger ");
00064     wait(2);
00065 
00066     lcd.cls();
00067     lcd.locate(0, 0);
00068     lcd.printf(" Starting up... ");
00069     lcd.locate(0, 1);
00070     lcd.printf(" Wait a moment. ");
00071     wait(2);
00072 }
00073 
00074 /**
00075  * Convert double to char.
00076  *
00077  * @param val Value.
00078  * @param buf A pointer to a buffer.
00079  * @param bufsiz The buffer size.
00080  */
00081 void convertDoubleToChar(double val, char *buf, size_t bufsiz) {
00082     snprintf(buf, bufsiz, "%f", val);
00083 }
00084 
00085 /**
00086  * Post to the feed on Pachube.
00087  *
00088  * @param web Pointer to a Pachube object.
00089  * @param feed_id Feed ID.
00090  * @param stream_no Stream number.
00091  * @param value value.
00092  *
00093  * @return Pachube code.
00094  */
00095 int web_post(PachubeV2CSV *web, int feed_id, int stream_no, double value) {
00096     char value_text[16];
00097     convertDoubleToChar(value, value_text, sizeof(value_text));
00098     char stream_no_text[8];
00099     stream_no_text[0] = "0123456789"[stream_no];
00100     stream_no_text[1] = '\0';
00101     return web->updateDataStream(feed_id, stream_no_text, std::string(value_text));
00102 }
00103 
00104 /**
00105  * Write to the file.
00106  *
00107  * @param v1 value no. 1.
00108  * @param v2 value no. 2.
00109  * @param v3 value no. 3.
00110  * @param v4 value no. 4.
00111  * @param v5 value no. 5.
00112  *
00113  * @return Return 0 if it succeed.
00114  */
00115 int file_write(int v1, int v2, int v3, int v4, int v5) {
00116     FILE *fp = fopen(DATACSV_FILENAME, "a");
00117     if (fp == NULL) {
00118         return -1;
00119     }
00120     fprintf(fp, "%d, %d, %d, %d, %d\n", v1, v2, v3, v4, v5);
00121     fclose(fp);
00122     return 0;
00123 }
00124 
00125 /**
00126  * Entry point.
00127  */
00128 int main() {
00129 
00130     /*
00131      * Splash.
00132      */
00133     splash();
00134     wait(5);
00135 
00136     /*
00137      * Initialize ethernet interface.
00138      */
00139     lcd.cls();
00140     lcd.locate(0, 0);
00141     lcd.printf("Initializing...");
00142     lcd.locate(0, 1);
00143     lcd.printf("Ethernet: ");
00144     EthernetErr ethErr = netif.setup();
00145     if (ethErr) {
00146         lcd.printf("[NG]");
00147         error("Ethernet setup failed. Done with code %d.\n", ethErr);
00148     }
00149     lcd.printf("[OK]");
00150     wait(3);
00151 
00152     /*
00153      * Read configuration variables from a file.
00154      */
00155     lcd.cls();
00156     lcd.locate(0, 0);
00157     lcd.printf("Reading...");
00158     lcd.locate(0, 1);
00159     lcd.printf("Setup: ");
00160     appconf_init(&appconf);
00161     if (appconf_read(CONFIG_FILENAME, &appconf) != 0) {
00162         lcd.printf("[NG]");
00163         error("Failure to read a configuration file.\n");
00164     }
00165     lcd.printf("[OK]");
00166     wait(3);
00167 
00168     /*
00169      * Initialize objects.
00170      */
00171     PachubeV2CSV web(appconf.apikey);
00172     const int feed_id = atoi(appconf.feedid);
00173 
00174     /*
00175      * Check the pachube feautures.
00176      */
00177     {
00178         lcd.cls();
00179         lcd.locate(0, 0);
00180         lcd.printf("Checking Pachube");
00181         lcd.locate(0, 1);
00182         lcd.printf("Status:");
00183         int errcnt = 0;
00184         if (web_post(&web, feed_id, 0, thermistor1.read()) == PACHUBE_CODE_OK) {
00185             lcd.printf("o");
00186         } else {
00187             lcd.printf("x");
00188             errcnt++;
00189         }
00190         if (web_post(&web, feed_id, 1, thermistor2.read()) == PACHUBE_CODE_OK) {
00191             lcd.printf("o");
00192         } else {
00193             lcd.printf("x");
00194             errcnt++;
00195         }
00196         if (web_post(&web, feed_id, 2, thermistor3.read()) == PACHUBE_CODE_OK) {
00197             lcd.printf("o");
00198         } else {
00199             lcd.printf("x");
00200             errcnt++;
00201         }
00202         if (web_post(&web, feed_id, 3, thermistor4.read()) == PACHUBE_CODE_OK) {
00203             lcd.printf("o");
00204         } else {
00205             lcd.printf("x");
00206             errcnt++;
00207         }
00208         if (web_post(&web, feed_id, 4, thermistor5.read()) == PACHUBE_CODE_OK) {
00209             lcd.printf("o");
00210         } else {
00211             lcd.printf("x");
00212             errcnt++;
00213         }
00214         if (errcnt == 5) {
00215             lcd.printf("[NG]");
00216             error("Inavlid pachube configuration.\n");
00217         }
00218         lcd.printf("[OK]");
00219         wait(3);
00220     }
00221 
00222     int cnt = 0;
00223     do {
00224         /*
00225          * Sense.
00226          */
00227         lcd.cls();
00228         double v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0;
00229         for (int i = 0; i < appconf.interval; i++) {
00230             led = 1 << (i % 4);
00231             // printf("%d/%d\n", i + 1, appconf.interval);
00232             v1 += thermistor1.read();
00233             v2 += thermistor2.read();
00234             v3 += thermistor3.read();
00235             v4 += thermistor4.read();
00236             v5 += thermistor5.read();
00237             lcd.locate(0, 0);
00238             lcd.printf("| 0| 1| 2| 3| 4|");
00239             lcd.locate(0, 1);
00240             lcd.printf("|%-2.0f|%-2.0f|%-2.0f|%-2.0f|%-2.0f|",
00241                        v1 / (i + 1),
00242                        v2 / (i + 1),
00243                        v3 / (i + 1),
00244                        v4 / (i + 1),
00245                        v5 / (i + 1));
00246             wait(1);
00247         }
00248         v1 /= appconf.interval;
00249         v2 /= appconf.interval;
00250         v3 /= appconf.interval;
00251         v4 /= appconf.interval;
00252         v5 /= appconf.interval;
00253         cnt++;
00254 
00255         /*
00256          * Post.
00257          */
00258         lcd.cls();
00259         lcd.locate(0, 0);
00260         lcd.printf("Posting No.%d", cnt);
00261         lcd.locate(0, 1);
00262         lcd.printf("Status:");
00263         int errcnt = 0;
00264         if (web_post(&web, feed_id, 0, v1) == PACHUBE_CODE_OK) {
00265             lcd.printf("o");
00266         } else {
00267             lcd.printf("x");
00268             errcnt++;
00269         }
00270         if (web_post(&web, feed_id, 1, v2) == PACHUBE_CODE_OK) {
00271             lcd.printf("o");
00272         } else {
00273             lcd.printf("x");
00274             errcnt++;
00275         }
00276         if (web_post(&web, feed_id, 2, v3) == PACHUBE_CODE_OK) {
00277             lcd.printf("o");
00278         } else {
00279             lcd.printf("x");
00280             errcnt++;
00281         }
00282         if (web_post(&web, feed_id, 3, v4) == PACHUBE_CODE_OK) {
00283             lcd.printf("o");
00284         } else {
00285             lcd.printf("x");
00286             errcnt++;
00287         }
00288         if (web_post(&web, feed_id, 4, v5) == PACHUBE_CODE_OK) {
00289             lcd.printf("o");
00290         } else {
00291             lcd.printf("x");
00292             errcnt++;
00293         }
00294         if (errcnt == 5) {
00295             lcd.printf("[NG]");
00296         }
00297         lcd.printf("[OK]");
00298         wait(1);
00299 
00300         /*
00301          * Write.
00302          */
00303         lcd.cls();
00304         lcd.locate(0, 0);
00305         lcd.printf("Writing No.%d", cnt);
00306         lcd.locate(0, 1);
00307         lcd.printf("Status: ");
00308         if (file_write(v1, v2, v3, v4, v5) == 0) {
00309             lcd.printf("[OK]");
00310         } else {
00311             lcd.printf("[NG]");
00312         }
00313         wait(1);
00314     } while (1);
00315 }