API leest waardes maar 1 keer bij Arduino startup

Ik heb een stukje code bij elkaar gehacked om de slimme meter uit te lezen via een P1 bus en de data door stuurt naar een Fibaro HC2 domotica controller.

Dit werkt vrij redelijk, maar de Fibaro lijkt alleen maar 1 maal een connectie te accepteren en daarna niet meer, de sketch loopt wel door overigens.
in de

Connectie maken met de Fibaro:

if (client.connect(Fibaro, 80)) {

client.print("PUT /api/globalVariables/Dag"); //Fibaro Global Variable
client.println(" HTTP/1.1");
client.println("Host: 192.168.0.110");
client.print("Authorization: ");
client.println("Basic ci52ZWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.print("Content-Length: ");
client.println(PostDataHT.length());
client.println();
client.println(PostDataHT);

Ik probeer de http connectie al af te sluiten in void loop met

if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;:wink:
;

Maar bij de volgende run van de loop accepteert de Fibaro zo te zien geen data meer, want er komt niks meer binnen.

Hoe los ik dit op?
Als er meer info nodig is, laat het mij a.u.b. weten.

Je moet ook connecten in de loop. Na elke transactie wordt je weer gedisconnect. Anders kun nooit zoveel clients bedienen bij grote installaties als bijv de banken of de belasting dienst

Nico, ik connect ook in de loop.
Ik heb 2 functions gemaakt die ik aanroep van uit de void loop:

decodeTelegram();

httpRequest();

Hopelijk leg ik het goed uit.

Ik vermoed dat het zal helpen als je je volledige programma toont. En gebruik code tags
type
** **[code]** **

plak je programma daarachter
type
** **[/code]** **
daarachter

Ok, hier is de code:

#include <Ethernet.h>
#include <SPI.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x2E, 0x33 };
byte ip[] = {192, 168, 0, 101};
byte gateway[] = {192, 168, 0, 254};
byte subnet[]  = {255, 255, 255, 0};
IPAddress Fibaro (192, 168, 0, 110);
EthernetClient client;

char input; // inkomende seriële data (byte)
bool readnextLine = false;
#define BUFSIZE 75
char buffer[BUFSIZE]; //Buffer voor seriële data om \n te vinden.
int bufpos = 0;
long mEVLT = 0; //Meterstand Elektra - verbruik laag tarief (nacht)
long mEVHT = 0; //Meterstand Elektra - verbruik hoog tarief (Dag)
long mEAV = 0;  //Meterstand Elektra - actueel verbruik (Huidig)
long mTotaal = 0; //Meterstand Elektra - Totaal verbruik (Dag + Nacht)
long mG = 0;   //Meterstand Gas

long lastTime = 0;
long interval = 60000;

void setup() {
  Ethernet.begin(mac, ip);
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial1.begin(115200);
  delay(1000);
}

void loop() {
  
mTotaal = mEVLT + mEVHT;
  decodeTelegram();

  if (millis() - lastTime > interval) {
    lastTime = millis();
    
    httpRequest();
    //Reset variables to zero for next run
    //   mEVLT = 0;
    //   mEVHT = 0;
    //   mEAV = 0;
    //   mG = 0;
    //Stop Ethernet
    client.stop();
  }
} //Einde loop

void decodeTelegram() {
  long tl = 0;
  long tld = 0;
  if (Serial1.available()) {

    input = Serial1.read();

    char inChar = (char)input;
   
    // Vul buffer tot en met een nieuwe lijn (\n)
    buffer[bufpos] = input & 127;
    bufpos++;

    if (input == '\n') { // we hebben een lijn binnen (gegevens tot \n)
      


      // Nacht tarief
      if (sscanf(buffer, "1-0:1.8.1(%ld.%ld" , &tl, &tld) == 2)
      {
          mEVLT = (tl*1);
                
      }

      // Dag tarief
      if (sscanf(buffer, "1-0:1.8.2(%ld.%ld" , &tl, &tld)== 2)
      {
        mEVHT = (tl*1);
      }

      // Huidig verbruik
      if (sscanf(buffer, "1-0:1.7.0(%ld.%ld" , &tl , &tld) == 2)
      {
        mEAV = (tl /1000);
      }

      // Gas meter
      if (strncmp(buffer, "0-1:24.2.1", strlen("0-1:24.2.1")) == 0) {
        if (sscanf(strrchr(buffer, '(') + 1, "%d.%d", &tl, &tld) == 2) {
          mG = (tl*1);
        }
      }

      // Empty buffer again (whole array)
      for (int i = 0; i < 75; i++)
      {
        buffer[i] = 0;
      }
      bufpos = 0;
    }
  } //Einde 'if Serial1.available'
} //Einde 'decodeTelegram()' functie

void httpRequest() {
  
  String PostDataHT = "{\"value\":\"";
  PostDataHT += mEVHT;
  PostDataHT += "\"\}\r\n";

  String PostDataLT = "{\"value\":\"";
  PostDataLT += mEVLT;
  PostDataLT += "\"\}\r\n";
  
  String PostDataAV = "{\"value\":\"";
  PostDataAV += mEAV;
  PostDataAV += "\"\}\r\n";

  String PostDataTotaal = "{\"value\":\"";
  PostDataTotaal += mTotaal;
  PostDataTotaal += "\"\}\r\n";
  
  String PostDataG = "{\"value\":\"";
  PostDataG += mG;
  PostDataG += "\"\}\r\n";

  if (client.connect(Fibaro, 80)) {
    
    client.print("PUT /api/globalVariables/Dag"); //Fibaro Global Variable
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.0.110");
    client.print("Authorization: ");
   client.println("Basic ci52ZWx0aGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    client.print("Content-Length: ");
    client.println(PostDataHT.length());
    client.println();
    client.println(PostDataHT);

    client.print("PUT /api/globalVariables/Nacht"); //Fibaro Global Variable
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.0.110");
    client.print("Authorization: ");
    client.println("Basic ci52ZWx0aG9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    client.print("Content-Length: ");
    client.println(PostDataLT.length());
    client.println();
    client.println(PostDataLT);

    client.print("PUT /api/globalVariables/Huidig"); //Fibaro Global Variable
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.0.110");
    client.print("Authorization: ");
    client.println("Basic ci52ZWx0aGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    client.print("Content-Length: ");
    client.println(PostDataAV.length());
    client.println();
    client.println(PostDataAV);

    client.print("PUT /api/globalVariables/Totaal"); //Fibaro Global Variable
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.0.110");
    client.print("Authorization: ");
    client.println("Basic ci52ZWx0aG9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    client.print("Content-Length: ");
    client.println(PostDataTotaal.length());
    client.println();
    client.println(PostDataTotaal);

    client.print("PUT /api/globalVariables/Gas"); //Fibaro Global Variable
    client.println(" HTTP/1.1");
    client.println("Host: 192.168.0.110");
    client.print("Authorization: ");
    client.println("Basic ci52ZWx0aG9lbkB1cGxxxxxxxxxxxxxxxxxxxxxxxxx");
    client.print("Content-Length: ");
    client.println(PostDataG.length());
    client.println();
    client.println(PostDataG);
  }
  else {
    //Request complete; empty recieve buffer
    while (client.available()) { //data available
        char c = client.read(); //gets byte from ethernet buffer
    }

    delay(3000);
  }
}

Behalve dat de code niet loopt(loept) heb ik ook een probleem met de komma.

Hoe kan ik mEVLT afronden op de komma, ik ontvang 6217786, maar wil ontvangen 6217.786

Hoe zet ik die punt er tussen?

Als je loop niet itereert, dan moet je op zoek naar de oorzaak daarvan (dûh).
Ik heb je code even bekeken in de IDE, maar die code gaat me iets te ver voor mijn kennis.
Toch kan ik je wel iets meegeven.
Ten eerste zie ik dat je 2 seriële poorten reserveert, maar ik zie er verder niets met de eerste gebeuren.
Naast een display, is de seriële poort is een krachtig debug hulpmiddel.
Je kunt op strategische plaatsen in je code een serieel berichtje sturen, waardoor je weet dat de sketch die plaats in de code is gepasseerd.
In de loop die je nu hebt laten zien, gebeuren er maar een paar dingen.
Je roept 2 functies aan(decodeTelegram, en httpRequest), je update een teller/klok en er word een sommetje gemaakt.
Dus, stuur een serieel signaaltje dat je de functie gaat aanroepen, en stuur een signaaltje dat je teruggekeerd bent van die functie.
Ik heb het vermoeden dat je dan bemerken zult dat je niet terugkeert uit een van die functies.
Vervolgens kun je hetzelfde hulpmiddel binnen die functie die je dwars zit toepassen.

Als jij andere data ontvangt dan je wil ontvangen, dan heb je een probleem.
Maar ik vermoed dat dat niet precies is wat je bedoelde.
Ik denk dat je in plaats daarvan bedoelde dat je die data iets anders wil presenteren als die aan jou gepresenteerd wordt door de bron.

In je code zie ik ook iets staan over het scannen van de datastring die je via serial1 binnen kreeg.
Ik heb het donkerbruine vermoeden dat dat een array betreft.
Als je de inhoud daarvan overzet naar een ander type variabele, dan kun je er daarna gewoon mee rekenen.
Dus dan delen door duizend.
Als je array een array blijft, dan kun je kijken hoe groot de array is.
Maak de nieuwe array 1 positie groter.
Kopieer vervolgens de een na laatste naar de laatste, dan de twee na laatste naar de een na laatste en zo voorts.
Als je dat lang genoeg gedaan hebt, kun je op de juiste positie de inhoud vervangen door de punt die je daar wil hebben.
Das niet veel werk en je sketch heeft dat in een mum voor mekaar.
Deze laatste methode gebruik ik zelf om een ontbrekende punt in via een seriële vorm binnen komende data, toch op een lcd af te beelden met de juiste punt.
De betreffende data komt met 9600 Bd. binnen en de sketch heeft er geen enkel probleem mee om dat on the fly te doen (naast nog een aantal andere conversies).

Brrr, weer veel te laat.
Kan zijn dat het te laat is en je helemaal niet geholpen bent met mn verhaal hier boven, sorry dan in dat geval.
Nu maar gauw het bed opzoeken denk ik.

Tnx voor je antwoord.
Ik heb getest met tussendoor berichten naar de seriele monitor te sturen, maar dat gaat goed.
Het gaat mis bij de httpRequests, die runt maar 1 keer en dat is bij de opstart van de Arduino.

Wat de getallen betreft wil ik b.v. getal 1234567 presenteren als 1234.567
Het kan niet moeilijk zijn, alleen heb ik geen oplossing voor zo iets simpels.

Het gaat dus om de long mEVHT resultaten, het is dus een variabele,ik hoef het niet op de serial console te printen.

httpRequest word onder voorwaarden aangeroepen.
Als ie niet word aangeroepen, dan zal dat komen doordat er niet aan de voorwaarde word voldaan.

De voorwaarde is dat ie maar eens per 60000 millis mag worden aangeroepen, als ik de code correct lees.

Maar, weet je zeker dat wat je meldt, ook is wat er gebeurt ?
Dat kun je dus ook weer via de seriële poort als debug hulp controleren.
Kom je door de test of er alweer 60000 millis zijn verstreken, stuur dan een berichtje naar die poort.
Dan kun je dus zien dat de test een 1 opleverde, en dat httpRequest werd aangeroepen.

Als je terug komt na dat aanroepen, doe je :

   client.stop();

Wat doet dat ?

En wanneer word dat weer gestart dan ?

En als ie gestopt is, hoe zinvol is het aanroepen van httpRequest dan nog ?

De serial output laat zien dat de HTTP verzoeken maar 1 keer lopen.
Mijn idee is dat de Fibaro ze connectie netjes afgesloten wil zien alvorens nieuwe code er op af te vuren, vandaar dat ik getest heb met client.stop
De httprequest loopt dus wel, maar de Fibaro leest ze niet.

EthernetClient client;

en

 client.stop();

Volgens mij zet je daar de client stil, toch ?
Als jij een HTTP dinges gaat doen, heb je daar dan die client niet voor nodig misschien ?
En als je 'm hebt uitgeschakeld, moet je 'm wellicht eerst weer inschakelen.
En ook wellicht even wachten tot ie er is.

Geen idee hoor, ik weet het echt niet.
Maar als ik het contact van de auto uitzet, kan ik op het gaspedaal trappen wat ik wil.
De auto gaat dan echt niet rijden hoor.

10 minuten later:
Maar even opgezocht.
Je start de verbinding wanneer je test of die verbinding er is, dat doe je zo:

if (client.connect(Fibaro, 80)) {

Ik ben bang dat het daar toch fout gaat.
Wanneer je een if... doet, dan is het resultaat waar, of niet waar.
Waar is dan een 1, niet waar is dan een nul.
Dat kun je 'misbruiken' door een test uit te voeren zoals jij dat hier probeert.
Maar de if... werkt onder de huid net iets anders.
En ik denk dat je daar je nu last van hebt.

Want de if... controleert of het resultaat niet een nul is.
En als het resultaat niet een nul is, dan is het een 1.
En de clou:
Client.connect geeft nooit een nul als resultaat.

Returns

Returns an int (1,-1,-2,-3,-4) indicating connection status :

SUCCESS 1
TIMED_OUT -1
INVALID_SERVER -2
TRUNCATED -3
INVALID_RESPONSE -4

Dan is de uitkomst dus altijd niet een nul, en daarom dus waar.

Das dus uit de Arduino Reference (klik !)

Als dit de oorzaak van je probleem mocht zijn, dan is de oplossing door te controleren of het resultaat van client.connect een 1 is.
Want dat geeft dus een nul wanneer het -1, -2, -3 of -4 is.

Ow, en om te debuggen zou ik het nog iets anders aanpakken.
Dan maak je dus een variabele die het resultaat van client.connect meekrijgt.
En die stuur je weer via de seriële poort.
Dan kun je zien of de verbinding tot stand gekomen is of niet.
En een klein beetje waarom niet.

Ik probeer dit via:

if (client.available()) {
char c = client.read();
Serial.print(c);

Maar dit print een "H" naar de serial console.

Waarom loopt dit nou niet, als ik de sketch b.v. 2 x upload, dan werkt het 2 x perfect.

Ok,

Haal je daar niet 1 karakter binnen van een verbinding die inmiddels staat ?
En is dat dan toevallig de H van HTTP ?

Als je in plaats van dit:

  if (client.connect(Fibaro, 80)){

Het volgende doet:

 cc = (client.connect(Fibaro, 80))
  serial.print(cc);
  if cc == 1{

Dan zou je dus het resultaat van de client.connect te zien moeten krijgen.

Ben er uit.

Je moet voor elke connectie (of er na, moet ik nog testen) het http verkeer stoppen met:

client.stop();

Alvorens weer verbinding te maken.

if (client.connect(Fibaro, 80)) {

Opgelost, bedankt voor het meedenken MAS3.

Graag gedaan, dat zet mij ook aan het denken.

Alleen deed je dit volgens mij al, zij het op een iets minder logische wijze.
Volgens mij riep je de request aan die dan een verbinding ging opzetten, en wanneer de request terug keerde na het aanroepen, werd de verbinding verbroken.
Minder logisch is dan omdat je de verbinding opzet in de request functie, en 'm verbreekt in de loop functie.
Ik zou er dan eerder voor kiezen de verbinding ook in de request functie te beëindigen, oogt mij dan wat netter.