Nachfragen zur Nutzung von HTTP_GET und Nachbildung des PING Kommandos

Begonnen von stm, 17. November 2011, 22:53:08

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 1 Gast betrachten dieses Thema.

stm

Hallo,

ich habe ein Gerät, das ich per HTTP Kommando steuern kann. (URL mit Aufrufparametern steuert aktiviert Gerätefunktion)
Dieses soll in meine Steuerung eingebunden werden.

Am HTTP_GET Bespiel bin ich dran, und versuche abzustrippen (feste IP Adresse, einmaliger aufruf, evtl ein zweites mal abhängig Rückgabeparameter.

Meine Fragen:
1) Muss ich IP_Control aufrufen? (wenn ja, wie oft? In jedem Funktionsblock, in dem ich eine Netwerkfunktion wie HTTP_GET habe ß Einmal pro Steuerung? Jedes mal, bevor ich eine andere IP Adressse verwende?)

2) Ich möchte testen, ob das Gerät aktiv ist, also suche ich einen FB, der dem PING Kommando entspricht

3) Wo gebe ich Timeouts für den HTTP_GET an?

4) Was bedeutet die Eingangsvariable UNLOCK_BUF ? reicht es nicht aus, den Vorgang über GET zu starten? Dem Beispiel nach wird UNLOCK_BUF gesetz, damit DONE zurück gesetzt, was wiederum über die DNS Abfrage einen neuen HTTP_GET erzeugt ...

Gibts dzu evtl ein Timing Diagramm?

Viele Fragen...

Lieben Dank

peewit

hallo

1.
der ip_control sollte immer zyklisch aufgerufen werden

der http_get baustein hat IP_C , R_BUF, S_BUF als in/out parameter die immer mit einer IP_CONTROL instanz verbunden sein müssen. der http_get kann aber das sharing der ressource, das heisst du kannst eine ip_control instanz mit mehreren http_get instanzen verbinden, da der baustein beim aktivieren wartet bis der ip_control es ihm erlaubt, und andere bausteine sind dann blockiert. im prinzip ist es ein automatischen verriegeln der bausteine auf den netzwerkzugriff !
dieses prinzip habe ich erfunden, da die meisten bausteine nur relativ selten und dann auch nur kurz des netzwerk benutzen
und die anzahl der gleichzeitig möglichen verbindungen bei den meisten kleinsteuerungen auf 8 verbindungen limitiert ist.
somit kann man komplexere programme schreiben, ohne sich um die anzahl der gleichzeitigen verbindungen kümmern zu müssen, da die bausteine automatisch hintereinander darauf zugreifen, und somit nur einen socket binden.
weiters müsstest du für jede weitere ip_control instanz immer den speicher für S_BUF und R_BUF rechnen, das kann man sich mit dem sharing ersparen (also speicher und ressourcen schonende lösung)

2. mit der network.lib sind nur udp und tcp möglich, also auf basis von ip-adressen (schicht 3)
    ein ping befehl arbeitet aber eine schicht darunter also nur auf basis von MAC-Adressen
   aber ich bezweifle das du wirklich eine ping benötigst
   du brauchst ja nur eine http_get abfrage machen, und wenn das gerät nicht aktiv ist, bekommst du eine
   connect-fehlermeldung 0xFF000000

3. das timeout gibst du beim baustein IP_CONTROL an, somit wird dieser zeitwert für alle aktionen benutzt
    verbindung aufbauen, senden, empfangen.

4. wenn du den http_get startest, dann werden die http-daten in den empfangsbuffer abgelegt, und stehen zur auswertung zur verfügung (DONE = TRUE)
solange du nicht "UNLOCK_BUF = TRUE" machst, bleibt der ip_control baustein von dieser http_get instanz blockiert
und andere bausteine bekommen keinen zugang zum ip_control und müssen warten
somit kannst du selber bestimmen wie lange die daten im empfangsbuffer verfügbar sind
sobald du die daten verarbeitet hast, gibst du für einen zyklus UNLOCK_BUF = true , und der baustein gibt den zugriff auf den ip_control wieder frei, aber ab diesen zeitpunkt gibt es keine garantie mehr, das die daten im empfangbuffer noch aktuell sind.


stm

Danke für Deine schnelle Antwort! Das hilft mir weiter !

... wenn ich mir dann noch vorstelle, was in und hinter den Routinen steckt ...

Bin beeindruckt!

Doch noch zum Verständnis eine Frage: Das IP_CONTROL muss ich einmal im ganzen Programm an einer Stelle zyklisch aufrufen, oder einmal pro Funktionsblock?

Was anderes ist mir noch aufgefallen ist: Ich bekomme in den Empfanspuffer nicht die gesamte Antwort des Webservers.

Hintergrund: Ich will über HTTP einen Satellitenreceiver abschalten und per HTTP kann ich sowohl den Betriebszustand bekommen, als auch schalten. Wenn ich den Betriebszustand abfrage, kommt eine XML Struktur - im Browser komplett, beim HTTP_GET in der letzten der Zeilen abgeschnitten. (Kein Unterschied, welchen MODE Parameter ich gewählt habe.)

PS: Ich plane kommenden Di einen Besuch auf der SPS in Nürnberg, bist Du auch dort ? (Habe sowas dunkel in Erinnerung - würde mich freuen dem Genius mal die Hand zu schütteln...)


peewit

anders herum
ein baustein der das netzwerk nutzen möchte braucht eine ip_control instanz

-----------------

wenn du im empfangsbuffer nicht alles findest , was eigentlich da sein sollte, dann haben die empfangsdaten wahrscheinlich
mehr als 4000 bytes.

das ist die aktuell vorgegebene groesse des buffers

wenn du mit codesys bzw. twincat arbeitest, dann ist es relativ einfach anzupassen
unter globale konstanten der network.lib findest du die definition des network_buffer

aber solange ich keine details deiner hhtp_get abfrage kenne, kann ich auch keinen sinnvollen kommentar abgeben

------

gehe mal auf    "http://web-sniffer.net/"
und mache deine http_get abfrage, und stelle das ergebnis online, dann kann ich es mir ansehen !

---------------------------

auf der sps nürnberg bin ich selber nicht, aber "hugo" der gründer von oscat wird sicherlich dort anzutreffen sein !

stm

Da die Adresse bei mir im Netz ist musste ich mit Wireshark ran. (Angehängt Trace des HTTP Aufrufes im Firefox)
Eigenartigerweise "sieht" der Wireshark die Kommunikation des Beckhoff TCP-Servers nicht - bekomme keine Aufzeichnung :-(

Also sehe ich nur was HTTP_GET liefert:
Im HTTP_GET kommt zwischen Start und Ende Body nur
                  $R$N<?xml version="1.0" encoding="UTF-8"?>$N<e2powerstate>$N$T<e2instandby>false$N$T</e
an.

Wo kann ich weitersuchen?

[gelöscht durch Administrator]

stm

Jetzt habe ich den Wireshark-Trace hinbekommen:
- Erste Anfrage vom Browser, zweite vom PLC Programm.

[gelöscht durch Administrator]

peewit

hallo

in dem wireshark file hast du aber einiges weggelassen ?
wenn ich nicht alles sehe , kann ich es nur auch nur ungefähr bewerten

das dein gerät einfach einen verbindungsabbruch macht, ist halt auch nicht sehr intelligent !
richtig wäre eine antwort die http konform ist.

ich vermute das dein gerät nicht mit HTTP Version 1.0 sich zufrieden gibt


probiere mal eine 2 oder 3 bei parameter "MODE" am http_Get baustein


wenns nicht geht, dann mach wieder eine wireshark aufzeichnung, möglichst ungefiltert, damit ich alles sehen kann

stm

Vorhin war ein Filter zuviel drin - jetzt nur die Adresse

und die Dumps von Mode=0 Mode=2 und Mode=3

Sorry, jetzt fange ich langsam an Aufwand zu machen: Wollte ich nicht, für mich reicht die Funktion so, dachte nur, die Lib wird durch meinen Input besser/fehlerfreier.

[gelöscht durch Administrator]

peewit

hallo

also ich habe kein problem damit, das wir hier miteinander versuchen "dein" problem zu lösen

mit modus 2 und 3 bekommst du nun auch die daten geliefert
also war meine vermutung anscheinend richtig.

nun müsstest du doch ein "done" bekommen und bei body_start / stop die datenbereiche.
Die xml-daten sind aber "Chunked Transfer Coding" , also keine normalen xml-daten so wie in einer text-datei
sondern in viele kleine pakete unterteilt
(blöd zum auswerten , aber daran ist rein dein gerät schuld, weil es die daten eben so liefert!)
ein klassischer browser fügt die einzelnen teile gleich wieder zusammen, und gibt sie in normaler form weiter
der sps baustein http_get holt aber nur die rohdaten und stellt sie zur verfügung
die interpretation der daten ist deine aufgabe
wir haben hier eben nur eine sps, und keinen ausgewachsenen browser

siehe: http://www.html-world.de/program/http_9.php
abschnitt: Chunked Encoding


nun sollten doch die daten im buffer sein, und du musst sie auswerten !
wenn nicht, würden mich die online-zustände des http_get baustein intressieren


stm

So jetzt verwende ich den Mode 3.

Habe aber wohl noch ein größeres Problem: Ich möchte einen Baustein bauen, der mit Flankenwechsel aufgerufen wird. Und dann eine einzige Abfrage durchführt.

Wahrscheinlich habe ich noch nicht verstanden, wie das HTTP_GET funktioniert, da sich mein Code nicht verhält wie geplant.

Frisch geladen und gestartet:
Erster Durchlauf:
      Wireshark sieht den Paketverkehr wie oben angehängt
      HTTP_GET Aufruf, bringt OK 200, Body ist leer

Zweiter Durchlauf:
      Wireshark sieht keinen Paketverkehr
      HTTP_GET Aufruf, bringt OK 200, Body enthält
            $R$N1$R$N<$R$N25$R$N?xml version="1.0" encoding="UTF-8"?>$R$N1$R$N$N$R$Ne$R$N<e2powerstate>$R$N1$R$N$N
      jedenfalls bringt das ein BUFFER_TO_STRING()- allerdings sollten da 181 Zeichen drin sein (body_end - body_end)


Irgendwas habe ich da wohl ziemlich vermurkst....



[gelöscht durch Administrator]

peewit

erster durchlauf:

nach dem kein wireshark anhang zu finden ist, kann ich auch keinen kommentar dazu abgeben, was beim ersten mal
passiert

zweiter durchlauf:

das ist relativ einfach denn man kann keine 181 zeichen in einen normalen 80 zeichen langen ziel-string kopieren
body : STRING(STRING_LENGTH); solltest du nehmen, dann hast du einen oscat konformen string mit maximaler länge (250 zeichen)


mit deinen baustein bin ich auch nicht wirklich zufrieden
habe auch momentan keine zeit ihn auszuprobieren


aber ich würde ip_control und http_get immer ohne bedinung zyklisch aufrufen
am einfachsten am ende des bausteins
dann musst du auch nicht zweimal die riesigen http_get bauteinblock in den code packen
und in den jweiligen schritten änderst du immer nur die benötigten parameter um, bzw holst dir die ergebnisse


der http_get reagiert auf positive flanke von parameter get, und wenn du den baustein nicht immer zyklisch aufrufst
dann wird er so manche flanke verpassen
der buf_relase wird bei dir auch erst kurz vor dem zweiten durchlauf gesetzt.

--------------------
richtig ist, abfrage starten, dann auf done oder error warten
wenn done dann daten verarbeiten
dann buf_release = true
dann warten bis done = false
dann buf_release = false

und nun kannst mit einer positiven flanke bei get wieder eine neue abfrage starten
--------------------