#include <EEPROM.h> #include <Arduino.h> #include <EtherCard.h> #include <MemoryFree.h> #include <Time.h> #define VERSION "WOWlanCloud 20140105-1016" // min/maj, cmd #define URL "/index.php?action=get" //&id=zorglub" #define WEBSITE "wolpobox.logsm.net" #define PERIODEMS 5000 #define WOLLISTENPORT 9 #define WOLTARGETPORT 9 #define WOLOUTPORT 100 // EEPROM map #define RESET 0 // compte les 4 off/on pour hard reset #define PHYBINAEEPROM 1 // fixe 6 #define PHYSTREEPROM PHYBINAEEPROM+6 #define IPBINAEEPROM PHYSTREEPROM+13 // fixe 4 // ip en mod caractère pas indispensable à virer #define IPSTREEPROM IPBINAEEPROM+4 // fixe 4 #define NAMEEEPROM IPSTREEPROM+4 // variable, max 20, null terminatef #define LONNAME 21 #define MAILTOEEPROM NAMEEEPROM+LONNAME // variable, null terminated, max 60 #define LONMAILTO 61 #define URLEEPROM MAILTOEEPROM+LONMAILTO #define LONURLEEPROM 60 #define EEPROMUSED URLEEPROM+LONURLEEPROM // #define true 1 #define false 0 // ethernet interface mac address, must be unique on the LAN static byte mymac[] = { 0x00,0x16,0xA5,0x76,0x19,0x3A }; int DEBUG=true; // true for debugging int TRACE=true; //some progree info. int CLOUD=true; int SERVER=true; int PROXY=true; int DALLAS=false; // real clock & memory #define LBUF 400 char id[LONNAME+1]="zorglub"; char website[] PROGMEM = WEBSITE; //char url[] PROGMEM = URL; static byte lowip= 255; // left part by Dhcp 255 if no! static byte unb ; // for ucase static uint32_t timer; static byte broadcast[4] = {255,255,255,255} ; //{255,255,255,255}; static int n=0; // count http requests over cloud static int ok=true; // global abandon static int lenquoi; static int termine; // 1 when found static int eq; static int iii; static int pv; static int ipv; // byte mac[6] ; byte key[10]; char magic[102]; char alphabet[17] ="0123456789ABCDEF"; #define LHEXA 100 char hexamac[LHEXA]=""; byte Ethernet::buffer[LBUF]; //?????? BufferFiller bfill; //??????? static int udpon=0; int write_str_eeprom( char* source ,int address, int allowed){ if (strlen(source)>allowed) { Serial.print("bug1"); return false; } for (iii=0;iii<1+strlen(source);iii=iii+1) EEPROM.write(address+iii,(byte)source[iii]); Serial.print(source); Serial.print(" storerd at "); Serial.println(address); return true; } void write_binary_eeprom(int lon, int address, int allowed){ if (lon>allowed) { Serial.print("bug2"); return; } for (iii=0;iii<lon;iii=iii+1) EEPROM.write(address+iii,(byte)hexamac[iii]); } int read_str_eeprom(char* target,int address, int allowed){ /* if (allowed>strlen(hexamac)) { Serial.print("bug33333333333333333333333 "); Serial.println(number); return; } */ int lonread=0; iii=0; while (lonread==0) { if (iii,allowed) return false; target[iii]=(char)EEPROM.read(address+iii); if (target[iii]==0) lonread=iii; } Serial.println(target); return true; } void read_binary_eeprom(int lon,int address, int allowed){ if (lon>allowed) { Serial.print("bug44444444444444444444444"); return; } for (iii=0;iii<lon;iii++) hexamac[iii]=(char)EEPROM.read(address+iii); } void prtoptions(){ Serial.print("Options: Debug, Trace, Cloud, Server, Proxy:"); Serial.print (DEBUG); Serial.print (TRACE); Serial.print (CLOUD); Serial.print (SERVER); Serial.println (PROXY); Serial.print("freeMemory()="); Serial.println(freeMemory()); } void prttime(int call ){ time_t t=now(); Serial.print (call); Serial.print(":"); Serial.print(t); Serial.print (" now>>"); Serial.print(year(t)); Serial.print("/"); Serial.print(month(t)); // The month now (1-12) Serial.print("/"); Serial.print(day(t)); // The day now (1-31) Serial.print("-"); Serial.print(hour(t)); // The hour now (0-23) Serial.print(":"); Serial.print(minute(t)); // The minute now (0-59) Serial.print(":"); Serial.print(second(t)); // The second now (0-59) Serial.println(""); } void blink(int led, int secondes, int on, int off){ iii=secondes*1000; while (iii>0){ Serial.print("."); digitalWrite(led, 0); // turn the LED on (HIGH is the voltage level) delay(on); // wait for a second digitalWrite(led, 1); // turn the LED off by making the voltage LOW delay(off); // wait for a second iii=iii-on-off; } } void raz(){ Serial.println("EEPROM Reeseted!"); // for (iii=0;iii<EEPROMUSED;iii++) EEPROM.write(iii,0); // ip // url //#define URLEEPROM MAILTOEEPROM+LONMAILTO //#define LONURLEPROM 60 write_str_eeprom( URL, URLEEPROM, LONURLEEPROM ); } void chkhardreset(){ int rc; rc=1+EEPROM.read(RESET); EEPROM.write(RESET,rc); if (rc>=4) raz(); if (rc==1) blink(13,4,100,900); else blink(13,4,900,100); EEPROM.write(RESET,0); } void setup () { Serial.begin(9600); write_str_eeprom("zorglub",NAMEEEPROM,LONNAME); write_str_eeprom("/index/php?action=get",URLEEPROM,LONURLEEPROM); Serial.print("waitting 10\" for hard reset!"); chkhardreset(); Serial.println(" andiamo! "); prttime(1); // check EEprom for mc address termine=false; for (iii=1;iii<6;iii=iii+1) if (EEPROM.read(PHYBINAEEPROM+iii)!=255) termine=true; if (!termine){ Serial.println("no previous PHY in EEPROM, added"); for (iii=0;iii<6;iii=iii+1) EEPROM.write(PHYBINAEEPROM+iii, mymac[iii]); } // for (iii=0;iii<6;iii=iii+1) mymac[iii]=EEPROM.read(PHYEEPROM+iii); for (iii=0;iii<6;iii=iii+1) { Serial.print(alphabet[mymac[iii]/16]); Serial.print(alphabet[mymac[iii]%16]); Serial.print(":"); } Serial.println(" <---- MAC used"); // id if (EEPROM.read(NAMEEEPROM)!=255) { read_str_eeprom(id,NAMEEEPROM,LONNAME); } Serial.println(VERSION); prtoptions(); Serial.print("Ethernet Controller: "); if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0) { ok=false; Serial.println( "Access Failed."); } else Serial.println("Ok."); // ether.staticSetup(myip); if (ok) { Serial.print("Dhcp: "); if (!ether.dhcpSetup()) { Serial.println("failed."); // setting fixed ip ether.myip[0]=192; ether.myip[1]=168; ether.myip[2]=100; ether.myip[3]=1; } else Serial.println("Ok."); } if (ok){ if (lowip<255) ether.myip[3]=lowip; ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); ether.printIp("DNS: ", ether.dnsip); if (CLOUD){ if (!ether.dnsLookup(website)) { Serial.println("DNS failed"); ok=false; } if (ok) { ether.printIp("SRV: ", ether.hisip); } } } //register udpSerialPrint() to port 1337 if (ok && PROXY) { ether.udpServerListenOnPort(&udpReceivedCallback, WOLLISTENPORT); Serial.print("listen wol on UDP port: "); Serial.println(WOLLISTENPORT); } } // return used part word getvalue(word off,word len,char retour[],int lenret,char pin[]){ lenquoi=strlen(pin); termine=false; // true whenpin found iii=off-1; while (!termine) { eq=0; iii=iii+1; if (iii==len) { //termine=true; // start pin not found // Serial.println("pas trouve initiale en bour"); retour[0]=0; return len; } while (!termine && Ethernet::buffer [iii+eq]==pin[eq]){ // Serial.print (pin[eq]); // Serial.println("trouve une ettre"); eq=eq+1; if (eq>=lenquoi ) termine=true; // pin not found if (iii+eq>len) { retour[0]=0; return len; } } } // Serial.println(""); // get value termine=false; ipv=0; // Serial.println("trouve pin "); //Serial.print("reponse="); while (!termine && iii+eq+1+ipv<len && ipv<lenret ) { retour[ipv]=Ethernet::buffer [iii+eq+ipv]; if (retour[ipv]==';') { // Serial.println("ok ; final "); retour[ipv]=0; termine=true; } ipv=ipv+1; } if (!termine) { // Serial.println ("no colon found"); // ok=false; retour[0]=0; return len; } return iii+eq+ipv; } /* void doopt (char* cmd,int target, int v){ if (strcmp(hexamac,cmd)==0 ) target=v; } */ void option(int v){ // prtoptions(); if (strcmp(hexamac,"DEBUG")==0 ) DEBUG=v; // doopt("DEBUG",DEBUG,v); if (strcmp(hexamac,"TRACE")==0 ) TRACE=v; if (strcmp(hexamac,"CLOUD") ==0) CLOUD=v; if (strcmp(hexamac,"PROXY" )==0) PROXY=v; if (strcmp(hexamac,"SERVER")==0 ) SERVER=v; if (TRACE) prtoptions(); } void ucase(word off,word len){ // search for pin: for (iii=off;iii<len;iii=iii+1){ unb= Ethernet::buffer [iii]; if (unb>96 && unb <=96+26) Ethernet::buffer [iii]=unb-32; } } void domax(int off,int len,const char* qui){ if (DEBUG) for (int j=off;j<len;j=j+1) Serial.print((char ) Ethernet::buffer[j]); // check print full packet ucase(off,len); //Serial.println("up"); // keep options // --------------------------- repetable commands word start; hexamac[0]='.'; hexamac[1]=0; start=off; while (strlen(hexamac)>0) { start=getvalue(start,len,hexamac,100,"SET:"); if (strlen(hexamac)>0) option(true) ; // optionis in hexamac } hexamac[0]='.'; hexamac[1]=0; start=off; while (strlen(hexamac)>0) { start=getvalue(start,len,hexamac,100,"CLR:"); if (strlen(hexamac)!=0) option(false) ; // optionis in hexamac } hexamac[0]='.'; hexamac[1]=0; start=off; while (strlen(hexamac)>0) { start=getvalue(start,len,hexamac,100,"PIN:"); if (strlen(hexamac)>0) { if (TRACE) Serial.println(hexamac); char* sep=strchr(hexamac,':'); if (TRACE) { Serial.print("arg:"); Serial.print (sep-hexamac); } hexamac[sep-hexamac]=0; if (TRACE) { Serial.print("pin:"); Serial.print (sep-hexamac); } if (TRACE) { Serial.print("val:"); Serial.println (sep); } } } // simple commands start=getvalue(off,len,hexamac,100,"RAZ:"); if (start<len) { Serial.print ("raz:!"); Serial.println(""); raz(); } start=getvalue(off,len,hexamac,100,"MAILTO:"); if (strlen(hexamac)>0) { write_str_eeprom(hexamac,MAILTOEEPROM,LONMAILTO); Serial.print ("mailto:"); Serial.println(hexamac); } start=getvalue(off,len,hexamac,100,"TIME:"); if (strlen(hexamac)>0) { uint32_t tt= atol(hexamac); setTime(tt); // Serial.println(tt); // Serial.println(now()); if (TRACE) { Serial.println(""); prttime(2); } } start=getvalue(off,len,hexamac,100,"PHY:"); if (strlen(hexamac)>0) { // 12 to 6 if (h2d(hexamac[1])%2==1) { Serial.println("rejected"); } else { for (iii=0;iii<6;iii=iii+1) EEPROM.write(PHYBINAEEPROM+iii, h2d(hexamac[2*iii])*16+h2d(hexamac[2*iii+1]) ); for (iii=0;iii<12;iii=iii+1) EEPROM.write(PHYSTREEPROM+iii, hexamac[iii] ); EEPROM.write(PHYSTREEPROM+12,0); } } getvalue(off,len,hexamac,100,"IP:"); if (strlen(hexamac)>0) { // for (iii=0;iii<6;iii=iii+1) EEPROM.write(PHYBINAEEPROM+iii, h2d(hexamac[2*iii])*16+h2d(hexamac[2*iii+1]) ); Serial.println("faire copie bina"); for (iii=0;iii<strlen(hexamac);iii=iii+1) EEPROM.write(IPSTREEPROM+iii, hexamac[iii] ); EEPROM.write(PHYSTREEPROM+12,0); } getvalue(off,len,hexamac,100,"ID:"); getvalue(off,len,hexamac,100,"NAME:"); if (strlen(hexamac)>0) { for (iii=0;iii<strlen(hexamac);iii=iii+1) EEPROM.write(NAMEEEPROM+iii, hexamac[iii] ); } getvalue(off,len,hexamac,100,"TOKEN:"); getvalue(off,len,hexamac,100,"MAC:"); buildmagic(); // will check hexamac! and set termine // if (termine) sendmagic(magic,102) later } // called when the client request is complete static void cloud_callback (byte status, word off, word len) { Ethernet::buffer[len] = 0; Serial.print(off); Serial.print(" "); Serial.print(len); Serial.println("<-- off lren"); domax(off,len,"cloud"); if (termine) sendmagic(magic,102); } //callback that echo received packet (magic!) void udpReceivedCallback(word port, byte ip[4], const char *data, word len) { if (!udpon) { // protect again re-entrance' udpon=true; if (DEBUG){ Serial.println(" Raw: "); Serial.println(data); } if (TRACE) Serial.println ("udp packet forwarded as broadcast"); sendmagic((char *) data,len); if (DEBUG) Serial.println(" done"); udpon=false; } } static word homePage(int off,int len,int ok) { n=n+1; // compte les appels à homePage uint32_t t; t=now(); bfill = ether.tcpOffset(); bfill.emit_p(PSTR( //??????? "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" // "<meta http-equiv='refresh' content='1'/>" "<title>Po server</title>" "<h1>$D:$D:$D $D/$D/</h1> n= $D ok=$D time=$D "), hour(t), minute(t), second(t) ,day(t),month(t),year(t), n,ok); //??????? return bfill.position(); ok=0; } int h2d(char h){ char* ih= strchr(alphabet,h); char* i0= strchr(alphabet,'0'); int ici=ih-i0; if (ici>15) ici=ici-6; return ici; } void buildmagic (){ termine=false; if (strlen(hexamac)!=12) return; if (DEBUG) Serial.print("build magic mac:"); termine=true; for (iii=0;iii<12;iii++) { char unc=hexamac[iii]; Serial.print(unc); if (unc<'0' || unc>'F' || (unc>'9' && unc<'A')) termine=false; } if (!termine) return; for (int repe=0;repe<6;repe=repe+1) magic[repe]=255; for (iii=0;iii<6;iii=iii+1){ magic[iii]=h2d(hexamac[2*iii])*16+h2d(hexamac[2*iii+1]); for (int repe=1;repe<16;repe=repe+1){ magic[6+6*repe+iii]=magic[6+iii]; } } } void sendmagic(char* magic,int len){ ether.sendUdp(magic, len, WOLOUTPORT, broadcast, WOLTARGETPORT); } int addstrtosandbox(char* quoi){ int lon=strlen(quoi); int lonmac=strlen(hexamac); if (lon+lonmac>=LHEXA) return false; for (iii=0;iii<1+lon;iii=iii+1) hexamac[lonmac+iii]=quoi[iii]; return true; } int addeepromtosandbox(int ad){ int lon=0; int lonmac=strlen(hexamac); // Serial.print (lonmac); // Serial.println("--<lonlmac"); iii=ad; while (lon==0 && (iii-ad)<(LHEXA-lonmac)) { if (EEPROM.read(iii)==0) lon=iii-ad; iii=iii+1; } if (lon+lonmac>=LHEXA) { return false; } for (iii=0;iii<1+lon;iii=iii+1) { hexamac[lonmac+iii]=EEPROM.read(ad+iii); } return true; } void loop () { if (ok) { if (PROXY) { // nothing } if (CLOUD) ether.packetLoop(ether.packetReceive()); if (CLOUD && ( millis() > timer) ) { timer = millis() + PERIODEMS; Serial.println(""); Serial.println("appel cloud"); hexamac[0]=0; addeepromtosandbox(URLEEPROM); addstrtosandbox("&id="); addeepromtosandbox(NAMEEEPROM); Serial.print (hexamac); Serial.println("<---totale"); ether.browseUrl(PSTR(URL) , "", website, cloud_callback); } // end cloud if (SERVER){ word len = ether.packetReceive(); word pos = ether.packetLoop(len); if (pos>0) {// check if valid tcp data is received domax(pos,len,"http"); ether.httpServerReply(homePage(pos,len,termine)); // send web page data if (termine) sendmagic(magic,102); /* ucase(pos,len); if (DEBUG) Serial.println("received http"); getvalue(pos,len,hexamac,100,"MAC:"); if (TRACE) { Serial.print(hexamac); Serial.println("<----server http"); } if (strlen(hexamac)>0) buildmagic(); if (termine) { sendmagic(magic,102); if (TRACE) Serial.println("Sent."); } */ } } } }