Probleme mit Prowl - Problemlösung

Abend,

ich experimentiere zurzeit mit Prowl herum. Soweit funktioniert es ganz gut. Auf einem Webserver liegt ein PHP-Script und das wird abgerufen und dadurch bekomme ich ein Push-Nachricht an mein iPhone bzw an die App. Und das ganze rufe ich mit dem EthernetClient und einem EthernetShield ab.

Hier mal der Code:

#include <SPI.h>
#include <Ethernet.h>

#define switchPin 7  

byte mac[] = {  0xXX, 0xXX, 0xXX, 0x0D, 0xXX, 0xEA };
byte ip[] = { 192,168,2,109 }; 
byte server[] = { 192,168,2,107 }; 

EthernetClient client;

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  delay(1000);
  pinMode(switchPin, INPUT);
}

void loop()
{
  if (digitalRead(switchPin) == HIGH)
  {
      Serial.println("Tür offen"); //Ausgabe nur für debugging
    if (client.connect(server, 80)) { 
      Serial.println("verbunden");
      // Make a HTTP request:
      client.println("GET /offen.php"); //PHP-Script für die Offen Push-Nachricht
      client.println();
    } 
    else {
      Serial.println("verbindung fehlgeschlagen");
    }
    delay(100);
    Serial.print("Antwort des Servers: ");
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  if (!client.connected()) {        // Wenn server verbindung schließt client beenden
      Serial.println("trennen von server");
      client.stop();
    }
    while (digitalRead(switchPin) == HIGH)
    {
      // Hier stoppen wenn tür offen bleibt
    }
    //Serial.println("tür geschlossen");
    delay(200);  //<-- liegt es an diesen delays ?
    
    // ZWEITE if Funktion wenn Tür zu ist zum Abrufen des geschlossen Scripts
    
    if (digitalRead(switchPin) == LOW)
  {
      Serial.println("tür geschlossen");
    if (client.connect(server, 80)) { 
      Serial.println("verbunden");
      
      client.println("GET /zu.php"); 
      client.println();
    } 
    else {
      Serial.println("verbindung fehlgeschlagen");
    }
    delay(100);
    Serial.print("antwort des servers: ");
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  if (!client.connected()) {
      Serial.println("trennen vom server");
      client.stop();
    }
    while (digitalRead(switchPin) == LOW)
    {   
    }
    //Serial.println("Tür geöffnet");
    delay(200);   
  }
  }
}

Wie schon im Code kommentiert habe ich eine zweite if Funktion eingebaut nur mit den LOW Werten das er mir das geschlossen Script abruft. Ich habe zwei if funktionen genommen wegen der while Funktion das er das Script nicht tausendmal aufruft während der Zustand des Schalter also 1 oder 0 noch andauert.

So jetzt das Problem. Es ist sehr sporadisch wie der die Scripts ausruft. Einmal ruft er nur das geöffnet Script ab und manchmal nur das geschlossen Script. Manchmal macht er auch das wie es sein soll. Also wenn die Tür geöffnet wird also Schalter auf HIGH, einmal das geöffnet Script abrufen und sobald die Tür geschlossen wird also Schalter auf LOW, einmal das geschlossen Script abrufen.

Ich vermute es liegt an den Delays nach den if Funktionen. Ich habe mich leider noch nicht so mit millis eingefunden und kapiere nicht wirklich.

Ich hoffe ihr könnt mir helfen oder Verbesserungsvorschläge bringen.

Danke im Vorraus,
Gruß maddig

maddig:
Ich hoffe ihr könnt mir helfen oder Verbesserungsvorschläge bringen.

Ich hoffe, Du kannst erklären, was Du EIGENTLICH machen möchtest.

Wahrscheinlich nicht das, was Du programmiert hast.

Könnte es zum Beispiel sein, dass am Webserver nur bei ÄNDERUNG des Pegels von switchPin eine Seite abgerufen werden soll?

In dem Fall müßtest Du das auch programmieren, also den switchPin nicht auf HIGH oder LOW abfragen und darauf reagieren, sondern Du müßtest auf die StatusÄNDERUNG von LOW-nach-HIGH bzw. HIGH-nach-LOW reagieren und dann die Seite beim Server aufrufen, wenn die Änderung stattgefunden hat.

Dein Programm verwendet als pinMode für den Schalter INPUT, d.h. der Schalter funktioniert nur dann korrekt, wenn Du ihn mit einem PullDown-Widerstand korrekt beschaltet hast. Hast Du?

Danke für die Antwort. Ok sorry wollte es eigentlich so rüberbringen... Ja der Schalter sitzt als Endschalter an einer Tür. Ist die Tür in den Angeln schaltet der Schalter durch und ich bekomme ein HIGH. Ist die Tür offen bekomme ich ein LOW. Als Pull Down ist ein 10K Widerstand auf Ground eingebaut.

Und die Funktionsweise soll genauso sein wie du sie beschrieben hast:

Bekomme ich ein HIGH also Tür offen soll einmal das Script abgerufen werden. Wird die Tür wieder geschlossen als ein LOW soll das zweite Script auch einmal aufgerufen werden.

maddig:
Danke für die Antwort. Ok sorry wollte es eigentlich so rüberbringen... Ja der Schalter sitzt als Endschalter an einer Tür. Ist die Tür in den Angeln schaltet der Schalter durch und ich bekomme ein HIGH. Ist die Tür offen bekomme ich ein LOW. Als Pull Down ist ein 10K Widerstand auf Ground eingebaut.

Und die Funktionsweise soll genauso sein wie du sie beschrieben hast:

Bekomme ich ein HIGH also Tür offen soll einmal das Script abgerufen werden. Wird die Tür wieder geschlossen als ein LOW soll das zweite Script auch einmal aufgerufen werden.

OK, ich habe mal versucht, an Deinem Sketch was zu ändern, so dass auf ÄNDERUNGEN des Türstatus reagiert wird und nur auf Änderungen, und dann eine Seite vom Server abgerufen wird.

Ungetesteter Code:

#include <SPI.h>
#include <Ethernet.h>

#define switchPin 7  

byte mac[] = {  0x01, 0x02, 0x03, 0x0D, 0x05, 0xEA };
byte ip[] = { 192,168,2,109 }; 
byte server[] = { 192,168,2,107 }; 

EthernetClient client;

enum {UNCHANGED, OPENED, CLOSED };
  
boolean buttonPressed()
{
  boolean result=false;
  static byte lastButtonState;
  byte buttonState = digitalRead(switchPin);
  if (buttonState == HIGH && lastButtonState == LOW) result=OPENED;
  else if (buttonState == LOW && lastButtonState == HIGH) result=CLOSED;
  else result=UNCHANGED;
  lastButtonState=buttonState;
  return result;
}

void getPage(int state)
{
  if (client.connect(server, 80)) 
  { 
    Serial.println("verbunden");
    // Make a HTTP request:
    if (state == OPENED)
    {
      Serial.println("Tür offen"); //Ausgabe nur für debugging
      client.println("GET /offen.php HTTP 1.0"); //PHP-Script für die Offen Push-Nachricht
    }
    else if (state == CLOSED)
    {
      Serial.println("tür geschlossen");
      client.println("GET /zu.php HTTP 1.0"); 
    }
    else
    {
       Serial.println("invalid state in getPage()");
       client.println("GET /error404.htm HTTP 1.0"); 
    }
    client.println();
    delay(200);
    Serial.print("Antwort des Servers: ");
    while (client.available()) 
    {
      char c = client.read();
      Serial.print(c);
    }
    Serial.println("trennen von server");
    client.stop();
    delay(1);
  }
  else 
  {
    Serial.println("verbindung fehlgeschlagen");
  }
}

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  delay(1000);
  pinMode(switchPin, INPUT);
}

void loop()
{
  int action=buttonPressed();
  if (action!=UNCHANGED) getPage(action);
}

Edit/Nachtrag: Code geändert, teilweise getestet.

wow ! Vielen vielen Dank. Funktioniert perfekt! Ich muss mich zwar noch ein bisschen eindenken aber es so in der Art zu programmieren, wäre ich nie drauf gekommen...

Danke für deine Hilfe !

Aber eine Frage habe ich noch. Ich bekomm manchmal die Zwei Meldung einfach ohne die Tür zu öffnen im Abstand von circa 5 Sekunden. Kann es sein dass das Signal des Schalters prellt ? Und wenn ja soll ich es per Kondensator und noch nen Widerstand unterdrücken oder gehts einfacher mit programmieren ?

Die Prowl Sache hört sich interessant an. Kannst du auch mal das php Skript posten?

maddig:
Aber eine Frage habe ich noch. Ich bekomm manchmal die Zwei Meldung einfach ohne die Tür zu öffnen im Abstand von circa 5 Sekunden. Kann es sein dass das Signal des Schalters prellt ?

Ein Schalter "prellt" höchstens eine Millisekunde, und das ist bei Deinem Sketch irrelevant, weil nach dem Schalten erstmal eine Webserverseite aufgerufen wird, was mindestens 200 ms dauert. Dann ist jedes Prellen vorbei.

Was Du wahrscheinlich hast, wenn Du Phantomschaltungen feststellst, sind EMV-Störungen:

Lange Leitungen mit Kleinspannung drauf, ungeschirmte Leitungen.
Jede "lange Leitung" ist so etwas wie eine "Antenne", die Störungen auffängt.
Und wenn Du z.B. Schaltvorgänge auf 230 Volt Leitungen durchführst, kann das Signal auf einer 5 Volt Leitung in der Nähe leicht ans Schwabbeln kommen und den Pegel wechseln.

Abhilfe wäre z.B. möglich durch:

  • kürzere Leitungen
  • optimierte Leitungsführung
  • Signalumsetzung auf störungsfreiere Pegel (z.B. Differenzspannungspegel)
  • geschirmte Leitungen (z.B. Cat5 Netzwerkkabel statt Telefonkabel)
  • Tiefpassfilterung des Signals bei der Auswertung in der Software

Kommt ja ganz drauf an, was Du Dir da für Störungen über die Leitung einfängst.

Ok danke für die Hilfe ich werde alles ausprobiern, denn das mit den Leitungen stimmt... Ich werde mal ein CAT 5/6 Kabel ausprobieren.

maddig:
Aber eine Frage habe ich noch. Ich bekomm manchmal die Zwei Meldung einfach ohne die Tür zu öffnen im Abstand von circa 5 Sekunden. Kann es sein dass das Signal des Schalters prellt ? Und wenn ja soll ich es per Kondensator und noch nen Widerstand unterdrücken oder gehts einfacher mit programmieren ?

Ich leg alle PHP Files die du benötigst in den Anhang. Die wären jetzt für den Sketch. Du brauchst die App und nen Account auf prowlapp.com um die eine API zu erstellen und die in das PHP Script einzufügen. Somit verbindest du dein Handy mit dem Script. Und das TXT natürlich noch in ein PHP umschreiben...

offen.txt (1.22 KB)

zu.txt (1.22 KB)

ProwlConnector.class.txt (10.1 KB)

ProwlMessage.class.txt (8.11 KB)

ProwlResponse.class.txt (6.33 KB)

maddig:
Ok danke für die Hilfe ich werde alles ausprobiern, denn das mit den Leitungen stimmt... Ich werde mal ein CAT 5/6 Kabel ausprobieren.

Wobei Du auch gestörte Signale auswerten kannst, wenn die Störungen kurz sind und die Auswertung langsam sein kann. Stichwort "Tiefpassfilterung".

Im einfachsten Fall machst Du zum Beispiel folgendes: Du liest den Zustand eines Buttons 100 mal aus mit je einer Millisekunde Zeit dazwischen, und addierst die Ergebnisse aufeinander: Und wenn mehr als 50 dabei herauskommt, wertest Du den Pegel als HIGH und ansonsten als LOW.

Damit kannst Du "Knackser" auf der Leitung, zum Beispiel induktiv eingestreute Störungen auf Deinem Signalkabel beim Betätigen des Lichtschalters oder beim Schalten des Staubsaugers normalerweise bereits ausfiltern.

Also ich habe noch ein kleines Problem, vielleicht kannst du mir da noch weiterhelfen
Ich habe:

  1. Prowl gekauft
  2. registriert
  3. API key generiert
  4. Firefox extension installiert, api key eingegeben. Push läuft
  5. Email auf api email gesendet. kommt in der app an

und nun:

  1. alle deine 5 dateien ins hauptverzeichnis einer domain gelegt. Auf dem Server läuft PHP Version 5.4.34-0+deb7u1
  2. txt in php umbenannt
  3. den api key ausgetauscht
  4. link in browser aufgerufen www.domain.com/offen.php
  5. in der app kommt nix an

Hast du ein Tipp oder was habe ich verkehrt gemacht?

Hab meinen Fehler gefunden, aber noch nicht beseitigt bekommen.

Auf einem Raspberry läuft es. Auf einem Vserver und auf einem dedicated Server nicht. Warum nicht, hab ich noch nicht rausbekommen, da sind meine Linux Kenntnisse zu bescheiden.

Aus irgeneinem Grund werden die Scripte nicht ausgeführt. haben aber die gleichen Rechte(664), Besitzer und Gruppen wie die anderen php im gleichen Verzeichnis. grrrr

Hab das mit dem Server zwar immer noch nicht am laufen, aber hab etwas an dem php Proggy rumgestrickt.

So dass man 2 Parameter übergeben kann,

z.B.:
http://www.domain.com/api.php?Betreff=Betrifft&Inhalt=Das ist grosse klasse, Leertaste, Komma, umlaute äüö gehen

Mit Leerstellen und Umlauten.

Man kann die Zeile im Browser ausprobieren, wenn mann den deaktivierten print-Befehl aktiviert, bekommt man Rückmeldung.

@maddig: Somit brauchst du nur noch eine Datei, um die verschiedensten Meldungen aufs Iphone zu bringen. Prowl war ne gute Idee von dir. Gefällt mir.

<?php
/*
        Snail Mail Push Alerts
        
        Server side PHP script for sending iPhone push alerts when this example.php
        is requested via HTTP by the Arduino.
        
        Adapted from ProwlPHP 0.3.1 by Mario Mueller: https://github.com/xenji/ProwlPHP
*/

require_once 'ProwlConnector.class.php';
require_once 'ProwlMessage.class.php';
require_once 'ProwlResponse.class.php';

$oProwl = new ProwlConnector();
$oMsg   = new ProwlMessage();

$Betreff = $_GET['Betreff'];
$Inhalt = $_GET['Inhalt'];

try 
{
/*
print "<html><meta http-equiv='Content-Type' content='text/html; charset=utf8' />
<body><h1>Nachricht abgeschickt</h1>
<p>Betreff: " . $Betreff . "</p>
<p>Inhalt: " . $Inhalt . "</p>
</body></html>";
*/
        $oProwl->setIsPostRequest(true);
        $oMsg->setPriority(0);
        $oMsg->addApiKey('89xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx31'); // Change to your API key from http://prowl.weks.net/ 
        $oMsg->setEvent($Inhalt);
        $oMsg->setApplication($Betreff);
        $oResponse = $oProwl->push($oMsg);
        if ($oResponse->isError())
                print $oResponse->getErrorAsString();
        else
        {
                print "Sent. " . $oResponse->getRemaining() . " Messages left. (Resets at: " . date('Y-m-d H:i:s', $oResponse->getResetDate()) . ")" . PHP_EOL;
        }
}
catch (InvalidArgumentException $oIAE)
{
        print $oIAE->getMessage();
}
catch (OutOfRangeException $oOORE)
{
        print $oIAE->getMessage();
}

?>

Hab den Fehler gefunden.

Auf dem Server wo das php aufgerufen wird, muss Curl installiert sein, sonst geht es nicht!