TIA Json Pasen in VBS TIA

emilio20

Level-2
Beiträge
836
Reaktionspunkte
20
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo ich bin grade dabei eine Json Pasen für einen Runtime PC in VBS zu erstellen. hierzu habe ich ein Beispiel im Netz gefunden das auf meinen PC Funktioniert.
Jetzt stehe ich aber vor dem Problem das Ganze in TIA zu integrieren.
Die einzelnen Funktionen habe ich angelegt.

Decode
Encodr
ParseArray
ParseObject
ParseString
ScanOnce
SkipWhitespace


Hir ist der gesamte Code
http://demon.tw/my-work/vbs-json.html

Da ich ja in Tia keine Class anlegen kann muss ich ja die globalen Variablen als Interne Variablen anlegen. Genau hier stoße ich auf das Problem
Wie könnte ich dies in in Tia anlegen?





Code:
   Class VbsJson
        
        Private Whitespace, NumberRegex, StringChunk
        Private b, f, r, n, t

        Private Sub Class_Initialize
            Whitespace = " " & vbTab & vbCr & vbLf
            b = ChrW(8)
            f = vbFormFeed
            r = vbCr
            n = vbLf
            t = vbTab

            Set NumberRegex = New RegExp
            NumberRegex.Pattern = "(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?"
            NumberRegex.Global = False
            NumberRegex.MultiLine = True
            NumberRegex.IgnoreCase = True

            Set StringChunk = New RegExp
            StringChunk.Pattern = "([\s\S]*?)([""\\\x00-\x1f])"
            StringChunk.Global = False
            StringChunk.MultiLine = True
            StringChunk.IgnoreCase = True
        End Sub
 

Anhänge

  • Json Pasen2.JPG
    Json Pasen2.JPG
    61,4 KB · Aufrufe: 28
  • Json Pasen1.JPG
    Json Pasen1.JPG
    108,2 KB · Aufrufe: 34
Zuletzt bearbeitet:
Tja ... und der eigentliche Sin von Json ist aber das Laden bzw. Speichern von Klassen-Objekten deren Struktur variiert oder unbekannt ist.
Warum willst du dies im Zusammenhang mit TIA einsetzen (was ja, wie du schon erkannst hast ,so nicht geht) ?
Es gibt doch für das generelle Laden und Abpeichern von Daten in der FAQ eine schöne Anleitung. Ob du die Daten nun in eine CSV-Datei schreibst oder in etwas, dessen Aufbau du dir selbst erdacht hast, ist dabei doch vollkommen unrelevant ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Larry,
ich möchte von einer json qwelle werte lesen. Ich habe den result schon mal vereinfacht mit Split zerlegt. Jedoch muss man hierzu genau wissen wo im Array der wert liegt. Bei der josn variante kann ich geziehlt nach Objekten suchen.
Wenn es nichts machbares gibt muss ich wohl wieder auf die Split variante zurückgreifen.
 
Du solltest ganz generell nicht VB.Net mit VB-Script verwechseln.
Das sind 2 völlig verschiedene Welten, die sich nur Teile der Sprachsyntax teilen ...

Aber meines Wissens lassen sind JSon-Dateien eigentlich ganz gut wie "normale" ASCII-Dateien behandeln.
Wie sieht denn der Aufbau einer deiner Dateien inhaltlich aus ?
 
Es geht um das Philips Hue json.

Wenn ich z.b alle Gruppen auslesen möchte um zu erfahren wie die Gruppe heist und welche Lampen der Gruppe angehören ist das die Antwort
Code:
{
    "1": {
        "name": "Wohnzimmer",
        "lights": [
            "10",
            "8",
            "2"
        ],
        "type": "Room",
        "state": {
            "all_on": false,
            "any_on": false
        },
        "class": "Living room",
        "action": {
            "on": false,
            "bri": 254,
            "hue": 0,
            "sat": 254,
            "effect": "none",
            "xy": [
                0.704,
                0.296
            ],
            "ct": 153,
            "alert": "none",
            "colormode": "hs"
        }
    },
    "2": {
        "name": "Küche",
        "lights": [
            "4",
            "5"
        ],
        "type": "Room",
        "state": {
            "all_on": false,
            "any_on": true
        },
        "class": "Living room",
        "action": {
            "on": false,
            "bri": 203,
            "hue": 48960,
            "sat": 254,
            "effect": "none",
            "xy": [
                0.2979,
                0.0905
            ],
            "ct": 172,
            "alert": "none",
            "colormode": "hs"
        }
    },
    "3": {
        "name": "Bad EG",
        "lights": [
            "6",
            "7"
        ],
        "type": "Room",
        "state": {
            "all_on": true,
            "any_on": true
        },
        "class": "Living room",
        "action": {
            "on": true,
            "bri": 254,
            "hue": 5077,
            "sat": 254,
            "effect": "none",
            "xy": [
                0.6528,
                0.3426
            ],
            "alert": "none",
            "colormode": "xy"
        }
    },
    "4": {
        "name": "Esszimmer",
        "lights": [
            "1"
        ],
        "type": "Room",
        "state": {
            "all_on": false,
            "any_on": false
        },
        "class": "Living room",
        "action": {
            "on": false,
            "bri": 252,
            "hue": 5984,
            "sat": 254,
            "effect": "none",
            "xy": [
                0.6399,
                0.3542
            ],
            "alert": "none",
            "colormode": "hs"
        }
    }
}

ich kann aber auch die anfrage auf jede Gruppe herunterbrechen

Code:
{
    "name": "Wohnzimmer",
    "lights": [
        "10",
        "8",
        "2"
    ],
    "type": "Room",
    "state": {
        "all_on": false,
        "any_on": false
    },
    "class": "Living room",
    "action": {
        "on": false,
        "bri": 254,
        "hue": 0,
        "sat": 254,
        "effect": "none",
        "xy": [
            0.704,
            0.296
        ],
        "ct": 153,
        "alert": "none",
        "colormode": "hs"
    }
}

dann gibt es die anfrage der lampen was ich ja schon mit der split Methode angewendet habe

Code:
{
    "state": {
        "on": false,
        "bri": 252,
        "hue": 5984,
        "sat": 254,
        "effect": "none",
        "xy": [
            0.6399,
            0.3542
        ],
        "alert": "none",
        "colormode": "hs",
        "reachable": true
    },
    "type": "Color light",
    "name": "LivingColors 1 Esszimmer",
    "modelid": "LLC011",
    "manufacturername": "Philips",
    "uniqueid": "00:17:88:01:00:c0:8a:e8-0b",
    "swversion": "5.23.1.13452"
}

dann gibt es noch scenen aber das würde denke ich zu weit gehen.
 
Zuletzt bearbeitet:
Hallo
ich stelle mal das Projekt hier Online. Ich komme nicht weiter. Vielleicht gibt es ja einen VBS Profi interesse hat das Problem zu lösen.
In der Datei zip Datei befindet sich eine json String in einer TEXT Datei.
 

Anhänge

Wenn du nicht einen universellen Parser benötigst, würde ich mich darauf konzentrieren möglichst einfach dein Problem zu lösen.
D.h. welche Werte benötigst du aus dem json-Datensatz, und dann eine Funktion schreiben welche genau diese Werte daraus extrahiert. Der Aufbau der json Datei sollte sich dann nicht mehr ändern.

Wenn du über die spezifische Anfrage die Antwort schon so weit herunterbrechen kannst, dann kommst du evtl. auch ohne "echten" Parser aus.
Bei deiner Anfrage nur auf eine einzelne Gruppe ist "name" beispielsweise eindeutig. Dann würde ich erstmal alle Leerzeichen, Tabs, Zeilenumbrüche aus der Antwort entfernen (außer die zwischen Anführungszeichen). Dann sollte es möglich sein, nach

"name":

zu suchen, also mit dem Doppelpunkt. Denn nur damit wird "name" ausschließlich als Variablenname, und nicht als womöglicher Wert erkannt. Dann nimmst du die Position des Zeichen danach, und weist der Variablen wenn von Typ String, alle Zeichen die sich danach zwischen zwei Anführungszeichen befinden zu. Oder du hängst an dem Suchstring das erste Anführungszeichen des Wertes mit an.
Bei Integer oder Gleitkommawerten würde ich eine Regex darauf ansetzen, oder schneidest den String zwischen ":" und "," aus, und versuchst es mit den Vb Konvertierungsfunktionen.
 
Mal auf die Schnelle was zusammengeschrieben, hat aber keine Fehlerbehandlung. Motto "Ärmel hochkrempeln und loslegen":
Code:
Dim fso, content
Dim json, varname, wert

filename = "F:\Programmierung\vbs\vbs\Json Pasen\json.txt"

Set fso = CreateObject( "Scripting.FileSystemObject" )
content = fso.OpenTextFile(filename).ReadAll

json = EatWhitespace(content)

varname = "name"
wert = GetStringValue(varname, json)
Wscript.echo varname & ": " & wert

varname = "hue"
wert = GetIntegerValue(varname, json)
Wscript.echo varname & ": " & wert

Function GetIntegerValue(key, json)
    Dim pos, search, result, intres
    result = ""
    search = Chr(34) & key & Chr(34) & ":"
    pos = InStr(json, search)
    If pos > 0 Then
        pos = pos + Len(search)
        For i = pos to Len(json)
            c = Mid(json, i, 1)
            If c >= "0" And c <= "9" Then
                result = result & c
            Else
                Exit For
            End If
        Next
    End If
    intres = CInt(result)
    GetIntegerValue = intres
End Function

Function GetStringValue(key, json)
    Dim pos, search, result
    result = ""
    search = Chr(34) & key & Chr(34) & ":" & Chr(34)
    pos = InStr(json, search)
    If pos > 0 Then
        pos = pos + Len(search)
        For i = pos to Len(json)
            c = Mid(json, i, 1)
            If c <> Chr(34) Then
                result = result & c
            Else
                Exit For
            End If
        Next
    End If
    GetStringValue = result
End Function

Function EatWhitespace(text)
    Dim out, i, c, inquote
    out = ""
    For i = 1 To Len(text)
        c = Mid(text, i, 1)
        If c = Chr(34) then
           If inquote = 0 Then
                inquote = 1
            Else
                inquote = 0
            End If
        End If
        If inquote = 0 Then
            If c <> " " And c <> vbCr And c <> vbLf And c <> vbTab Then
                out = out & c
            End If
        Else
            out = out & c
        End If
    Next
    EatWhitespace = out
End Function

Wie gesagt, funktioniert nicht universell für alle json Dateien, sondern nur für deine angehängte Datei. Bzw. alle bei denen der Variablenname nur einmal vorkommt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
ich habe den Parser sowei das TIA nicht mehr abstürzt.
Allerdings habe ich noch ein Problem. Im Skript ParseObject wird mir in Zeile 30 der Fehler " zu wenig Parameter angezeigt

Code:
Function ParseObject(ByRef str, ByRef idx)
 Dim c, key, value
            Set ParseObject = CreateObject("Scripting.Dictionary")
            idx = SkipWhitespace(str, idx)
            c = Mid(str, idx, 1)
            
            If c = "}" Then
                Exit Function
            ElseIf c <> """" Then
                'Err.Raise 8732,,"Expecting property name"
            End If

            idx = idx + 1
            
            Do 
                key = ParseString(str, idx)
                SmartTags("key")=key
                
                idx = SkipWhitespace(str, idx)
                If Mid(str, idx, 1) <> ":" Then
                    'Err.Raise 8732,,"Expecting : delimiter"
                End If

                idx = SkipWhitespace(str, idx + 1)
                If Mid(str, idx, 1) = "{" Then
                    Set value = ScanOnce(str, idx)
                Else
                    value = ScanOnce(str, idx)
                End If
                ParseObject.Add key, value
                
                
                idx = SkipWhitespace(str, idx)
                c = Mid(str, idx, 1)
                If c = "}" Then
                    Exit Do
                ElseIf c <> "," Then
                    'Err.Raise 8732,,"Expecting , delimiter"
                End If

                idx = SkipWhitespace(str, idx + 1)
                c = Mid(str, idx, 1)
                If c <> """" Then
                    'Err.Raise 8732,,"Expecting property name"
                End If

                idx = idx + 1
            Loop
            SmartTags("idx")=idx
            idx = idx + 1

End Function

Weiß jemand wie ich das Problem lösen kann ?
 

Anhänge

  • Json Pasen3.JPG
    Json Pasen3.JPG
    52,7 KB · Aufrufe: 22
Hast du mal probiert was er dir anzeigst wenn du als Parameter zwei Stringkonstanten einfügst?
Also
ParseObject.Add "testkey", "testwert"

Bei WinCCflex Vbs nimmt er das zumindest grundsätzlich.
 
Hallo Thomas,
da zeig er das selbe an .
Wenn ich eine neue funktion erstelle ohne Parameter erhalte ich keinen Fehler
 

Anhänge

  • Json Pasen4.JPG
    Json Pasen4.JPG
    55 KB · Aufrufe: 16
  • Json Pasen5.JPG
    Json Pasen5.JPG
    57,1 KB · Aufrufe: 13
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich bin kein VBS-Experte ob das mit der Rückgabe eines Objekts überhaupt so funktioniert wie du das vorhast.

Probier mal das Objekt als lokale Variable anzulegen, und dann am Ende der Funktion (mit Set) zuzuweisen. Beim Funktionsaufruf ebenfalls mit Set.
 
Zuletzt bearbeitet:
Hallo thomas,
wenn ich das skript in Windows als vbs datei ausführe funktioniert es ohne Probleme
Code:
   Class VbsJson
        'Author: Demon
        'Date: 2012/5/3
        'Website: http://demon.tw
        Private Whitespace, NumberRegex, StringChunk
        Private b, f, r, n, t

        Private Sub Class_Initialize
            Whitespace = " " & vbTab & vbCr & vbLf
            b = ChrW(8)
            f = vbFormFeed
            r = vbCr
            n = vbLf
            t = vbTab

            Set NumberRegex = New RegExp
            NumberRegex.Pattern = "(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?"
            NumberRegex.Global = False
            NumberRegex.MultiLine = True
            NumberRegex.IgnoreCase = True

            Set StringChunk = New RegExp
            StringChunk.Pattern = "([\s\S]*?)([""\\\x00-\x1f])"
            StringChunk.Global = False
            StringChunk.MultiLine = True
            StringChunk.IgnoreCase = True
        End Sub
        
        'Return a JSON string representation of a VBScript data structure
        'Supports the following objects and types
        '+-------------------+---------------+
        '| VBScript          | JSON          |
        '+===================+===============+
        '| Dictionary        | object        |
        '+-------------------+---------------+
        '| Array             | array         |
        '+-------------------+---------------+
        '| String            | string        |
        '+-------------------+---------------+
        '| Number            | number        |
        '+-------------------+---------------+
        '| True              | true          |
        '+-------------------+---------------+
        '| False             | false         |
        '+-------------------+---------------+
        '| Null              | null          |
        '+-------------------+---------------+
        Public Function Encode(ByRef obj)
            Dim buf, i, c, g
            Set buf = CreateObject("Scripting.Dictionary")
            Select Case VarType(obj)
                Case vbNull
                    buf.Add buf.Count, "null"
                Case vbBoolean
                    If obj Then
                        buf.Add buf.Count, "true"
                    Else
                        buf.Add buf.Count, "false"
                    End If
                Case vbInteger, vbLong, vbSingle, vbDouble
                    buf.Add buf.Count, obj
                Case vbString
                    buf.Add buf.Count, """"
                    For i = 1 To Len(obj)
                        c = Mid(obj, i, 1)
                        Select Case c
                            Case """" buf.Add buf.Count, "\"""
                            Case "\"  buf.Add buf.Count, "\\"
                            Case "/"  buf.Add buf.Count, "/"
                            Case b    buf.Add buf.Count, "\b"
                            Case f    buf.Add buf.Count, "\f"
                            Case r    buf.Add buf.Count, "\r"
                            Case n    buf.Add buf.Count, "\n"
                            Case t    buf.Add buf.Count, "\t"
                            Case Else
                                If AscW(c) >= 0 And AscW(c) <= 31 Then
                                    c = Right("0" & Hex(AscW(c)), 2)
                                    buf.Add buf.Count, "\u00" & c
                                Else
                                    buf.Add buf.Count, c
                                End If
                        End Select
                    Next
                    buf.Add buf.Count, """"
                Case vbArray + vbVariant
                    g = True
                    buf.Add buf.Count, "["
                    For Each i In obj
                        If g Then g = False Else buf.Add buf.Count, ","
                        buf.Add buf.Count, Encode(i)
                    Next
                    buf.Add buf.Count, "]"
                Case vbObject
                    If TypeName(obj) = "Dictionary" Then
                        g = True
                        buf.Add buf.Count, "{"
                        For Each i In obj
                            If g Then g = False Else buf.Add buf.Count, ","
                            buf.Add buf.Count, """" & i & """" & ":" & Encode(obj(i))
                        Next
                        buf.Add buf.Count, "}"
                    Else
                        Err.Raise 8732,,"None dictionary object"
                    End If
                Case Else
                    buf.Add buf.Count, """" & CStr(obj) & """"
            End Select
            Encode = Join(buf.Items, "")
        End Function

        'Return the VBScript representation of ``str(``
        'Performs the following translations in decoding
        '+---------------+-------------------+
        '| JSON          | VBScript          |
        '+===============+===================+
        '| object        | Dictionary        |
        '+---------------+-------------------+
        '| array         | Array             |
        '+---------------+-------------------+
        '| string        | String            |
        '+---------------+-------------------+
        '| number        | Double            |
        '+---------------+-------------------+
        '| true          | True              |
        '+---------------+-------------------+
        '| false         | False             |
        '+---------------+-------------------+
        '| null          | Null              |
        '+---------------+-------------------+
        Public Function Decode(ByRef str)
            Dim idx
            idx = SkipWhitespace(str, 1)

            If Mid(str, idx, 1) = "{" Then
                Set Decode = ScanOnce(str, 1)
            Else
                Decode = ScanOnce(str, 1)
            End If
        End Function
        
        Private Function ScanOnce(ByRef str, ByRef idx)
            Dim c, ms

            idx = SkipWhitespace(str, idx)
            c = Mid(str, idx, 1)

            If c = "{" Then
                idx = idx + 1
                Set ScanOnce = ParseObject(str, idx)
                Exit Function
            ElseIf c = "[" Then
                idx = idx + 1
                ScanOnce = ParseArray(str, idx)
                Exit Function
            ElseIf c = """" Then
                idx = idx + 1
                ScanOnce = ParseString(str, idx)
                Exit Function
            ElseIf c = "n" And StrComp("null", Mid(str, idx, 4)) = 0 Then
                idx = idx + 4
                ScanOnce = Null
                Exit Function
            ElseIf c = "t" And StrComp("true", Mid(str, idx, 4)) = 0 Then
                idx = idx + 4
                ScanOnce = True
                Exit Function
            ElseIf c = "f" And StrComp("false", Mid(str, idx, 5)) = 0 Then
                idx = idx + 5
                ScanOnce = False
                Exit Function
            End If
            
            Set ms = NumberRegex.Execute(Mid(str, idx))
            If ms.Count = 1 Then
                idx = idx + ms(0).Length
                ScanOnce = CDbl(ms(0))
                Exit Function
            End If
            
            Err.Raise 8732,,"No JSON object could be ScanOnced"
        End Function

        Private Function ParseObject(ByRef str, ByRef idx)
            Dim c, key, value
            Set ParseObject = CreateObject("Scripting.Dictionary")
            idx = SkipWhitespace(str, idx)
            c = Mid(str, idx, 1)
            
            If c = "}" Then
                Exit Function
            ElseIf c <> """" Then
                Err.Raise 8732,,"Expecting property name"
            End If

            idx = idx + 1
            
            Do
                key = ParseString(str, idx)

                idx = SkipWhitespace(str, idx)
                If Mid(str, idx, 1) <> ":" Then
                    Err.Raise 8732,,"Expecting : delimiter"
                End If

                idx = SkipWhitespace(str, idx + 1)
                If Mid(str, idx, 1) = "{" Then
                    Set value = ScanOnce(str, idx)
                Else
                    value = ScanOnce(str, idx)
                End If
                ParseObject.Add key, value

                idx = SkipWhitespace(str, idx)
                c = Mid(str, idx, 1)
                If c = "}" Then
                    Exit Do
                ElseIf c <> "," Then
                    Err.Raise 8732,,"Expecting , delimiter"
                End If

                idx = SkipWhitespace(str, idx + 1)
                c = Mid(str, idx, 1)
                If c <> """" Then
                    Err.Raise 8732,,"Expecting property name"
                End If

                idx = idx + 1
            Loop

            idx = idx + 1
        End Function
        
        Private Function ParseArray(ByRef str, ByRef idx)
            Dim c, values, value
            Set values = CreateObject("Scripting.Dictionary")
            idx = SkipWhitespace(str, idx)
            c = Mid(str, idx, 1)

            If c = "]" Then
                ParseArray = values.Items
                Exit Function
            End If

            Do
                idx = SkipWhitespace(str, idx)
                If Mid(str, idx, 1) = "{" Then
                    Set value = ScanOnce(str, idx)
                Else
                    value = ScanOnce(str, idx)
                End If
                values.Add values.Count, value

                idx = SkipWhitespace(str, idx)
                c = Mid(str, idx, 1)
                If c = "]" Then
                    Exit Do
                ElseIf c <> "," Then
                    Err.Raise 8732,,"Expecting , delimiter"
                End If

                idx = idx + 1
            Loop

            idx = idx + 1
            ParseArray = values.Items
        End Function
        
        Private Function ParseString(ByRef str, ByRef idx)
            Dim chunks, content, terminator, ms, esc, char
            Set chunks = CreateObject("Scripting.Dictionary")

            Do
                Set ms = StringChunk.Execute(Mid(str, idx))
                If ms.Count = 0 Then
                    Err.Raise 8732,,"Unterminated string starting"
                End If
                
                content = ms(0).Submatches(0)
                terminator = ms(0).Submatches(1)
                If Len(content) > 0 Then
                    chunks.Add chunks.Count, content
                End If
                
                idx = idx + ms(0).Length
                
                If terminator = """" Then
                    Exit Do
                ElseIf terminator <> "\" Then
                    Err.Raise 8732,,"Invalid control character"
                End If
                
                esc = Mid(str, idx, 1)

                If esc <> "u" Then
                    Select Case esc
                        Case """" char = """"
                        Case "\"  char = "\"
                        Case "/"  char = "/"
                        Case "b"  char = b
                        Case "f"  char = f
                        Case "n"  char = n
                        Case "r"  char = r
                        Case "t"  char = t
                        Case Else Err.Raise 8732,,"Invalid escape"
                    End Select
                    idx = idx + 1
                Else
                    char = ChrW("&H" & Mid(str, idx + 1, 4))
                    idx = idx + 5
                End If

                chunks.Add chunks.Count, char
            Loop

            ParseString = Join(chunks.Items, "")
        End Function

        Private Function SkipWhitespace(ByRef str, ByVal idx)
            Do While idx <= Len(str) And _
                InStr(Whitespace, Mid(str, idx, 1)) > 0
                idx = idx + 1
            Loop
            SkipWhitespace = idx
        End Function

    End Class








Dim field_K, field_D
Dim i
Dim f 
Dim IP, Username
Dim MyURL , postData 
Dim winHttpReq 
Dim fso, json, str, o
Dim hue1, hue2, hue3, hue4, hue5
Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")

On Error Resume Next

'Parameter IP, Username
IP="192.168.178.48"'SmartTags("PHILIPS HUE_IP")
Username="1234567890"'SmartTags("PHILIPS HUE_username")





MyURL = "http://"&IP&"/api/"&Username&"/lights/1"


winHttpReq.Open "GET", MyURL, False
winHttpReq.Send 

str = winHttpReq.ResponseText




    Set json = New VbsJson
    Set fso = WScript.CreateObject("Scripting.Filesystemobject")
    'str = fso.OpenTextFile("HUE.txt").ReadAll
    Set o = json.Decode(str)
    WScript.Echo o("state")("bri")
    WScript.Echo o("state")("hue")
    WScript.Echo o("state")("sat")
    WScript.Echo o("name")
    For Each i In o("state")("xy")
        WScript.Echo i
    Next
 
Zurück
Oben