German Steuerung von Philips Hue

Andie

Member
Licensed User
Longtime User
Mit der Philips-Hue-Api und Python kann man sehr leicht seine Lampen über den PC einschalten und den Status der Lampen (an oder aus, Helligkeit etc.) bestimmen.

Lampe1 einschalten (Python-Code):
B4X:
url = 'http://192.168.178.31/api/' + username + '/lights/1/state'
data = '{"on":true}'
requests.put(url, data=data)

Status der Lampen (Python-Code):
B4X:
url = 'http://192.168.178.31/api/' + username + '/lights'
r = requests.get(url)

Dabei ist username eine Stringvariable, die meine Hue-Benutzerkennung enthält und r nimmt einen Json-String auf, aus dem ich dann die gewünschten Status-Informationen extrahieren kann.

Leider weiß ich nicht, welche Lib (HTTP, OkHttpUtils, etc.) ich dafür benutzen muss und welche Methode. Ich habe bis jetzt immer nur mit der Download2-Methode des HttpJob-Objektes gearbeitet, was hier aber wohl nicht weiter führt.
 

DonManfred

Expert
Licensed User
Longtime User
okhttputils2, Download2 (get) sollte passen

Wenn du Lust hast meine Lib zu testen (in der Entwicklung) dann kann ich meine HUESDK Lib mal hochladen....

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 sdk As PHHueSDK
    Dim APselected As PHAccessPoint
    Dim BridgeSelected As PHBridge
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    sdk.Initialize("HUE","QuickStartApp")
    Log(sdk.InitManager)
    Log("Bridge selected="&sdk.SelectedBridge)
    Log("APs found: "&sdk.AccessPointsFound)
    Dim SPs As List = sdk.AccessPointsFound
    If SPs.Size > 0 Then
        Log("Get 1st AP")
        For i = 0 To SPs.Size-1
            Dim ap As PHAccessPoint = SPs.Get(i)
            Log($"AP initialized = ${ap.IsInitialized}"$)
            If ap.IsInitialized Then
                sdk.connect(ap)
            End If
           
        Next
    End If
   
    Dim bridges As List = sdk.AllBridges
    Log(bridges)
    If bridges.Size > 0 Then
        Log("Get 1st Bridge")
        For i = 0 To bridges.Size-1
            Dim bridge As PHBridge = bridges.Get(i)
            Log($"Bridge initialized = ${bridge.IsInitialized}"$)
        Next
    End If

    Dim ap As PHAccessPoint
    ap.Initialize("")
    ap.IpAddress = "192.168.1.116"
    ap.MacAddress = "00:17:88:12:CB:6E"
    ap.BridgeId = "001788FFFE12CB6E"
   
    'Log(ap.IpAddress)
    'Log(ap.MacAddress)
    'Log(ap.Username)
    If sdk.isAccessPointConnected(ap) Then
        Log("ap connected")
        Dim bridge As PHBridge = sdk.SelectedBridge
        Log("Groups: "&bridge.AllGroups)
        Log("Lights: "&bridge.AllLights)
        Log("Rules: "&bridge.AllRules)
        Log("Scenes: "&bridge.AllScenes)
        Log("Sensors: "&bridge.AllSensors)
        Log("AllShedules: "&bridge.getAllSchedules(True))
        Log("AllTimers: "&bridge.getAllTimers(True))
    Else
        LogColor("ap not connected",Colors.Blue)
        Log(sdk.DisconnectedAccessPoint)
        'sdk.search2(True,True,True)
        sdk.search(True,True)
    End If
   
    'Log(sdk.AllBridges)
    'Log(sdk.SelectedBridge)
   
    Log(sdk.AccessPointsFound)
End Sub
Sub HUE_onAccessPointsFound(APs As List)
    'Log($"HUE_onAccessPointsFound(${APs})"$)
    Log($"HUE_onAccessPointsFound()"$)
    If APs.IsInitialized Then
        Log($"AP list is initialized. size = ${APs.Size}"$)
        'Log(APs)
        If APs.Size = 1 Then
            Log("get 1st")
            If APs.Get(0) Is PHAccessPoint Then
                Log("get PHAccessPoint")
                Dim ap As PHAccessPoint = APs.Get(0)
                Log(ap.BridgeId)
                Log(ap.IpAddress)
                Log(ap.MacAddress)
                'Log(ap.Username)
                APselected = ap
                sdk.connect(ap)   
            else if APs.Get(0) Is PHBridge Then
                Log("get PHBridge")
                Dim bridge As PHBridge = APs.Get(0)
                sdk.addBridge(bridge)
            else if APs.Get(0) Is PHBridgeHeader Then
                Log("get PHBridgeHeader")
                Dim bridgehdr As PHBridgeHeader = APs.Get(0)
            else if APs.Get(0) Is PHLight Then
                Log("get PHLigth")
                Dim light As PHLight = APs.Get(0)
            End If
            'sdk.startPushlinkAuthentication(ap)
            'Log("Groups: "&bridge.AllGroups)
            'Log("Lights: "&bridge.AllLights)
            'Log("Rules: "&bridge.AllRules)
            'Log("Scenes: "&bridge.AllScenes)
            'Log("Sensors: "&bridge.AllSensors)
            'Log("AllShedules: "&bridge.getAllSchedules(True))
            'Log("AllTimers: "&bridge.getAllTimers(True))
        Else
            For i = 0 To APs.Size-1
                Dim ap As PHAccessPoint = APs.Get(i)
                   
            Next
        End If
    End If
End Sub
Sub HUE_onAuthenticationRequired(apoint As PHAccessPoint)
    Log($"HUE_onAuthenticationRequired(${apoint})"$)
    If apoint<>Null And apoint Is PHAccessPoint Then
        Dim ap As PHAccessPoint = apoint
        Log(ap.BridgeId)
        Log(ap.IpAddress)
        sdk.startPushlinkAuthentication(ap)
    End If
End Sub
Sub HUE_onBridgeConnected(bridge As PHBridge, info As String)
    Log($"HUE_onBridgeConnected(${bridge},${info})"$)
    BridgeSelected = bridge
    sdk.addBridge(bridge)
    Log("Groups: "&bridge.AllGroups)
    Log("Lights: "&bridge.AllLights)
    Log("Rules: "&bridge.AllRules)
    Log("Scenes: "&bridge.AllScenes)
    Log("Sensors: "&bridge.AllSensors)
    Log("AllShedules: "&bridge.getAllSchedules(True))
    Log("AllTimers: "&bridge.getAllTimers(True))
   
End Sub
Sub HUE_onCacheUpdated(cacheNotifications As List, bridge As PHBridge)
    Log($"HUE_onCacheUpdated(${cacheNotifications},)"$)
End Sub
Sub HUE_onConnectionLost(ap As PHAccessPoint)
    Log($"HUE_onConnectionLost(${ap})"$)
End Sub
Sub HUE_onConnectionResumed(bridge As PHBridge)
    Log($"HUE_onConnectionResumed(${bridge})"$)
End Sub
Sub HUE_onError(code As Int, message As String)
    Log($"HUE_onError(${code},${message})"$)
End Sub
Sub HUE_onParsingErrors(errors As List)
    Log($"HUE_onParsingErrors(${errors})"$)
End Sub
 
Last edited:

Andie

Member
Licensed User
Longtime User
Hi, Manfred,
vielen Dank für Deine Antwort. Mit der download-Methode kann ich jetzt immerhin den Status der einzelnen Lampen abfragen. Mit dem Einschalten bzw. Ausschalten klappt es noch nicht.
Deine Hue-Lib finde ich sehr interessant. Ich vermute mal, dass sie auch auf die Philips-Api zugreift. Allerdings bin ich im Moment noch kein geeigneter Tester dafür, da ich mich erst noch in das Hue-System etwas einarbeiten muss. Aber dann würde ich sie gerne mal ausprobieren ...
Andie
 

DonManfred

Expert
Licensed User
Longtime User
Ich vermute mal, dass sie auch auf die Philips-Api zugreift
Nicht AUCH. Sie arbeit nur mit dem PhilipsSDK.
Das das alles per hhtp auch geht war mit gar nicht bewusst. :D
Hast Du genauere Infos dazu?

PS: Ich habe kürzlich erst alle Lampen und ein paar Schalter durch HUE-Komponenten ausgetauscht und nutze aktuell die Original-App von Philips.
 

Andie

Member
Licensed User
Longtime User
So mache ich es im Moment auch; aber mit eigener App zu steuern macht natürlich mehr Spaß.

Ich werde den "request.put"-Fall mal im englischen Forum posten. Habe ein gutes Gefühl, dass ich auch das Einschalten noch hinkriege. Ich werde Dir auf jeden Fall Bescheid und genauere Infos geben.
 

Andie

Member
Licensed User
Longtime User
Auch an dieser Stelle ein Dankeschön für Dein reply im englischen Forum, Manfred.

Der Python-Code läuft bei mir auf dem Raspberry Pi und auf meinem Windows-Rechner unter der Python-IDE Thonny (eine tolle Sache). Ich habe die Codes fürs Einschalten, Ausschalten, Status und Erzeugung einer Api-User-ID in einer Word-Datei mit Kommentaren zusammengefasst. Falls Du Interesse daran hast, kann ich sie Dir mailen.

Aber das Schönste ist natürlich, dass ich nun meine Philips-Lampen - wenn auch bis jetzt nur ganz "grob" - per App steuern kann.
 

DonManfred

Expert
Licensed User
Longtime User
Auch an dieser Stelle ein Dankeschön für Dein reply im englischen Forum, Manfred
Bitte. Gern geschehen.
Ich habe die Codes fürs Einschalten, Ausschalten, Status und Erzeugung einer Api-User-ID in einer Word-Datei mit Kommentaren zusammengefasst
Nicht nötig; ich habe die nötigen Infos in der Dokumentation (siehe oben) gefunden.
 

DonManfred

Expert
Licensed User
Longtime User
Ich habe die Codes fürs Einschalten, Ausschalten, Status und Erzeugung einer Api-User-ID in einer Word-Datei mit Kommentaren zusammengefasst
Du kannst, für die Allgemeinheit, im englischen Bereich ein Tutorial erstellen, wo Du auf die Erzeugung des "Usernamen" eingehst. Das wird die grösste Hürde sein bei den Anwendern denke ich. Ich bin da auch nur "durch Zufall" drauf gestossen.

Das Tutorial wäre sicherlich hilfreich für viele.

PS: Für die Nutzung der Api wird es bald von mir eine Library geben mit der man das dann easy in die eigene app einbauen kann. Ich werde eine Lib veröffentlichen die das Hue Java SDK benutzt.

Ich werde aber auch eine Beispiel Klasse für B4A veröffentlichen mit der man das ohne Lib machen kann die dann okhttputils2 benutzt...

Beginn der Klasse PhilipsHUE.bas
B4X:
Sub Class_Globals
    Private HUEusername = "ofmxXcuFVe0okMRIxcyaSQRMtqTFBS9ANBjfCboI"
    Private bridgeurl As String = ""

End Sub

'initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(bridgeIP As String, username As String)
    bridgeurl = $"http://${bridgeIP}/api/${username}/"$
    'getLights
    'getNewLights
    'getSensors
    getGroups
End Sub

' Get a List of all known Lights
Sub getLights()
    Dim l As List
    l.Initialize
    Dim Job As HttpJob
    Job.Initialize("", Me)
    Job.Download(bridgeurl&"lights")
    wait for (Job) Jobdone(Job As HttpJob)
    If Job.Success Then
        Log(Job.GetString)
       
        Dim parser As JSONParser
        parser.Initialize(Job.GetString)
        Dim root As Map = parser.NextObject
        For i = 1 To 512
            Dim key As String = i
            If root.ContainsKey(key) Then
                Dim m1 As Map = root.Get(key)
                l.Add(m1)
                Log(m1)
            End If
        Next
        Log("Size of Lightslist = "&l.Size)
        For i = 0 To l.Size-1
            getLight(i+1)
        Next
       ' Event in b4a auslösen...
    Else
        Log(Job.ErrorMessage)
    End If

End Sub

' Get new connected lights
' Returns an Empty list if no new Lights are found
Sub getNewLights()
    Dim l As List
    l.Initialize
    Dim Job As HttpJob
    Job.Initialize("", Me)
    Job.Download(bridgeurl&"lights/new")
    wait for (Job) Jobdone(Job As HttpJob)
    If Job.Success Then
        Log(Job.GetString)
       
        Dim parser As JSONParser
        parser.Initialize(Job.GetString)
        Dim root As Map = parser.NextObject
        For i = 1 To 512
            Dim key As String = i
            If root.ContainsKey(key) Then
                Dim m1 As Map = root.Get(key)
                l.Add(m1)
            End If
        Next
        Log("Size of NewLightslist = "&l.Size)
       ' Event in b4a auslösen...
    Else
        Log(Job.ErrorMessage)
    End If

End Sub

' Get the state of a Light.
Sub getLight(lightID As String)
    Dim l As List
    l.Initialize
    Dim Job As HttpJob
    Job.Initialize("", Me)
    Job.Download(bridgeurl&"lights/"&lightID)
    wait for (Job) Jobdone(Job As HttpJob)
    If Job.Success Then
        Log(Job.GetString)
       
        Dim parser As JSONParser
        parser.Initialize(Job.GetString)
        Dim root As Map = parser.NextObject
        For i = 1 To 512
            Dim key As String = i
            If root.ContainsKey(key) Then
                Dim m1 As Map = root.Get(key)
                l.Add(m1)
            End If
        Next
        Log("Size of Lightslist = "&l.Size)
       ' Event in b4a auslösen...
    Else
        Log(Job.ErrorMessage)
    End If

End Sub


' Get a List of all known Sensors
Sub getSensors()
    Dim l As List
    l.Initialize
    Dim Job As HttpJob
    Job.Initialize("", Me)
    Job.Download(bridgeurl&"sensors")
    wait for (Job) Jobdone(Job As HttpJob)
    If Job.Success Then
        Log(Job.GetString)
       
        Dim parser As JSONParser
        parser.Initialize(Job.GetString)
        Dim root As Map = parser.NextObject
        For i = 1 To 512
            Dim key As String = i
            If root.ContainsKey(key) Then
                Dim m1 As Map = root.Get(key)
                l.Add(m1)
                Log(m1)
            End If
        Next
        Log("Size of sensorslist = "&l.Size)
        For i = 0 To l.Size-1
            'getSensor(i+1)
        Next
       ' Event in b4a auslösen...
    Else
        Log(Job.ErrorMessage)
    End If

End Sub

' Get a List of all known Groups
Sub getGroups()
    Dim l As List
    l.Initialize
    Dim Job As HttpJob
    Job.Initialize("", Me)
    Job.Download(bridgeurl&"groups")
    wait for (Job) Jobdone(Job As HttpJob)
    If Job.Success Then
        Log(Job.GetString)
       
        Dim parser As JSONParser
        parser.Initialize(Job.GetString)
        Dim root As Map = parser.NextObject
        For i = 1 To 512
            Dim key As String = i
            If root.ContainsKey(key) Then
                Dim m1 As Map = root.Get(key)
                l.Add(m1)
                Log(m1)
            End If
        Next
        Log("Size of Groupslist = "&l.Size)
        For i = 0 To l.Size-1
            'getSensor(i+1)
        Next
       ' Event in b4a auslösen...
    Else
        Log(Job.ErrorMessage)
    End If

End Sub
 

Andie

Member
Licensed User
Longtime User
Deine Lib und die Klasse PhilipsHUE.bas sind ein Meilenstein. Ein schöner Nebeneffekt der Klasse ist, dass man viel über Http und das Parsen von JSON-Strings lernt, wenn man sich ein bisschen reinarbeitet.

Was das Tutorial bzgl. username angeht: Ich denke, da wirst Du bei der Veröffentlichung Deiner Lib bzw. Klasse drauf eingehen. Wenn ich das jetzt machen würde, stände es isoliert im Raum. Im Gesamtzusammenhang ist es besser aufgehoben....
 

DonManfred

Expert
Licensed User
Longtime User
Wenn ich das jetzt machen würde, stände es isoliert im Raum
Nö- Ich würde in meinem Library-Thread auf dieses Tutorial verlinken....

Sagen wir es so: Sobald Du dein Tutorial veröffentlicht hast werde ich meine Library veröffentlichen (spätestens am Tag danach) und ich werde im Library-thread auf dieses Tutorial verweisen als Pflichtlektüre. Ebenso bei der Klasse.
Ich bin FAUL was Dokumentation und so weiter betrifft.

Käme mir also entgegen, auf solch ein Tutorial verweisen zu können :)
 
Last edited:
Top