/* ------------------------------------------------------------------------ * Lndk_Avra05.ino * Interface Arduino pour regulateur solaire EP-SOLAR Tracer 2210RN * * Copyright (c) 2007-2008, Marc Dilasser, Le Net du Kermeur * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1 Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2 Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3 Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * History : * Original : Marc Dilasser, Le Net du Kermeur, Mars 2013 * * Version 0.4 * Moyenne des dix dernieres mesures * RESET, DUMP * Version 0.5 * TIME, UPTIME, PORT, LOAD, prise en compte 1 seul acces si multiple */ // Modifications dans la librairie EtherShield // http://blog.derouineau.fr/2011/07/putting-enc28j60-ethernet-controler-in-sleep-mode/ #include "EtherShield.h" #include #include #include "Lndk_Avra05.h" #define MYWWWPORT 80 #define ETH_SIZE 512 #define SER_SIZE 256 #define MSG_SIZE 256 #define DAT01012013 1356994800 #define NORMAL 0x00 #define MESURE 0x01 #define PREDELESTAGE1 0x02 #define PREDELESTAGE2 0x03 #define DELESTAGE 0x04 #define MAINTENANCE 0x05 #define BUTTON 0x02 #define MACADDRESS 0 #define ADDRESS 1 #define MASK 2 #define GATEWAY 3 #define WWWPORT 4 // les modes ECOnomie #define ECOSTOP 0 #define ECOSEARCH 1 #define ECORUNNING 2 // Adresses MAC, IP, GATEWAY et PORT par defaut // Configurables en Eeprom par les commandes MACA, ADDR, GATE et PORT uint8_t mymac[6] = { 0x54,0x55,0x56,0x21,0x22,0x23}; uint8_t myip[4] = {192,168,1,25}; uint8_t gwip[4] = {192,168,1,1}; uint8_t myport = MYWWWPORT ; static uint8_t ethbuf[ETH_SIZE + 1] = ""; static uint8_t serbuf[SER_SIZE + 1] = ""; static uint8_t msgbuf[MSG_SIZE + 1] = ""; // Stockage des mesures (6 * 10 * 2 + 9 * 10 = 210 octets) static uint16_t mbat[10], msol[10], mcon[10], modv[10], mbfv[10], mcur[10]; static uint8_t mlod[10], movl[10], mlsc[10], msoc[10], mbol[10], mbod[10], mful[10], mchg[10], mtmp[10]; int serind, msgind; #ifdef SERIALDEBUG int SerialDebug = 0; #endif int FlagMaintenance = LOW; unsigned long time, startTime, DureeDelestage = 20000; unsigned long t0Eco, t1Eco, MoyennEco, DiffEco[4]; unsigned long t0Mesure = 10000L, t1Mesure = 0; int State, LndkRunRun, modeEco = ECOSEARCH; int nbmes = 0; // The ethernet shield EtherShield es=EtherShield(); /* -------------------------------------------------------- h t t p 2 0 0 o k */ uint16_t http200ok(void) { return(es.ES_fill_tcp_data_p(ethbuf, 0, PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"))); } /* ------------------------------------------------ p r i n t _ w e b p a g e Prepare the webpage by writing the data to the tcp send buffer */ uint16_t print_webpage(uint8_t *buf) { uint16_t plen; plen=http200ok(); plen = es.ES_fill_tcp_data_p(ethbuf, plen, PSTR("Lndk Tracer\n")); plen = es.ES_fill_tcp_data_p(ethbuf, plen, PSTR("

Lndk Tracer version v0.5

\n")); plen = es.ES_fill_tcp_data(ethbuf, plen, (char *) msgbuf); plen = es.ES_fill_tcp_data_p(ethbuf, plen, PSTR("\n\n")); plen = es.ES_fill_tcp_data_p(ethbuf, plen, PSTR("\n")); return(plen); } /* -------------------------------------------------- W r i t e E t h 2 H e x */ int WriteEth2Hex(int position, int nbval, int moyenne, uint8_t table[]) { int ij; byte inChar; unsigned long somme; somme = 0L; for (ij = 0; ij < nbval; ij ++) somme = somme + table[ij]; if (moyenne) somme /= nbval; inChar = (somme & 0x00F0) >> 4; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); inChar = somme & 0x000F; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); msgbuf[position++] = 32; return position; } /* -------------------------------------------------- W r i t e E t h 4 H e x */ int WriteEth4Hex(int position, int nbval, uint16_t table[]) { int ij; byte inChar; unsigned long somme; somme = 0L; for (ij = 0; ij < nbval; ij ++) somme = somme + table[ij]; somme = somme / nbval; inChar = (somme & 0xFFFF) >> 12; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); inChar = (somme & 0x0F00) >> 8; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); inChar = (somme & 0x00F0) >> 4; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); inChar = somme & 0x000F; msgbuf[position++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); msgbuf[position++] = 32; return position; } /* -------------------------------------------------- W r i t e E t h T i m e Ecriture d'un temps time_t en huit caracteres hexadecimaux */ int WriteEthTime(int position, time_t time) { int ij; ij = time >> 28; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x0F000000) >> 24; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x00F00000) >> 20; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x000F0000) >> 16; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x0000F000) >> 12; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x00000F00) >> 8; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = (time & 0x000000F0) >> 4; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); ij = time & 0x0F; msgbuf[position++] = (ij > 9) ? (55 + ij) : (48 +ij); msgbuf[position++] = ' '; return position; } /* ---------------------------------------------------------- S e n d T i m e */ uint16_t EthSendTime(void) { int ik; uint16_t lenstate; // serbuf[serind] = 0; // Flag du programme pour info, par defaut 0000 msgbuf[0] = '0' + timeStatus(); if (nbmes > 15) nbmes = 15; msgbuf[1] = (nbmes > 9) ? (55 + nbmes) : (48 + nbmes); msgbuf[2] = 48 + modeEco; msgbuf[3] = 48 + State; msgbuf[4] = ' '; ik = 5; // Champ date en secondes depuis 1/1/1970, en hexadecimal ik = WriteEthTime(ik, now()); // Uptime en secondes ik = WriteEthTime(ik, (now() - startTime)); msgind = ik; msgbuf[ik] = 0; lenstate = print_webpage(ethbuf); return (lenstate); } /* -------------------------------------------------------- S e n d S t a t e */ uint16_t SendState(int dump) { int ij, ik; uint16_t lenstate; time_t time; // serbuf[serind] = 0; time = now(); // Flag du programme pour info, par defaut 0000 msgbuf[0] = '0' + timeStatus(); if (nbmes > 15) nbmes = 15; msgbuf[1] = (nbmes > 9) ? (55 + nbmes) : (48 + nbmes); msgbuf[2] = 48 + modeEco; msgbuf[3] = 48 + State; msgbuf[4] = ' '; ik = 5; // if (timeStatus() != timeNotSet) time = now(); // Champ date en secondes depuis 1/1/1970, en hexadecimal ik = WriteEthTime(ik, now()); if (dump > 0) { // Donnees lues sur le port serie, en hexadecimal for (ij = 0; ij < min(40, SER_SIZE); ij++) { byte inChar; inChar = serbuf[ij] >> 4; msgbuf[ik++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); inChar = serbuf[ij] & 0x0F; msgbuf[ik++] = (inChar > 9) ? (55 + inChar) : (48 + inChar); msgbuf[ik++] = 32; } } else { if (nbmes > 0) { int nbval; // Nombre de valeurs retenues nbval = min(10, nbmes); // Tension batterie ik = WriteEth4Hex(ik, nbval, mbat); // Tension panneau solaire ik = WriteEth4Hex(ik, nbval, msol); // Consommation ik = WriteEth4Hex(ik, nbval, mcon); // Over discharge voltage ik = WriteEth4Hex(ik, nbval, modv); // Batterie Full Voltage ik = WriteEth4Hex(ik, nbval, mbfv); // Courant de charge; ik = WriteEth4Hex(ik, nbval, mcur); // Load ON/OFF ik = WriteEth2Hex(ik, nbval, 0, mlod); // Indicateur Overload movl[10] ik = WriteEth2Hex(ik, nbval, 0, movl); // Indicateur Load short circuit, mlsc[10] ik = WriteEth2Hex(ik, nbval, 0, mlsc); // Indicateur SOC, faire la moyenne msoc[10] ik = WriteEth2Hex(ik, nbval, 1, msoc); // Indicateur Batterie overload mbol[10] ik = WriteEth2Hex(ik, nbval, 0, mbol); // Indicateur batterie over discharge mbod[10] ik = WriteEth2Hex(ik, nbval, 0, mbod); // Indicateur batterie full mful[10] ik = WriteEth2Hex(ik, nbval, 0, mful); // Indicateur de charge mchg[10] ik = WriteEth2Hex(ik, nbval, 0, mchg); // Temperature mtmp[10], faire la moyenne ik = WriteEth2Hex(ik, nbval, 1, mtmp); } } msgind = ik; msgbuf[ik] = 0; lenstate = print_webpage(ethbuf); #ifdef SERIALDEBUG if (SerialDebug > 0) { Serial.print("Recu "); Serial.print(serind); Serial.println(" caracteres"); } #endif if (dump == 0) nbmes = 0; return (lenstate); } /* ---------------------------------------------------- D e u x H e x a E t h */ uint8_t DeuxHexaEth(int position) { uint8_t inChar; uint8_t value; value = 0; inChar = ethbuf[position]; if ((inChar >= '0') && (inChar <= '9')) { value = (inChar - 48); } else { if ((inChar >= 'A') && (inChar <= 'F')) { value = inChar - 55; } } value = value << 4; inChar = ethbuf[position + 1]; if ((inChar >= '0') && (inChar <= '9')) { value |= (inChar - 48); } else { if ((inChar >= 'A') && (inChar <= 'F')) { value |= inChar - 55; } else { value = 0; } } return(value); } /* -------------------------------------------------------- C o n f i g _ I p Ecriture en EEPROM de la configuration IP */ int Config_Ip(int config, int position) { uint8_t aa = 0, ab = 0, a1, a2, a3, a4; int ik = 0; // Configuration IPV4 if (strncmp("?P1=", (char *)&(ethbuf[position]), 4) == 0) { // Lecture des 8 caracteres hexaA ik = position + 4; if (config == MACADDRESS) { aa = DeuxHexaEth(ik); ik += 2; ab = DeuxHexaEth(ik); ik += 2; } a1 = DeuxHexaEth(ik); ik += 2; a2 = DeuxHexaEth(ik); if (config != WWWPORT) { ik += 2; a3 = DeuxHexaEth(ik); ik += 2; a4 = DeuxHexaEth(ik); } else a3 = a4 = 0; #ifdef SERIALDEBUG if (SerialDebug) { Serial.println(a1); Serial.println(a2); Serial.println(a3); Serial.println(a4); } #endif if ((a1 != 0) || (a2 != 0) || (a3 != 0) || (a4 != 0)) { ik = config * 8; switch (config) { case MACADDRESS : EEPROM.write(ik++, 'M'); EEPROM.write(ik++, 'A'); EEPROM.write(ik++, aa); EEPROM.write(ik++, ab); break; case ADDRESS : EEPROM.write(ik++, 'A'); EEPROM.write(ik++, 'D'); EEPROM.write(ik++, 'D'); EEPROM.write(ik++, 'R'); break; case MASK : EEPROM.write(ik++, 'M'); EEPROM.write(ik++, 'A'); EEPROM.write(ik++, 'S'); EEPROM.write(ik++, 'K'); break; case GATEWAY : EEPROM.write(ik++, 'G'); EEPROM.write(ik++, 'A'); EEPROM.write(ik++, 'T'); EEPROM.write(ik++, 'E'); break; case WWWPORT : EEPROM.write(ik++, 'P'); EEPROM.write(ik++, 'O'); EEPROM.write(ik++, 'R'); EEPROM.write(ik++, 'T'); break; } EEPROM.write(ik++, a1); EEPROM.write(ik++, a2); EEPROM.write(ik++, a3); EEPROM.write(ik++, a4); } } else { #ifdef SERIALDEBUG if (SerialDebug) { Serial.println("Manque parametres"); } #endif } return (ik); } /* ---------------------------------------------- L i r e _ C o n f i g _ I P */ void Lire_Config_IP(void) { uint8_t aa, ab, a1, a2, a3, a4; uint8_t ik; for (ik = 0; ik < 64; ik ++) { serbuf[ik] = EEPROM.read(ik); } serbuf[ik] = 0x00; ik = 0; // Lecture adresse MAC if ((serbuf[ik] == 'M') && (serbuf[ik + 1] == 'A')) { ik += 2; aa = serbuf[ik++]; ab = serbuf[ik++]; a1 = serbuf[ik++]; a2 = serbuf[ik++]; a3 = serbuf[ik++]; a4 = serbuf[ik++]; if ( ((aa != 0) || (ab != 0) || (a1 != 0) || (a2 != 0) || (a3 != 0) || (a4 != 0)) && ((aa != 0xFF) || (ab != 0xFF) || (a1 != 0xFF) || (a2 != 0xFF) || (a3 != 0xFF) || (a4 != 0xFF))) { mymac[0] = aa; mymac[1] = ab; mymac[2] = a1; mymac[3] = a2; mymac[4] = a3; mymac[5] = a4; } } // Lecture adresse IP ik = ADDRESS * 8; if ((serbuf[ik] == 'A') && (serbuf[ik + 1] == 'D') && (serbuf[ik + 2] == 'D') && (serbuf[ik + 3] == 'R')) { ik += 4; a1 = serbuf[ik++]; a2 = serbuf[ik++]; a3 = serbuf[ik++]; a4 = serbuf[ik]; if ( ((a1 != 0) || (a2 != 0) || (a3 != 0) || (a4 != 0)) && ((a1 != 0xFF) || (a2 != 0xFF) || (a3 != 0xFF) || (a4 != 0xFF))) { myip[0] = a1; myip[1] = a2; myip[2] = a3; myip[3] = a4; } } // Adresse passerelle ik = GATEWAY * 8; if ((serbuf[ik] == 'G') && (serbuf[ik + 1] == 'A') && (serbuf[ik + 2] == 'T') && (serbuf[ik + 3] == 'E')) { ik += 4; a1 = serbuf[ik++]; a2 = serbuf[ik++]; a3 = serbuf[ik++]; a4 = serbuf[ik]; if ( ((a1 != 0) || (a2 != 0) || (a3 != 0) || (a4 != 0)) && ((a1 != 0xFF) || (a2 != 0xFF) || (a3 != 0xFF) || (a4 != 0xFF))) { gwip[0] = a1; gwip[1] = a2; gwip[2] = a3; gwip[3] = a4; } } // Port TCP ik = WWWPORT * 8; if ((serbuf[ik] == 'P') && (serbuf[ik + 1] == 'O') && (serbuf[ik + 2] == 'R') && (serbuf[ik + 3] == 'T')) { ik += 4; a1 = serbuf[ik++]; a2 = serbuf[ik++]; if ((a1 != 0) || (a2 != 0)) { myport = a1 * 256 + a2; } } } /* ---------------------------------------- E c o R u n n i n g 2 S e a r c h Desactivation du mode ECO s'il etait actif */ void EcoRunning2Search() { if (modeEco == ECORUNNING) { modeEco = ECOSEARCH; #ifdef SERIALDEBUG if (SerialDebug) { Serial.print("Mode ECO desactive"); } #endif } } /* -------------------------------------------- W r i t e _ P r e a m b u l e Envoi de debut de commande */ void Write_Preambule(void) { int ij; for (ij = 0; ij < 3; ij ++) { Serial.write(0xEB); Serial.write(0x90); } } /* -------------------------------------------------------- L o a d O n O f f */ void LoadOnOff(int on) { // Envoi de la commande de coupure de l'utilisation Write_Preambule(); // Synchro Serial.write(0x00); // Device Serial.write(0xAA); // Commande Serial.write(0x01); // Longueur de donnees if (on) { Serial.write(0x01); // Donnee Serial.write(0x4D); Serial.write(0x9A); // Checksum } else { Serial.write(0x00); // Donnee Serial.write(0x5D); Serial.write(0xDB); // Checksum } Serial.write(0x7F); // Fin de commande } /* ---------------------------------------------- M e s u r e s _ T r a c e r Si une sequence de mesures du regulateur est reconnue, l'enregistrer */ void Mesures_Tracer(void) { int ij; // Detection de mesure, si ok la sauvegarder // 5 10 15 20 25 30 36 // EB 90 EB 90 EB 90 00 A0 18 DB 04 0F 00 00 00 09 00 4B 04 C8 05 01 00 00 25 00 00 00 00 2B 00 00 00 92 74 7F if ( (serbuf[0] == 0xEB) && (serbuf[1] == 0x90) && (serbuf[2] == 0xEB) && (serbuf[3] == 0x90) && (serbuf[4] == 0xEB) && (serbuf[5] == 0x90)) { // Decaler anciennes mesures for (ij = 8; ij >= 0; ij --) { mbat[ij + 1] = mbat[ij]; msol[ij + 1] = msol[ij]; mcon[ij + 1] = mcon[ij]; modv[ij + 1] = modv[ij]; mbfv[ij + 1] = mbfv[ij]; mlod[ij + 1] = mlod[ij]; movl[ij + 1] = movl[ij]; mlsc[ij + 1] = mlsc[ij]; msoc[ij + 1] = msoc[ij]; mbol[ij + 1] = mbol[ij]; mbod[ij + 1] = mbod[ij]; mful[ij + 1] = mful[ij]; mchg[ij + 1] = mchg[ij]; mtmp[ij + 1] = mtmp[ij]; mcur[ij + 1] = mcur[ij]; } mbat[0] = (serbuf[10] << 8) | serbuf[9]; msol[0] = (serbuf[12] << 8) | serbuf[11]; mcon[0] = (serbuf[16] << 8) | serbuf[15]; modv[0] = (serbuf[18] << 8) | serbuf[17]; mbfv[0] = (serbuf[20] << 8) | serbuf[19]; mlod[0] = serbuf[21]; movl[0] = serbuf[22]; mlsc[0] = serbuf[23]; msoc[0] = serbuf[24]; mbol[0] = serbuf[25]; mbod[0] = serbuf[26]; mful[0] = serbuf[27]; mchg[0] = serbuf[28]; mtmp[0] = serbuf[29]; mcur[0] = (serbuf[31] << 8) | serbuf[30]; nbmes++; serind=0; serbuf[SER_SIZE] = 0; } } /* ---------------------------------------------------- T i m e C o m m a n d */ int TimeCommand(char *param, int setIt) { int ij; char a1; unsigned long t0, t1; if (setIt) { if (strncmp("?P1=", param, 4) == 0) { t0 = 0L; ij = 4; a1 = param[ij++]; while (((a1 >= '0') && (a1 <= '9')) && (ij < 15)) { t0 *= 10; t0 += (a1 - 48); a1 = param[ij++]; } t1 = 0L; if (strncmp("&P2=", ¶m[ij - 1], 4) == 0) { ij += 3; a1 = param[ij++]; while (((a1 >= '0') && (a1 <= '9')) && (ij < 25)) { t1 *= 10; t1 += (a1 - 48); a1 = param[ij++]; } if ((t1 < 120L) || (t1 > 7200L)) t1 = 1200L; setSyncInterval(t1); } // If time not allready set, set startTime if (timeStatus() == 0) { startTime = t0 - (millis() / 1000L); } setTime(t0); #ifdef SERIALDEBUG if (SerialDebug) { Serial.print("Set Time "); Serial.print(t0); Serial.print("("); Serial.print(t1); Serial.println(")"); } #endif } } return (EthSendTime()); } /* ---------------------------------------------------------------- s e t u p */ void setup() { uint8_t ij; // Bouton mode maintenance pinMode(BUTTON, INPUT); pinMode(9, OUTPUT); ij = digitalRead(BUTTON); // Lecture configuration IPV4 en EEPROM desactivee si bouton BUT enfonce if (ij == HIGH) Lire_Config_IP(); // initialize enc28j60 es.ES_enc28j60Init(mymac); // init the ethernet/ip layer: es.ES_init_ip_arp_udp_tcp(mymac,myip, myport); es.ES_client_set_gwip(gwip); // Initialisation du port serie Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.println("Lndk Tracer v0.5"); // Serial.println(millis()); msgind = 0; serind = 0; DiffEco[0] = DiffEco[1] = DiffEco[2] = DiffEco[3] = 0L; t0Eco = t1Eco = millis(); // Forcer mise en ligne de la charge sur un RESET LoadOnOff(1); State = NORMAL; LndkRunRun = 1; } /* ------------------------------------------------------------------ l o o p */ void loop() { static uint16_t dat_p, ij; static int done; static unsigned long t1 = 0L, t2 = 0L, t0State, t1State; uint8_t a1 = 0; while (LndkRunRun) { switch (State) { case NORMAL : // read packet, handle ping and wait for a tcp packet: dat_p=es.ES_packetloop_icmp_tcp(ethbuf,es.ES_enc28j60PacketReceive(ETH_SIZE, ethbuf)); /* dat_p will be unequal to zero if there is a valid http get */ if (dat_p != 0) { // Passer toute la requete en majuscules for (ij = dat_p; (ij < (dat_p + 64)) && (ij <=ETH_SIZE); ij ++) { uint8_t ethChar; ethChar = ethbuf[ij]; if ((ethChar >= 'a') && (ethChar <= 'z')) { ethChar -= 32; ethbuf[ij] = ethChar; } } done = 0; if (strncmp("GET ",(char *)&(ethbuf[dat_p]),4)!=0){ // head, post and other methods: dat_p=http200ok(); dat_p = es.ES_fill_tcp_data_p(ethbuf,dat_p,PSTR("

200 OK

")); done = 1; } // just one web page in the "root directory" of the web server if (strncmp("/ ",(char *)&(ethbuf[dat_p+4]),2)==0){ dat_p=print_webpage(ethbuf); done = 1; } #ifdef SERIALDEBUG if (strncmp("/SERIALDEBUG",(char *)&(ethbuf[dat_p+4]), 12)==0){ SerialDebug = (SerialDebug != 0) ? 0 : 1; if (SerialDebug) { Serial.println("Mode debug"); } dat_p = print_webpage(ethbuf); done = 1; } #endif // Modification et enregistrement de la configuration IP if (strncmp("/MACA", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { Config_Ip(MACADDRESS, dat_p + 9); done = 1; } if (strncmp("/ADDR", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { Config_Ip(ADDRESS, dat_p + 9); done = 1; } if (strncmp("/MASK", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { Config_Ip(MASK, dat_p + 9); done = 1; } if (strncmp("/GATE", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { Config_Ip(GATEWAY, dat_p + 9); done = 1; } if (strncmp("/PORT", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { Config_Ip(WWWPORT, dat_p + 9); done = 1; } if (strncmp("/RESET", (char *)&(ethbuf[dat_p + 4]), 6) == 0) { LndkRunRun = 0; done = 1; } if (strncmp("/LOAD", (char *)&(ethbuf[dat_p + 4]), 5) == 0) { if (strncmp("?P1=", (char *)&(ethbuf[dat_p + 9]), 4) == 0) { a1 = ethbuf[dat_p + 13]; if (a1 == '0') { LoadOnOff(0); } if (a1 == '1') { LoadOnOff(1); } } done = 1; } if (strncmp("/MODEECO", (char *)&(ethbuf[dat_p + 4]), 8) == 0) { if (strncmp("?P1=", (char *)&(ethbuf[dat_p + 12]), 4) == 0) { a1 = ethbuf[dat_p + 16]; if (a1 == '0') { modeEco = ECOSTOP; } if (a1 == '1') { modeEco = ECOSEARCH; } } dat_p = SendState(1); done = 1; } if (strncmp("/DUMP", (char *)&(ethbuf[dat_p+4]), 5) == 0) { dat_p = SendState(1); done = 1; t0State = t1State = millis(); } if (strncmp("/MESURES", (char *)&(ethbuf[dat_p+4]), 8) == 0) { dat_p = SendState(0); done = 1; t0State = t1State = millis(); } if (strncmp("/DELESTAGE", (char *)&(ethbuf[dat_p+4]), 10) == 0) { // Tester si parametre de duree DureeDelestage = 20000; if (strncmp("?P1=", (char *)&(ethbuf[dat_p + 14]), 4) == 0) { ij=18; t0State = 0; a1 = ethbuf[dat_p + ij++]; while (((a1 >= '0') && (a1 <= '9')) && (ij < 23)) { t0State *= 10; t0State += (a1 - 48); a1 = ethbuf[dat_p + ij++]; } if ((t0State >= 30) && (t0State <= 86400)) { DureeDelestage = t0State * 1000; } } // Envoi de la commande de coupure de l'utilisation LoadOnOff(0); State = PREDELESTAGE1; t0State = millis(); // Autres initialisations a effectuer, passer en mode ECO } if (strncmp("/TIME", (char *)&(ethbuf[dat_p+4]), 5) == 0) { dat_p = TimeCommand((char *) &(ethbuf[dat_p + 9]), 1); done = 1; } if (strncmp("/UPTIME", (char *)&(ethbuf[dat_p+4]), 7) == 0) { dat_p = TimeCommand((char *) &(ethbuf[dat_p + 9]), 0); done = 1; } if ((done == 0) && (State == 0)) { dat_p=es.ES_fill_tcp_data_p(ethbuf, 0, PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n

401 Unauthorized

")); done = 1; } } else { // Silence pas de paquet recu if (modeEco == ECORUNNING) { unsigned long deltaEco, relanceEco; // Silence de plus de 5% de l'intervalle entre chaque paquet deltaEco = max(10000L, (MoyennEco / 20L)); relanceEco = MoyennEco / 12L; // t0Eco : date envoi dernier paquet // t1Eco : date reveil interface if (((millis() - t0Eco) > deltaEco) && ((millis() - t1Eco) > relanceEco)) { // Si une reponse de faite depuis le dernier reveil de l'interface if ((t0Eco - t1Eco) > 0L) { t0State = millis(); es.ES_enc28j60PowerDown(); DureeDelestage = MoyennEco - (2 * deltaEco); State = DELESTAGE; } // Sinon reactiver le mode recherche else modeEco = ECOSEARCH; } } } break; // case MESURE : // t1State = millis(); // Pour une demande de mesure, on attend pendant 250ms la reponse // if ((t1State - t0State) > 150) { // dat_p = SendState(); // done = 1; // State = NORMAL; // } // break; case PREDELESTAGE1 : t1State = millis(); // Pour une demande de mesure, on attend pendant 250ms la reponse if ((t1State - t0State) > 100L) { dat_p = SendState(1); done = 1; State = PREDELESTAGE2; } break; case PREDELESTAGE2 : t1State = millis(); // Laisser le temps pour la reponse ethernet if ((t1State - t0State) > 300) { es.ES_enc28j60PowerDown(); if (modeEco == ECORUNNING) modeEco = ECOSEARCH; State = DELESTAGE; #ifdef SERIALDEBUG if (SerialDebug > 0) { Serial.println("Mode delestage"); } #endif } break; case DELESTAGE : // if ((millis() - waitUntil) >= interval) t1State = millis(); if ((t1State - t0State) >= DureeDelestage) { // Envoyer la commande de retablissement de la charge if (modeEco != ECORUNNING) LoadOnOff(1); // Faire une verification du LOAD ON avant de declarer le State a 0 ? es.ES_enc28j60PowerUp(); t1Eco = millis(); State = NORMAL; } break; } // End switch State // Toutes les 30 secondes, commande d'interrogation des valeurs du regulateur if ((unsigned long)(millis() - t0Mesure) > 30000L) { // Envoi de la commande d'interrogation des registres au regulateur Write_Preambule(); Serial.write(0x01); // Adresse Serial.write(0xA0); // Commande Serial.write(0x00); // Longueur de donnees Serial.write(0x6F); // Check sum Serial.write(0x52); // Check sum Serial.write(0x7F); serind = 0; t0Mesure = millis() / 30000L; t0Mesure *= 30000L; } // --------------------------------------------------------------- // Reponse HTTP a faire // --------------------------------------------------------------- if (done == 1) { // Memoriser la duree des intervalles des cinq derniers acces // Plusieurs requetes à se suivre ne comptent que pour une if ((millis() - t0Eco) > 5000L) { for (ij = 3; ij > 0; ij --) DiffEco[ij] = DiffEco[ij - 1]; DiffEco[0] = (millis() - t0Eco); } t0Eco = millis(); if (modeEco > ECOSTOP) { if ((DiffEco[0] != 0L) && (DiffEco[1] != 0L) && (DiffEco[2] != 0L) && (DiffEco[3] != 0L)) { unsigned long minEco, maxEco, deltaEco; MoyennEco = (DiffEco[0] + DiffEco[1] + DiffEco[2] + DiffEco[3]) / 4L; // Si intervalle moyen compris entre 2mn et 2H (Cacti : 5mn) if ((MoyennEco >= 120000L) && (MoyennEco <= 7200000L)) { deltaEco = MoyennEco / 20L; minEco = MoyennEco - deltaEco; maxEco = MoyennEco + deltaEco; // Si les ecarts sont stables, on active le mode ECO if ( (DiffEco[0] >= minEco) && (DiffEco[0] <= maxEco) && (DiffEco[1] >= minEco) && (DiffEco[1] <= maxEco) && (DiffEco[2] >= minEco) && (DiffEco[2] <= maxEco) && (DiffEco[3] >= minEco) && (DiffEco[3] <= maxEco)) { if (modeEco == ECOSEARCH) { modeEco = ECORUNNING; #ifdef SERIALDEBUG if (SerialDebug) { Serial.print("Mode ECO "); Serial.print(MoyennEco); Serial.println(" ms"); } #endif } } else EcoRunning2Search(); } else EcoRunning2Search(); } } es.ES_www_server_reply(ethbuf,dat_p); // send web page data for (ij = 0; ij < ETH_SIZE; ij ++) ethbuf[ij] = 0; done = 0; } // --------------------------------------------------------------- // Traitement du bouton BUT, mise en mode maintenance // --------------------------------------------------------------- ij = digitalRead(BUTTON); if (ij == LOW) { if (t1 == 0) { t1 = millis(); } else { t2 = millis(); } } else { // Tester si relachement du bouton if ((t1 > 0) && (t2 > 0)) { if (((t2 - t1) >= 750L) && ((t2 - t1) <= 2000L)) { FlagMaintenance = (FlagMaintenance == LOW) ? HIGH : LOW; digitalWrite(9, FlagMaintenance); if (FlagMaintenance == HIGH) { Serial.println("Maintenance"); State = MAINTENANCE; es.ES_enc28j60PowerDown(); // Avant sleep mode, 8mA de consommation } else { Serial.println("Wake up"); es.ES_enc28j60PowerUp(); State = NORMAL; } } } t1 = t2 = 0; } // --------------------------------------------------------------- // Traitement des caracteres recus sur le port serie // --------------------------------------------------------------- while (Serial.available() > 0) { // get the new byte: char *ptr; ptr = (char *) &serbuf; ptr = ptr + serind; if (Serial.readBytes(ptr, 1) == 1) { serind++; } if ((serind == 36) && (serbuf[35] == 0x7F)) Mesures_Tracer(); if (serind >= SER_SIZE) serind = 0; } } } /* -------- End of Lndk_Tracer.ino ------ That's All, Folks -------- */