michielpost / Q42.HueApi

C# helper library to talk to the Philips Hue bridge
MIT License
411 stars 114 forks source link

Entertaiment API stops streaming after x time #236

Closed TripleNico closed 2 years ago

TripleNico commented 3 years ago

I noticed than if the connection is running longer than x time it seams that the bridge somehow falls out of Streamingmode. The entertaiment commands are handled without any error but nothing happens. Re-creating the entertaimentlayer causes the bridge to go back in Streamingmode.

Is this expected behaviour?

michielpost commented 3 years ago

I'm not aware of any time limits on streaming mode. I've succesfully used streaming for periods longer than 24 hours continuously.

If the bridge does not receive any new streaming updates for I believe 5 or 10 seconds, it will close the streaming channel and you have to restart it.

TripleNico commented 3 years ago

Hmm strange. I would have to investigate it further.

The streaming void in the Q42 API library does send data every 50ms right?

michielpost commented 3 years ago

If you call client.AutoUpdate(entGroup, 50); it sends 50 updates per second. So once every 20ms.

https://github.com/Q42/Q42.HueApi/blob/master/src/Q42.HueApi.Streaming/StreamingHueClient.cs#L98

TripleNico commented 3 years ago

I'm already using that void, so it was also strange to me. Haven't set the update frequency because this is a optional parameter which default is already 50.

I decided i will make a WatchDog task that watches for the streaming mode to become inactive, log it and then restart/init it.

This is my setup code so far which works fine. I use one one baselayer for the entertainment API.

If Me.EntertainmentClient IsNot Nothing AndAlso Me.EntertainmentClient.LocalHueClient IsNot Nothing Then
            Log.Message(LogLevel.Info, "Setting Entertainment...")

            'To use entertainment we have to setup the entertainment streams so we only have to send commands in the IFTTT processor
            'Get the entertainment group(s)
            Dim lstGroups As IReadOnlyList(Of Group) = Await Me.EntertainmentClient.LocalHueClient.GetEntertainmentGroups

            'Get the entertainment group
            Dim item As Group = lstGroups.FirstOrDefault

            'Check if we got the entertainment group. If not exit this function
            If item Is Nothing Then
                Log.Message(LogLevel.Warning, "No entertainmentgroups found, Please add one in the Hue App on your smartphone")
                Await localMain.ShowErrorDialog("No entertainmentgroups found, Please add one in the Hue App on your smartphone")
                Exit Sub
            End If

            Log.Message(LogLevel.Debug, "Found Entertainment groupname: " & item.Name & " Id:" & item.Id & " Streamactive: " & item.Stream.Active.ToString)

            'Create a streaming group
            Dim entGroup As New StreamingGroup(item.Locations)

            Try
                'Connect to the streaming group
                Await Me.EntertainmentClient.Connect(item.Id)
            Catch ivo As InvalidOperationException
                Log.Exception(ivo)
            Catch ex As Exception
                Log.Exception(ex)
            End Try

            'Create new base layer
            Me.entGroup = New EntertainmentGroup With {.GroupID = item.Id, .entBaseLayer = entGroup.GetNewLayer(True), .entEffectLayer = entGroup.GetNewLayer(False)}

            'Start auto updating this entertainment group
            Await Me.EntertainmentClient.AutoUpdate(entGroup, cancelToken.Token)
End If

En than when executing a command: LocalHueBridge.entGroup.entBaseLayer.SetState(ct, trig.RGB, trig.Brightness / 255, trig.Priv_Duration, False)

TripleNico commented 3 years ago

Some extra information, i found out that in AutoUpdate an TLS exception could be thrown, causing the AutoUpdate to stop:

Org.BouncyCastle.Crypto.Tls.TlsFatalAlert
  HResult=0x80131620
  Message=internal_error(80)
  Source=BouncyCastle.Crypto
  StackTrace:
   at Org.BouncyCastle.Crypto.Tls.DtlsTransport.Send(Byte[] buf, Int32 off, Int32 len) in D:\a\1\s\crypto\src\crypto\tls\DtlsTransport.cs:line 58
   at Q42.HueApi.Streaming.StreamingHueClient.Send(Byte[] buffer, Int32 offset, Int32 count)
   at Q42.HueApi.Streaming.StreamingHueClient.Send(List1 states)
   at Q42.HueApi.Streaming.StreamingHueClient.Send(IEnumerable1 chunks)
   at Q42.HueApi.Streaming.StreamingHueClient.<>c__DisplayClass13_0.<AutoUpdate>b__0()
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
InvalidOperationException: GCM cipher cannot be reused for encryption

Versions: Q42.HueApi = v3.15.4 BouncyCastle.NetCore = v1.8.5

TripleNico commented 2 years ago

This problem was solved in issue #253