German Http Request zu SPS - xml-String

Vansdan

Member
Licensed User
Longtime User
Soweit, so gut...

Hallo Jens,

habe deinen Code um ein Sub ergänzt, Request und Response funktionieren jetzt soweit.

Mein bisheriger Code:

B4X:
'Activity module
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    
    Dim HC As HttpClient
    Dim PARSER As SaxParser

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim TxtList As List
    Dim SPSDataTypes As Map
End Sub


Sub Activity_Create(FirstTime As Boolean)
   
   Activity.LoadLayout("layout1")
    If FirstTime Then
        HC.Initialize("HC")
        
    End If
   PARSER.Initialize 
   'Laden von layout1
   

End Sub

Sub Activity_Resume
Dim Query As String 
Dim PDD_CSV As String

TxtList.Initialize
SPSDataTypes.Initialize 

' ** Initialisiere Vars
Load_Defaults

PDD_CSV = XMLString

Query = "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & _
"<body><version>1.0</version><client>IMasterPhoenix5_14_05" & _
"</client><client_ver>5.14.0501</client_ver><item_list_size>" & PDD_CSV
Send2SPS(Query,1)

End Sub


Sub Load_Defaults

'SPSDataTypes = File.ReadMap (File.DirDefaultExternal,"pdd.csv")
SPSDataTypes = File.ReadMap (File.DirAssets,"pdd.csv")


' Format eg. ONBOARD_INPUT:WORD

'**Manuelles Laden der MAP
'SPSDataTypes.Put("ONBOARD_INPUT","WORD")


End Sub
Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub HC_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int )
    Log("Error: " & Reason & ", StatusCode: " & StatusCode)
    If Response <> Null Then
        Log(Response.GetString("UTF8"))
        Response.Release
    End If



End Sub

Sub Send2SPS(Query As String, TaskId As Int)
    Dim Req As HttpRequest
    ProgressDialogShow("connecting...")

    Req.InitializePost2("http://192.168.3.150/cgi-bin/ILRReadValues.exe", Query.GetBytes("UTF8"))
    HC.Execute(Req,TaskId)

    ProgressDialogHide
End Sub

Sub HC_ResponseSuccess (Response As HttpResponse, TaskId As Int)
    Dim Res As String
    Dim In As InputStream

   Res = Response.GetString("UTF8")
    Log("Response from server: " & Res)
   'Msgbox(Res,"Result")
    Select TaskId
    Case 1
'        Msgbox(Res,"Result") ' fail = -1
'    Response.GetAsynchronously("XMLResponse", File.OpenOutput(File.DirInternalCache, "Rss.txt", False), True, TaskId)
    Response.GetAsynchronously("XMLResponse", File.OpenOutput(File.DirDefaultExternal , "sps.xml", False), True, TaskId)
   'Response.GetAsynchronously("XMLResponse", File.OpenOutput(File.DirInternalCache , "sps.xml", False), True, TaskId)


'Response von der SPS:

'<?xml version="1.0"encoding="UTF-8"?>
'<body>
'<version>1.0</version>
'<client>IMasterPhoenix5_14_05</client><client_ver>5.14.0501</client_ver>
'<item_list_size>11</item_list_size>
'   <item_list>
      '<i><n>@GV.Input_Analog</n><v>914</v></i>
      '<i><n>@GV.Output_Analog</n><v>1992</v></i>
      '<i><n>@GV.TestOutputs</n><v>0</v></i>
      '<i><n>@GV.PLCMODE_ON</n><v>0</v></i>
      '<i><n>@GV.ONBOARD_INPUT_BIT1</n><v>0</v></i>
      '<i><n>@GV.Test_BOOL</n><v>0</v></i>
      '<i><n>Main.Q_Bool</n><v>0</v></i>
      '<i><n>Main.V001</n><v>0</v></i>
      '<i><n>Main.Test1</n><v>0</v></i>
      '<i><n>Main.V005</n><v>0.000000</v></i>
      '<i><n>Main.V004</n><v></v></i>
   '</item_list>
'</body>


    End Select    

End Sub
Sub XMLResponse_StreamFinish (Success As Boolean, TaskId As Int)
    Dim In As InputStream
    
    If Success = False Then
        Msgbox(LastException.Message, "Error")
        Return
    End If

'   parse the xml file
    In = File.OpenInput(File.DirDefaultExternal, "sps.xml")
   'In = File.OpenInput(File.DirInternalCache, "sps.xml")
    PARSER.Parse(In, "Parser")
    In.Close

End Sub 
Sub Parser_StartElement (Uri As String, Name As String, Attributes As Attributes)

End Sub

Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)

'*** Hole die Anzahl der Werte 
    If PARSER.Parents.IndexOf("body") > -1 Then
        If Name = "item_list_size" Then
            TxtList.add(Text.ToString)
        End If
    End If

'    If PARSER.Parents.IndexOf("item_list") > -1 Then
'        If Name = "b" Then
'        TxtList.add(Text.ToString)
'        End If
'    End If

' *** Abschnitt item_list
' *** wenn das �bergeordnete Element item_list ist
If PARSER.Parents.IndexOf("item_list") > -1 Then

    
' *** wenn das �bergeordnete Element n ist
    If PARSER.Parents.IndexOf("n") > -1 Then

' *** wenn das aktuelle Element b ist
       ' If Name = "b" Then
        '    TxtList.add(Text.ToString)
        'End If
    End If
    
' *** wenn das �bergeordnete Element v ist
    If PARSER.Parents.IndexOf("v") > -1 Then

' *** wenn das aktuelle Element i ist
        If Name = "i" Then
            TxtList.add(Text.ToString)
      End If
End If
    
End If

End Sub


Sub XMLString As String
   
   Dim su As StringUtils
   Dim i, j, ColCount, RowCount, AnzV As Int
   Dim Table, CSV As List
   Dim XMLString As String
   Dim sb As StringBuilder
   Dim sbXML2 As StringBuilder
   
    Table = su.LoadCSV(File.DirAssets, "pdd.csv", ",")
   
   'pdd.csv:
   'Name,Data Type
   '@GV.Input_Analog,WORD
   '@GV.Output_Analog,WORD
   '@GV.TestOutputs,BOOL
   '@GV.PLCMODE_ON,BOOL
   '@GV.ONBOARD_INPUT_BIT1,BOOL
   '@GV.Test_BOOL,BOOL
   'Main.Q_Bool,BOOL
   'Main.V001,BOOL
   'Main.Test1,BOOL
   'Main.V005,REAL
   'Main.V004,String(80)
      
    RowCount=Table.Size
   AnzV = RowCount-1 
    ColCount=2
    Dim MyArray(RowCount, ColCount), aRow() As String
    For i=0 To RowCount-1
        aRow=Table.Get(i)
        For j=0 To ColCount-1
            MyArray(i, j)=aRow(j)
         Next
         'Log(MyArray(i, 0))
    Next
       
   sb.Initialize
   For i = 1 To RowCount-1
    sb.Append("<i><n>").Append(MyArray(i, 0)).Append("</n></i>")
   Next
      
   sbXML2.Initialize
   sbXML2.Append(AnzV).Append("</item_list_size><item_list>").Append(sb).Append("</item_list></body>")
   
   Return sbXML2

End Sub

Allerdings klappt das mit dem Parsen irgendwie noch nicht bzw. kann ich mir die Ergebnisse nicht anzeigen lassen. Habe ich hier irgendwo einen Fehler oder dergleichen. Kann auch gerne mal die zip-Datei anhängen.

Noch kurz eine andere Frage. Um immer aktuelle Werte zu erhalten, wäre es sinnvoll, den Request jede Sekunde abzusenden. Sind hier Probleme bezüglich der Performance zu erwarten, da die Daten ja immer erst gespeichert und wieder geöffent werden. Oder habe ich das falsch verstanden?

Schöne Grüße
Daniel
 

Attachments

  • ILC.zip
    8.5 KB · Views: 268

Tron

Member
Licensed User
Longtime User
...weiter gehts

Hallo Daniel.
Das Problem mit dem Parsen ergibt sich aus den Unterschieden des vorigen Posts und dem jetzigen XML. Das Aktuelle hat den <b> Tag nicht mehr !
Ich habe den Parserabschnitt angepasst.

..kann ich mir die Ergebnisse nicht anzeigen lassen
Breakpoints setzen und im debug-Modus mit dem Mauszeiger über die Variablen halten, oder LOG - Befehle einbauen.

Um immer aktuelle Werte zu erhalten, wäre es sinnvoll, den Request jede Sekunde abzusenden. Sind hier Probleme bezüglich der Performance zu erwarten
Bei einer Update-rate von 1s sind auch ohne abspeichern, zwar weniger Performance-verluste (hängt vom Device ab), aber dafür schnell leere Akkus zu erwarten.
Der Parser erwartet als Eingabequelle einen Datenstrom, der aus einer URL kommen kann, oder einer Datei.

Im späteren Verlauf des Projekts würde ich dazu raten, die HTTP Routine und den Parser zu einem Service Modul zu "konvertieren" , dann läuft die Kommunkation im Hintergrund und das "Hauptprogramm" kümmert sich um Eingabe und Anzeige !
(schon mal vorsorglich den Abschnitt Service Module "inhalieren" !)

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   
   Dim HC As HttpClient
   Dim PARSER As SaxParser

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim TxtList As List
   Dim SPSDataTypes As Map
End Sub

Sub Activity_Create(FirstTime As Boolean)

   If FirstTime Then
      HC.Initialize("HC")
      PARSER.Initialize 
   End If

End Sub

Sub Activity_Resume
Dim Query As String 

TxtList.Initialize
SPSDataTypes.Initialize 

' ** Initialisiere Vars
Load_Defaults

Query = "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & _
"<i><n>@GV.PLCMODE_ON</n></i><i><n>@GV.ONBOARD_INPUT_BIT1</n></i>"
Send2SPS(Query,1)


End Sub
Sub Load_Defaults

SPSDataTypes = File.ReadMap (File.DirDefaultExternal,"SPS_Vars.csv")
' Format eg. ONBOARD_INPUT:WORD

'**Manuelles Laden der MAP
'SPSDataTypes.Put("ONBOARD_INPUT","WORD")


End Sub
Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub HC_ResponseError (Response As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int )
   Log("Error: " & Reason & ", StatusCode: " & StatusCode)
   If Response <> Null Then
      Log(Response.GetString("UTF8"))
      Response.Release
   End If

End Sub
Sub Send2SPS(Query As String, TaskId As Int)
   Dim Req As HttpRequest
   ProgressDialogShow("connecting...")

   Req.InitializePost2("http://192.168.216.22/spstest/track.xml", Query.GetBytes("UTF8"))
   HC.Execute(Req,TaskId)

   ProgressDialogHide
End Sub

Sub HC_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   Dim Res As String
   Dim In As InputStream

'   Res = Response.GetString("UTF8")
   Log("Response from server: " & Res)

   Select TaskId
   Case 1
'      Msgbox(Res,"Result") ' fail = -1
'   Response.GetAsynchronously("XMLResponse", File.OpenOutput(File.DirInternalCache, "Rss.txt", False), True, TaskId)
   Response.GetAsynchronously("XMLResponse", File.OpenOutput(File.DirDefaultExternal , "sps.xml", False), True, TaskId)

   End Select   
   
   

End Sub
Sub XMLResponse_StreamFinish (Success As Boolean, TaskId As Int)
   Dim In As InputStream
   
   If Success = False Then
        Msgbox(LastException.Message, "Error")
        Return
    End If

'   parse the xml file
   In = File.OpenInput(File.DirDefaultExternal, "sps.xml")
   PARSER.Parse(In, "Parser")
   In.Close

' TEST TEST TEST TEST TEST TEST TEST TEST 
   File.WriteList(File.DirDefaultExternal, "result.txt", TxtList)
   

End Sub 
Sub Parser_StartElement (Uri As String, Name As String, Attributes As Attributes)

End Sub

Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)

'*** Hole die Anzahl der Ergebnisse
   If PARSER.Parents.IndexOf("body") > -1 Then
      If Name = "item_list_size" Then
         TxtList.add(Text.ToString)
      End If
   End If

'   If PARSER.Parents.IndexOf("item_list") > -1 Then
'      If Name = "b" Then
'      TxtList.add(Text.ToString)
'      End If
'   End If

' *** Abschnitt item_list
' *** wenn das übergeordnete Element item_list ist
If PARSER.Parents.IndexOf("item_list") > -1 Then

   
' *** wenn das übergeordnete Element i ist
   If PARSER.Parents.IndexOf("i") > -1 Then

' *** wenn das aktuelle Element n ist
      If Name = "n" Then
         TxtList.add(Text.ToString)
      End If
   
' *** wenn das aktuelle Element v ist
      If Name = "v" Then
         TxtList.add(Text.ToString)
      End If
   
   End If
   
End If
   
End Sub

arbeitest Du eigentlich im Moment mit Tablet oder Smartphone ?

gruß Jens
 
Last edited:

Vansdan

Member
Licensed User
Longtime User
Fragen über Fragen...

Hallo Jens,

als Ausgabegerät möchte ich mein Asus EEpad TF101 Transformer verwenden. Diesem kann man ja noch eine Tastatur hinzufügen, die dann als Ladestation fungieren würde. Somit wäre der Akku jetzt nicht so das Problem. Man schaut ja nicht die ganze Zeit nach, wie hoch die Temperatur oder dergleichen in jedem Raum ist...

Das Aktuelle hat den <b> Tag nicht mehr !
Ich habe den Parserabschnitt angepasst.

Vielen Dank, weiß jetzt auch nicht genau, wo das b herkam. Evtl. vom Versuch, den Wert dick (bold) dazustellen.

Kurz noch eine Bitte an dich. Wäre es möglich, dass du mir dein bisheriges Versuchsprogramm nicht nur als Code, sondern auch als zip-Paket bereitstellen könntest. Irgendwie habe ich jetzt bei den ganzen Versionen alles durcheinander gebracht.
Deshalb habe ich auch das Problem, dass ich die Werte nach dem Parsen nicht angezeigt bekomme. Weder als Log noch als Messagebox, keine Ahnung, wieso.


Danke und schönen Abend noch.

Daniel
 

Tron

Member
Licensed User
Longtime User
So..implementiert

So.. habe mein B4a erstmal auf v2 up-gegraded und wie gewünscht den Parserabschnitt überarbeitet.
Ps ich habe übrigens ein HTC Desire und ein Galaxy Tab 10.1N.
Ich hätte gern das hier,
xphone promo HD - YouTube
aber kommt mir irgendwie komisch vor :D
gruß Jens
 

Attachments

  • Vis_ILC.zip
    8.4 KB · Views: 249

Vansdan

Member
Licensed User
Longtime User
Dankeschön...

Hallo Jens,

entschuldige bitte die verspätete Antwort, hatte am WE wenig Zeit zum ausprobieren...

Parsen funktioniet jetzt, musste aber hier noch eine Leerzeile ergänzen:
B4X:
Query = "<?xml version=" & Chr(34) & "1.0" & Chr(34) & Chr(32) & "encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & _

Das Resultat schaut dann so aus:

attachment.php


Nun hätte ich noch eine andere Frage. Kann man die Ergebnisse nach dem Parsen statt in einer TxtListe auch in eine Map oder dergleichen speichern? Wäre gut, wenn man immer ein Wertepaar mit Variable und dazugehörigem Wert hätte...
Wie könnte man das dann im Designer anzeigen lassen? Habe schon verschiedene ListViews probiert, leider klappt das irgendwie noch nicht so, wie es soll...

Wie kann man eigentlich eine Map anzeigen lassen. Mit Log() kommt ja immer ungefähr sowas, das = wird scheinbar immer angehängt, oder?

B4X:
(MyMap) {@GV.PLCMODE_ON,BOOL=, Main.V004,STRING(80)=, Main.Q_Bool,BOOL=, Name,Data=Type, Main.V001,BOOL=, @GV.Input_Analog,WORD=, @GV.Test_BOOL,BOOL=, Main.Test1,BOOL=, Main.V005,REAL=, @GV.ONBOARD_INPUT_BIT1,BOOL=, @GV.TestOutputs,BOOL=, @GV.Output_Analog,WORD=}


Nochmals vielen Dank für deine umfangreiche Hilfe!

Schönen Abend
Daniel
 

Attachments

  • Result_TxtList_k.jpg
    Result_TxtList_k.jpg
    18.6 KB · Views: 321

Tron

Member
Licensed User
Longtime User
Es darf auch ge-map-t werden...

Hallo Daniel.
Nun hätte ich noch eine andere Frage. Kann man die Ergebnisse nach dem Parsen statt in einer TxtListe auch in eine Map oder dergleichen speichern? Wäre gut, wenn man immer ein Wertepaar mit Variable und dazugehörigem Wert hätte...

kein Problem:

B4X:
Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   
'   Dim TxtList As List
   Dim SPSDataTypes As Map

' **NEU
   Dim GvKey As String 
   Dim TxtMap   As Map
   
End Sub

B4X:
Sub Activity_Resume
Dim Query As String 

' *** NEU ***
'TxtList.Initialize
TxtMap.Initialize


SPSDataTypes.Initialize 

' ** Initialisiere Vars
Load_Defaults

Query = "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>" & _
"<i><n>@GV.PLCMODE_ON</n></i><i><n>@GV.ONBOARD_INPUT_BIT1</n></i>"
Send2SPS(Query,1)

End Sub

B4X:
Sub XMLResponse_StreamFinish (Success As Boolean, TaskId As Int)
   Dim In As InputStream
   
   If Success = False Then
        Msgbox(LastException.Message, "Error")
        Return
    End If

'   parse the xml file
   In = File.OpenInput(File.DirDefaultExternal, "sps.xml")
   PARSER.Parse(In, "Parser")
   In.Close

' TEST TEST TEST TEST TEST TEST TEST TEST 
'   File.WriteList(File.DirDefaultExternal, "result.txt", TxtList)
' *** NEU
   File.WriteMap (File.DirDefaultExternal, "result.txt", TxtMap)

End Sub

B4X:
Sub Parser_EndElement (Uri As String, Name As String, Text As StringBuilder)

'*** Hole die Anzahl der Ergebnisse
   If PARSER.Parents.IndexOf("body") > -1 Then
      If Name = "item_list_size" Then
'*** NEU
'         TxtList.add(Text.ToString)
         TxtMap.Put(Name,Text.ToString)

      End If
   End If

' *** Abschnitt item_list
' *** wenn das übergeordnete Element item_list ist
If PARSER.Parents.IndexOf("item_list") > -1 Then

   
' *** wenn das übergeordnete Element i ist
   If PARSER.Parents.IndexOf("i") > -1 Then

' *** wenn das aktuelle Element n ist
      If Name = "n" Then
'***NEU
         GvKey = Text.ToString
'         TxtList.add(Text.ToString)
      End If
   
' *** wenn das aktuelle Element v ist
      If Name = "v" Then

'***NEU
'         TxtList.add(Text.ToString)
         TxtMap.Put(GvKey,Text.ToString)
      End If
   
   End If
   
End If
   
End Sub

Ein Map-objekt hat übrigens seine eigene Art der Sortierung, also nicht erschrecken.

Wie kann man eigentlich eine Map anzeigen lassen. Mit Log() kommt ja immer ungefähr sowas, das = wird scheinbar immer angehängt, oder?

Während der "Testphase" speichern wir doch alles auf die SD-Karte :)
mit File.WriteMap (File.DirDefaultExternal, "result.txt", TxtMap)
Das kann man mit einem Texteditor öffnen (über den Explorer oder Astro).

Als nächstes würde ich vorschlagen diesen Abschnitt zu einem Service umzuwandeln.
Dann kann man periodisch die SPS abfragen und grafisch darstellen.

gruß Jens
PS. Meine Literatur zur SPS ist ein 68 Seiten PDF namens ilc_150_gsm_gprs.pdf
Ist das die richtige SPS ?
 

Attachments

  • 000.png
    000.png
    20.3 KB · Views: 265
Last edited:

Vansdan

Member
Licensed User
Longtime User
Vielen Dank!

Hallo Jens,
mal wieder vielen Dank für deine Hilfe. Habe jetzt das Projekt mal mit der neuen HttpUtils2 umgesetzt, funktioniert soweit.
Deine Vorlagen für die Maps habe ich auch umgesetzt und hab diese in ein Listview geschrieben. Funktioniert auch, nur jeder Request verlängert die Liste anstatt eine neue anzulegen. Hier muss ich nochmal nachlesen...

Hab dir das Programm mal angehängt, vielleicht könntest du es dir mal anschauen und mir ein paar Hinweise/Verbesserungsvorschläge machen. Bin mir immer noch etwas unschlüssig, was wann wo und wie aufgerufen werden muss :)

PS. Meine Literatur zur SPS ist ein 68 Seiten PDF namens ilc_150_gsm_gprs.pdf
Ist das die richtige SPS ?

Ist im Grunde die gleiche SPS, meine heißt ILC 150 ETH, die von dir erwähnte hat noch ein zusätzliches GSM Modul, die Funktion ist aber gleich...

Schönen Abend noch.
Daniel
 

Attachments

  • Visu_ILC_20120717.zip
    17.5 KB · Views: 269
Last edited:

Vansdan

Member
Licensed User
Longtime User
Vielen Dank!

Hallo Jens,

wollte mich nochmals bei dir für die Hilfe bedanken, bis jetzt klappt alles soweit...
Hast du dir meinen Code nochmal angeschaut? Habe diesen mittlerweile noch etwas ergänzt.

Im späteren Verlauf des Projekts würde ich dazu raten, die HTTP Routine und den Parser zu einem Service Modul zu "konvertieren" , dann läuft die Kommunkation im Hintergrund und das "Hauptprogramm" kümmert sich um Eingabe und Anzeige !

Deinen Vorschlag würde ich gerne noch aufgreifen, die HTTP Routine läuft in der HttpUtils2 ja als Service, oder sehe ich das verkehrt? Den Parserteil müsste ich demnach noch umsetzen...

Vielleicht kannst du mir noch etwas auf die Sprünge helfen!

Danke und schöne Grüße
Daniel
 
Top