// Easy Screen with DHCP ver. 0.9 // (C) CQ Publishing Inc. & F. Nakamura, 2009 // #include #include #include "Dhcp.h" byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x22, 0x0E }; // Node location int longitude[] = { 137, 43, 9 , 3 }; int latitude[] = { 37, 5 , 18 , 7 }; int altitude[] = { 254 , 6 }; // UL means unsigned long #define PASSKEY 1234567UL // get it from http://100.eleki-jack.com/ ////////////////////////////////////////////////////////// // No need to touch the server address in most cases. byte server[] = { 219, 101, 148, 94 }; // 100.eleki-jack.com int port = 14949; /////////////////////////////////////////////////////////// // No need to modefiy the lines below /////////////////////////////////////////////////////////// Client client(server, port); boolean useDHCP = true; // These are not used if useDHCP == true byte ip[] = { 192, 168, 3 , 99 }; byte gateway[] = { 192, 168, 3, 254 }; byte netmask[] = { 255, 255, 255, 0 }; // Usually, you do not need to edit the items under this line. #define TEMPERATURE_PIN 0 #define HUMIDITY_PIN 1 #define DSTEP_mV 4.9 // Arduino digitization unit (4.9mV) #define DEFAULT_NEXT (20*1000) // milli seconds #define LOCAL_LOG_ENTRIES 10 // record entries #define LOCAL_LOG_INTERVAL_M (60UL*1000UL) #define DHCP_TIMEOUT (15*1000) #define INIT_TIMEOUT (20UL*1000UL) // msec #define MAX_RETRY_INTERVAL_M (60UL*60UL*1000UL) // 1 hour // Never touch definitions after this line unless you know what you're doing. #define VERBOSE_MODE 0x01 int systemStatus = -1; // -1: not started, 0: initialization phase, 1: connected byte flags = 0x00; unsigned long recordedTime_s[LOCAL_LOG_ENTRIES]; int vlog[5][LOCAL_LOG_ENTRIES]; int lindex = 0; unsigned long lastLocalLogTime_m = 0UL; unsigned long nextLocalLogTime_m = 0UL; unsigned long lastConnection_m = 0UL; unsigned long nextConnection_m = 0UL; unsigned long reportInterval_m = DEFAULT_NEXT; unsigned long unixTimeAtServer_s = 0UL; unsigned long lastConnection_s = 0UL; unsigned long nextConnection_s = 0UL; unsigned long arduinoTimeAtServer_m = 0; #define CONNECTION_NOT_TRIED 0x01 #define CONNECTION_SUCCEEDED 0x02 #define CONNECTION_FAILED 0x04 #define CONNECTION_UNKNOWN_COMMAND 0x08 #define CONNECTION_REGISTRATION_ERROR 0x10 byte connectionStatus = CONNECTION_NOT_TRIED; byte serverROM[] = { 0,0,0,0 }; int portROM = 0; boolean useEEPROMParams = true; boolean writeParamsEEPROM = true; // end of declarations and definitions. int getTemperature() { int a = analogRead(TEMPERATURE_PIN); int ret = (a * DSTEP_mV - 600)/10 + 0.0; return ret; } int getHumidity() { int b = analogRead(HUMIDITY_PIN); int ret = (b * DSTEP_mV - 0.0)/10.0 + 0.0; return ret; } void setup() { Serial.begin(9600); Serial.println("Initializing.."); setServerParameters(); if( useDHCP ) if( Dhcp.beginWithDHCP(mac,DHCP_TIMEOUT) ) Serial.println("DHCP done."); else Serial.println("DHCP failed."); else Ethernet.begin(mac, ip, gateway, netmask); //LANMonitor.begin(); delay(1000); nextConnection_m = millis() + reportInterval_m; nextLocalLogTime_m = millis() + INIT_TIMEOUT; Serial.println("Initialization done."); } void loop() { mainproc(); localMonitor(); } void mainproc() { unsigned long currentTime_m; currentTime_m = millis(); if( isPassed(currentTime_m, nextConnection_m, lastConnection_m) ) { checkServer(); if( flags & VERBOSE_MODE ) printStatus(); } if( isPassed(currentTime_m, nextLocalLogTime_m, lastLocalLogTime_m) ) checkSensors(); } void localMonitor() { if( Serial.available() ) procMon(Serial.read()); } unsigned long checkServer() { byte svip[4] = { 0,0,0,0 }; int svport = 0; int v[5] = { 0,0,0,0,0 }; v[0] = getTemperature(); v[1] = getHumidity(); if( flags & VERBOSE_MODE ) Serial.println("Connecting to the server"); lastConnection_s = getUnixTime(); lastConnection_m = millis(); if (client.connect()) { if( flags & VERBOSE_MODE) Serial.println("connected"); sendNodeInfo(client,v,sizeof(v)/2); connectionStatus = CONNECTION_SUCCEEDED; } else { setRetryInterval(); if( flags & VERBOSE_MODE) Serial.println("connection failed"); connectionStatus = CONNECTION_FAILED; return(1); } char buf[64]; int i=0; while (client.connected()) { if (client.available()) { char c = client.read(); buf[i++] = c; } } buf[i] = '\0'; client.stop(); if( buf[0] == 'N' ) { setRetryInterval(); if( flags & VERBOSE_MODE ) { Serial.println("Node parameter is not found or incorrect"); Serial.println("Please check the parameters."); } connectionStatus |= CONNECTION_REGISTRATION_ERROR; return 0; } else if( buf[0] != 'T' ) { setRetryInterval(); if( flags & VERBOSE_MODE) Serial.println("Unkwon response from the server"); connectionStatus |= CONNECTION_UNKNOWN_COMMAND; return 0; } arduinoTimeAtServer_m = millis(); unixTimeAtServer_s = char2ulong(buf,2,11); nextConnection_s = char2ulong(buf,13,22); getServerAddrPort(svip,&svport,buf,24,44); if( !cmpServerAndEEPROM(server,port,svip,svport) ) { for( int k = 0; k < 4; k++ ) server[k] = svip[k]; port = svport; if( writeParamsEEPROM ) { writeEEPROMAddrPort(svip,svport); getEEPROMAddrPort(serverROM,&portROM); getEEPROMAddrPort(server,&port); } } if( nextConnection_s > unixTimeAtServer_s ) { reportInterval_m = (nextConnection_s - unixTimeAtServer_s)*1000UL; nextConnection_m = millis() + reportInterval_m; } else { connectionStatus |= CONNECTION_UNKNOWN_COMMAND; setRetryInterval(); } if( flags & VERBOSE_MODE) { Serial.print("Unix Time in UL="); Serial.println(unixTimeAtServer_s); Serial.print("Next Connection in UL="); Serial.println(nextConnection_s); } if( flags & VERBOSE_MODE ) Serial.println("Connection terminated"); } // End of checkServer() int sendNodeInfo(Client c, int v[], int vi) { int i; c.print("I 18 "); for( i = 0; i < sizeof(longitude)/2; i++ ) { c.print(longitude[i]); c.print(' '); } for( i = 0; i < sizeof(latitude)/2; i++ ) { c.print(latitude[i]); c.print(' '); } for( i = 0; i < sizeof(altitude)/2; i++ ) { c.print(altitude[i]); c.print(' '); } c.print(PASSKEY); for( i = 0; i < vi; i++ ) { c.print(' '); c.print(v[i]); } c.print('\n'); return 1; } void procMon(char cmd) { switch(cmd) { case 'T': case 't': Serial.println(getTemperature()); break; case 'H': case 'h': Serial.println(getHumidity()); break; case 'r': case 'R': checkServer(); break; case 'l': case 'L': printLog(); break; case 'i': case 'I': printNodeInfo(); break; case 's': case 'S': printConnectionStatus(); break; case 'v': case 'V': flags ^= VERBOSE_MODE; Serial.print("Verbose mode: "); Serial.println(flags,BIN); break; case 'e': case 'E': printEEPROMAddrPort(); break; case 'w': case 'W': writeEEPROMAddrPort(server,port); getEEPROMAddrPort(serverROM,&portROM); Serial.println("Save IP and port to EEPROM"); break; case 'c': case 'C': clearEEPROM(); Serial.println("EEPROM cleared"); break; case 'd': case 'D': printEEPROMAddrPortRaw(); break; case '?': printHelp(); break; default: Serial.println("Unknown command."); } } int checkSensors() { if( unixTimeAtServer_s > 0 ) recordedTime_s[lindex] = getUnixTime(); else recordedTime_s[lindex] = millis()/1000; vlog[0][lindex] = getTemperature(); vlog[1][lindex] = getHumidity(); for(int i = 2; i < 5 ; i++ ) vlog[i][lindex] = 0; lindex = (lindex + 1) % LOCAL_LOG_ENTRIES; lastLocalLogTime_m = millis(); nextLocalLogTime_m = lastLocalLogTime_m + LOCAL_LOG_INTERVAL_M; return 1; } // Log display functions void printLog() { int li = lindex; for( int i = 0; i < LOCAL_LOG_ENTRIES; i++ ) { if( recordedTime_s[li] > 0 ) { Serial.print(recordedTime_s[li]); for( int j = 0; j < 5; j++ ) { Serial.print(" "); Serial.print(vlog[j][li]); } Serial.println(); } li = (li + 1) % LOCAL_LOG_ENTRIES; } } // Status information void printStatus() { unsigned long curtime = millis(); Serial.print("Internal time(ms): "); Serial.println(curtime,DEC); unsigned long ct = getUnixTime(); Serial.print("Internal time(UT): "); Serial.println(ct,DEC); Serial.print("Temp(Cel): "); Serial.print(getTemperature(),DEC); Serial.print(" Humidity(%): "); Serial.println(getHumidity(),DEC); } void printConnectionStatus() { Serial.print("Internal time: "); Serial.println(getUnixTime()); Serial.print("Last connection: "); Serial.println(lastConnection_s); Serial.print("Connection status(NotTried:1,Success:2,Fail:4,Unknown:8,RegErr:16): "); Serial.println(connectionStatus,DEC); Serial.print("Next connection: "); Serial.println(nextConnection_s); } void printNWInfo(const byte c[], int n, char dlm,int mode) { Serial.print(c[0],mode); for(int i = 1; i < n ; i++ ) { Serial.print(dlm); Serial.print(c[i],mode); } Serial.println(); } void printNodeInfo() { Serial.print("Longitude:"); for( int i = 0; i < 4; i++ ) { Serial.print(" "); Serial.print(longitude[i]); } Serial.print(" Latitude:"); for( int i = 0; i < 4; i++ ) { Serial.print(" "); Serial.print(latitude[i]); } Serial.println(); Serial.print("Altitude:"); for( int i = 0; i < 2; i++ ) { Serial.print(" "); Serial.print(altitude[i]); } Serial.println(); Serial.print("Node key: "); Serial.println(PASSKEY); Serial.print("Server: "); printNWInfo(server,4,'.',DEC); Serial.print("Port:"); Serial.println(port); Serial.print("IP address: "); printIP(); Serial.print("Netmask: "); printMask(); Serial.print("Gateway: "); printGW(); Serial.print("MAC address: "); printNWInfo(mac,6,':',HEX); } // Utility functions void printIP() { byte buff[4]; if( useDHCP ) Dhcp.getLocalIp(buff); else for( int m = 0; m < 4; m++ ) buff[m] = ip[m]; printNWInfo(buff,4,'.',DEC); } void printMask() { byte buff[4]; if( useDHCP ) Dhcp.getSubnetMask(buff); else for( int m = 0; m < 4; m++ ) buff[m] = netmask[m]; printNWInfo(buff,4,'.',DEC); } void printGW() { byte buff[4]; if( useDHCP ) Dhcp.getGatewayIp(buff); else for( int m = 0; m < 4; m++ ) buff[m] = gateway[m]; printNWInfo(buff,4,'.',DEC); } boolean isPassed(unsigned long cur, unsigned long nxt, unsigned long lst) { // Arduino millis() will round up about 50 days... if( nxt > lst ) { if( cur > nxt || lst > cur ) return true; } else { if( cur > nxt && lst > cur ) return true; } return false; } void getServerAddrPort(byte a[],int *pport,char buf[],int s,int e) { buf[45] = '\0'; for( int i = 0; i < 4; i++ ) { a[i] = char2int(buf,s + i * 4,s + i * 4 + 2); } *pport = char2int(buf,s+16,s+20); return; } void setRetryInterval() { nextConnection_m = millis() + reportInterval_m; reportInterval_m = min(reportInterval_m * 2UL,MAX_RETRY_INTERVAL_M); return; } unsigned long getUnixTime() { unsigned long current_m = 0; unsigned long ret_s = 0; if( unixTimeAtServer_s != 0 ) { current_m = millis(); if( current_m > arduinoTimeAtServer_m ) ret_s = (current_m - arduinoTimeAtServer_m)/1000UL+unixTimeAtServer_s; else { ret_s = (4294967295 - (arduinoTimeAtServer_m - current_m))/1000UL+unixTimeAtServer_s; unixTimeAtServer_s = ret_s; arduinoTimeAtServer_m = millis(); } } return ret_s; } void printHelp() { Serial.println("All commands are case insensitive."); Serial.println(); Serial.println("T : Print temperature"); Serial.println("H : Print humidity"); Serial.println("R : Connect to server"); Serial.println("L : Print recent observation logs"); Serial.println("I : Print node information"); Serial.println("S : Print last connection status"); Serial.println("V : Toggle verbose mode"); Serial.println("E : Print addr and port in RAM read from EEPROM"); Serial.println("W : Write currnet addr and port to EEPROM"); Serial.println("C : Clear EEPROM"); Serial.println("? : Print this help"); } // EEPROM functions void setServerParameters() { if( checkEEPROMAddrPort() ) { getEEPROMAddrPort(serverROM,&portROM); if(useEEPROMParams) { getEEPROMAddrPort(server,&port); } Serial.println("Read from EEPROM"); } else { writeEEPROMAddrPort(server,port); getEEPROMAddrPort(serverROM,&portROM); Serial.println("Wrote to EEPROM"); } return; } boolean cmpServerAndEEPROM(byte si[],int sp, byte ei[], int ep) { boolean result = true; for(int i = 0; i < 4; i++ ) if( si[i] != ei[i] ) result = false; if( sp != ep ) result = false; return result; } boolean checkEEPROMAddrPort() { byte a[2]; boolean checkOK = true; for( int i = 0; i < 6; i++ ) { a[0] = EEPROM.read(i); a[1] = ~(EEPROM.read(i+6)); if( a[0] != a[1] ) checkOK = false; } return checkOK; } void printEEPROMAddrPort() { Serial.print(serverROM[0],DEC); for( int i = 1; i < 4; i++ ) { Serial.print("."); Serial.print(serverROM[i],DEC); } Serial.print(" "); Serial.println(portROM); return; } void printEEPROMAddrPortRaw() { Serial.print(EEPROM.read(0),DEC); for( int i = 1; i < 12; i++ ) { Serial.print(" "); Serial.print(EEPROM.read(i),DEC); } Serial.println(); Serial.print(analogRead(0)); for( int i = 1; i < 5; i++ ) { Serial.print(" "); Serial.print(analogRead(i)); } Serial.println(); return; } void getEEPROMAddrPort(byte p[],int *pport) { for( int i = 0; i < 4; i++ ) p[i] = EEPROM.read(i); *pport = EEPROM.read(4) * 256 + EEPROM.read(5); return; } void writeEEPROMAddrPort(byte a[],int port) { for( int i = 0; i < 4; i++ ) { EEPROM.write(i,a[i]); EEPROM.write(i + 6,~a[i]); } byte b = port >> 8; byte c = port % 256; EEPROM.write(4,b); EEPROM.write(4+6,~b); EEPROM.write(5,c); EEPROM.write(5+6,~c); return; } void clearEEPROM() { for( int i = 0; i < 12; i++ ) EEPROM.write(i,0); return; } // tiny conversion functions unsigned long char2ulong(char b[],int j, int k) { unsigned long ret; ret = 10UL*(b[j]-'0'); for( int i = j+1; i < k ; i++ ) ret = 10UL*(ret+(b[i]-'0')); ret += (b[k]-'0'); return ret; } int char2int(char b[],int j, int k) { int ret; ret = 10*(b[j]-'0'); for( int i = j+1; i < k ; i++ ) ret = 10*(ret+(b[i]-'0')); ret += (b[k]-'0'); return ret; }