Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

[SonyAudio]Sony Audio Control API #4838

Merged
merged 1 commit into from
Nov 7, 2018

Conversation

freke
Copy link
Contributor

@freke freke commented Jan 2, 2018

Sony has just released their Audio Control API, this is a first implementation to make use this. And make a extension to control the officially supported products from Sony.

All help/comments to get this accepted would be appreciated.

More info about the Audio Control API can be found at https://developer.sony.com/develop/audio-control-api/

David Åberg
Sony Developer World

Signed-off-by: David AAberg david.aberg@sony.com

@tmrobert8
Copy link
Contributor

tmrobert8 commented Jan 3, 2018

David (@freke),

I hope you don't mind if I comment on this - I've written a whole sony product line binding (TVs, AVRs, soundbars, blurays) for openHAB that pretty much already covers what this does plus alot more (I have a whole dynamic scalarwebapi implementation, ircc, dial and simpleip implementations). All my work has been based on figuring out the APIs from wireshark and observances (can't believe we finally have some API doc)!

I'd love to do some collaboration with you on the whole binding since, it appears, you are an actual sony developer! I'm definitely going to look through the documentation/your code and see if/where I'm missing things.

Feel free to contact me for additional information

Tim

@freke
Copy link
Contributor Author

freke commented Jan 3, 2018

Hi Tim (@tmrobert8),

I have had some look at your work at the OpenHAB forum/github for a while (since we started to work on releasing this), I'm still on holiday but was planning to comment at the OpenHAB forum to let you know about the API if you missed it, when I was back. I will happily answers all the questions I can, if I can't I have contacts with the Audio engineers in Tokyo.
Unfortunately I can only comments the parts that are opened (mainly Audio and secondly Camera) for now, But to keep things in order I think the questions not directly about this pull request should be in the OpenHAB forum (I will add a comment there too).

The reason for this pull request is, that if I understand the setup correctly "eclipse smarthome" is for only officially released API:s therefore this this binding is only for the products/API's that have got clearance from SONY. OpenHAB is for then you are going in to the gray area ;-)

If I have misunderstood feel free to correct me.

David Åberg
Sony Developer World

@tmrobert8
Copy link
Contributor

tmrobert8 commented Jan 3, 2018

David (@freke),

I'll let @kaikreuzer or someone else from the project respond to your question about separation between the projects (and what goes where) - that's above my pay grade ;) However, depending on the answer, I'd be happy to 'upgrade' the plugin code to ESH and do some team development on it with you or whomever. I'm currently in the process of making changes so that it can be merged properly - so I'm close to the review time.

Enjoy your holiday and when you get back (no hurry on this) - could you comment on the following...

I (quickly) looked through the API and think I got most of it covered (atleast to what I wanted to support) - although the websocket part was all new and I'll be integrating that in shortly. I do have a few questions:

  1. For discussion purposes - can we talk only about the officially supported hardware or can we talk more generally (since webscalar is on alot of devices)?
  2. Are these APIs documented advertised in the methods returned by getMethodTypes call or do we just assume they are available?
  3. Would we be able to talk about authentication (which is the biggest issue)? Example: I have an HT-NT5 soundbar that advertises webscalar services but I haven't figured out (yet) how to authenticate against it because it doesn't advertise the actRegister method (this applies to some other devices as well).

Just wanted to comment that this is very exciting - I believe the openHAB plugin is the most advanced and handles the widest range of sony products of any other plugin out there and would love to have some QA time with developers 'in the know'!

BTW - you mentioned the camera API as well. I'd love to hear any ideas about integrating that API - I don't really know the use cases well enough to venture into it (I do have some sony cameras and video records - not sure if they are supported however).

THanks,
Tim

@tmrobert8
Copy link
Contributor

David (@freke)

Verrrryyyy cool - the websocket connection doesn't need authentication! I just modified your code to support my HT-NT5 and it came online and is controllable just fine. I'll definitely be adding that back into my code!

@freke
Copy link
Contributor Author

freke commented Jan 3, 2018

Hi Tim,
Quick answers,

  1. You can ask and I can see what I can do. But see it as I can only talk about the released parts of the API, it is not really bound to the hardware.
  2. getMethodTypes is one of the functions not documented ;-) (but yes all the method supported by the current product is reported by getMethodTypes then supported)
  3. Can't talk about authentication since no audio products is using this.

You might find this SDK a good reading https://developer.sony.com/develop/cameras/ even if your device is not supported :-)

Best Regardes
David Åberg

@tmrobert8
Copy link
Contributor

David,

Thanks for the answers - if when you were looking at my code you saw any issues and are open to discussing them, I'm all ears..

Tim

@kaikreuzer
Copy link
Contributor

Welcome @freke at ESH, it is awesome to see official support and documentation for Sony Audio products!

"eclipse smarthome" is for only officially released API:s
openHAB is for then you are going in to the gray area

Let me clarify/precise this a bit: Any code that is used (or of interest to be used) in a commercial product that is based on Eclipse SmartHome should be part of this project. As anyone that builds a commercial product wants to be sure that device integrations run stable and correct, officially documented APIs and common protocols are clearly the much preferred way here.
It imho therefore makes a lot of sense to have a SonyAudio binding here at ESH, which is based on the officially supported API (and nothing more than that).

Having said this doesn't mean that code on the openHAB side is automatically in a "gray area". Many bindings are simply put there because they are only interesting for openHAB and not for any other ESH-based solution, so we do not want to spend the time for the more rigid IP checks at Eclipse. Also, code might be based on reverse-engineering of protocols (such as @tmrobert8's work), which afaik isn't a legal issue as long as it does not break any encryption, but which obviously runs the risk to easily break by any new firmware update of a device.

So how shall we best proceed here?
I'd think it would be great if @tmrobert8 could join forces on this PR here with all his knowledge that he already has about ESH. Ideally the outcome is a binding that supports all officially documented parts for all Sony products that support the Sony Audio API.
All further devices/features could continue to reside in openhab2-addons. We can discuss how this should be best structured: Whether we have a completely independent binding or if we'd better design the ESH binding to be easily extensible e.g. by extending handler classes while reusing all the code from the ESH binding (I guess that'll be the much preferred way).

Cheers,
Kai

@freke
Copy link
Contributor Author

freke commented Jan 4, 2018

Thanks Kai,

That sounds like a good idee @kaikreuzer I like the idea of having a ESH biding that is expandable in to the OpenHAB domain, to avoid duplicated functionality/bugs and would like the knowledge of @tmrobert8 do this.

And thanks for the clarification, I think I have understood this correctly, "gray area" might have been the wrong term, was not implying that OpenHAB was doing anything illegal, just that it is using things that don't have a clear usages agreement, that can be unsertant for commercial use.

Best,
David Åberg

@tmrobert8
Copy link
Contributor

The approach sounds good to me but just for my understanding @kaikreuzer - are you saying that openHAB bindings can reference/extend ESH bindings (as opposed to openHAB bindings cannot reference other openHAB bindings)? If that's the case, then I can certainly recommend some changes that would allow me to reuse some of the code (definitely the websocket connection and we could move some of the json processing/classes from mine up to his).

@kaikreuzer
Copy link
Contributor

are you saying that openHAB bindings can reference/extend ESH bindings

@tmrobert8, Almost, but not quite. What I am saying is that a binding can consist out of multiple OSGi bundles, which could reside anywhere (in ESH, OH2 or whereever else).
This is a concept that we had in mind when defining the binding skeleton - you will notice that the handler packages are actually exported in the MANIFEST, so that they can be reused/extended.
Only one bundle must include a binding.xml, though, the additional ones would be seen as "extensions" to the binding and would only bring additional thing types.

Although this concept has been conceived from the beginning, it was actually never used so far.
We are experimenting with the first bindings to do exactly that right now, see e.g. Bluetooth (#4535) or Zigbee (openhab/org.openhab.binding.zigbee#47).

Note that this only applies at all the code parts that contain thing types/handlers etc and thus belong to the same binding. As we already discussed in the past, another option is the introduction of an io.transport bundle, which could contain code that you might want to share across multiple bindings (e.g. a "Sony Audio" and a "Sony TV" binding). It would simply be a kind of shared library as a common dependency, but it would not bring itself any user facing functionality.

@freke
Copy link
Contributor Author

freke commented Feb 15, 2018

Have rebased and updated the pull request with the two new soundbars SONY is now supported by the Audio Control API.

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, @freke, that looks already pretty good!
I left a few first comments regarding the thing xmls. I won't dive deeper into the code yet, but rather wait for your signal that you do not consider it WIP anymore, but think it is getting towards completion. Thanks!

xsi:schemaLocation="http://eclipse.org/smarthome/schemas/binding/v1.0.0 http://eclipse.org/smarthome/schemas/binding-1.0.0.xsd">

<name>SonyAudio Binding</name>
<description>This is the binding for SonyAudio products (Recievers and wirelesspeakers).</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Recievers -> Receivers
I see this more often throughout the code, please fix it at all places.

<description>The IP or host name of the SONY audio device</description>
<context>network-address</context>
</parameter>
<parameter name="port" type="integer" min="1" max="65335" required="true">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be required as you define a default value.

<description>Port of the SONY audio device to control</description>
<default>10000</default>
</parameter>
<parameter name="path" type="text" required="true">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be required as you define a default value.

</parameter>
<parameter name="path" type="text" required="true">
<label>Base path</label>
<description>Base path to the SONY audio device to control</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it is really not clear, what this path is supposed to be and what is expected from me as a user when manually configuring it.

@@ -0,0 +1,13 @@
# FIXME: please substitute the xx_XX with a proper locale, ie. de_DE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this file


<!-- HT-CT800 Thing Type -->
<thing-type id="HT-CT800">
<label>SONY soundbar HT-CT800</label>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

soundbar -> Soundbar


<!-- HT-MT500 Thing Type -->
<thing-type id="HT-MT500">
<label>SONY soundbar HT-MT500</label>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

soundbar -> Soundbar

<channel-type id="radioBroadcastFreq">
<item-type>Number</item-type>
<label>Broadcast frequency</label>
<description>Select the broadcast frequency</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is for "selecting", why did you mark it as readOnly (which means that you cannot send commands to it)?

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you switch to using DS annotations? (check other bindings or the latest archetype on how that looks like).

@@ -0,0 +1,99 @@
/**
* Copyright (c) 2014,2017 Contributors to the Eclipse Foundation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you re-run mvn license:format to update the year in all headers?

@freke
Copy link
Contributor Author

freke commented Feb 16, 2018

@kaikreuzer Last build is it my fault it failed or is it travis that had a hick up?

@kaikreuzer
Copy link
Contributor

Doesn't look like your fault, I've just retriggered Travis.

@freke
Copy link
Contributor Author

freke commented Mar 5, 2018

I don't think this build fail was with the sonyaudio plugin looks like it was the paperui to me.
I believe I have fixed the initial concerns @kaikreuzer had and if @tmrobert8 don't have anything he wants to add/alter to better suite his needs, I'm happy with this and will remove the WIP tag next week (then I'm back from vacation).

@kaikreuzer
Copy link
Contributor

Thanks @freke! I haven't yet found the time to have another detailed look, but if you feel the code is ready, please remove the WIP at any time - this is then anyhow the best signal that you wish it to be reviewed and merged!

@FrankZimmer
Copy link

Hi,

thanks first the initial work and i happy to have my Sony Player supportet next :-)
Correct me if I'm wrong, but i'm wondering if it possible to support some more features:

  • Player Item (support Play Pause, Next, Prev etc...)
  • String Items for: current Track, current Artist, Album, Title, etc..
  • I see in the API docu, that you can set a URI (setPlayContent --The URI of the input or source). So you can see on the SONOS Binding, we implement here an notification channel. Idea behind set here an MP3 File URI and the Player start playing this sound. Also the binding should care about the state previous. e.g. Playing a Playlist, call notofocation sound via API, Player stop playing Playlist, start playing the notofocation sound, after it is finished, the player return to the latest postition of the playlist. Same works for Streaming or Internetradio etc... We also use a seperat notofocation sound volume, to set a special volume for this...

I think special the last point (notification) makes the player a step closer to a smarthome use case at all.

Thanks for support

Frank

@freke
Copy link
Contributor Author

freke commented Mar 15, 2018

Hi @FrankZimmer

  • I have chosen not to include the play functionality since that is handled by DLNA protocol, google cast or spotify on Sony devices. So a generic DLNA/google cast/spotify player/controller might be a better solution instead of implement my own.
  • I was thinking of adding String Items for: current Track, current Artist, Album, Title, etc.. but dropped it since if you play a google cast or spotify and sometimes if via DLNA I don't get this info via the Audio Control Api so it will be confusing for the user why it only works some times. This is maybe also more related to the actual player.
  • the URI referred to in the API reference is an old remanence the preferred way is to use DLNA.

At the moment getting something out that works (even if limited) is better than nothing, in my oppinion. Adding the player functionality and audiosink later if it is seen as a good idee is always possible.

David

@freke freke changed the title [WIP][SonyAudio]Sony Audio Control API [SonyAudio]Sony Audio Control API Mar 15, 2018
Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @freke, sorry for taking so long with coming back to you!
I agree that this binding makes sense even with the limited set of functionality (and rather hope for some proper DLNA support by another binding), so let's go ahead with this.

The code looks pretty good already and I mainly think it requires some hardening for exception and error handling - please see my comments below and let me know, if you have any questions. Thanks!

xsi:schemaLocation="http://eclipse.org/smarthome/schemas/binding/v1.0.0 http://eclipse.org/smarthome/schemas/binding-1.0.0.xsd">

<name>SonyAudio Binding</name>
<description>This is the binding for SonyAudio products (Receivers and wirelesspeakers).</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: wirelesspeakers -> wireless speakers

</parameter>
<parameter name="port" type="integer" min="1" max="65335">
<label>Port</label>
<description>Port part from X_ScalarWebAPI_BaseURL for the SONY audio device to control.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove the "Port part from X_ScalarWebAPI_BaseURL for the SONY audio device to control." from the description as this sounds rather technical for the average user.

</parameter>
<parameter name="path" type="text">
<label>Base path</label>
<description>The path part from the X_ScalarWebAPI_BaseURL for the SONY audio device to control, "/sony" in most cases</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also better remove "part from the X_ScalarWebAPI_BaseURL" here

<channel-type id="input-dn1080-zone2">
<item-type>String</item-type>
<label>Input Source</label>
<description>Select the input source of the reciever</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: reciever -> receiver

<channel-type id="input-dn1080-zone4">
<item-type>String</item-type>
<label>Input Source</label>
<description>Select the input source of the reciever</description>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: reciever -> receiver

try {
socket.close();
} catch (Exception e) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better at least add a debug logging here

try {
socket.open();
return socket.isConnected();
} catch (Throwable t) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never catch Throwable, only more specific exceptions.

socket.open();
return socket.isConnected();
} catch (Throwable t) {
logger.error("exception during connect to {}", socket.getURI().toString(), t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not log errors unless it's a software bug and remove toString() from parameters.

return item.get("currentValue").getAsString().equalsIgnoreCase("on") ? true : false;
}
}
throw new IOException("Unexpected responces");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: responces -> responses

try {
List<Channel> channels = getThing().getChannels();
for (Channel channel : channels) {
handleCommand(channel.getUID(), RefreshType.REFRESH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty inefficient for those reasons:

  1. You are doing calls for channels that aren't linked at all - that's a waste of time. Better use the callback.isChannelLinked method.
  2. This can cause a huge number of external requests; is the connection able to easily handle this load? Afaics, some requests contain data for multiple channels, so that the same requests are done multiple times. If my assumption is true, you might want to consider using the ExpiringCache see here.

@kaikreuzer kaikreuzer removed their assignment Jun 22, 2018
@kaikreuzer
Copy link
Contributor

@freke Something just went pretty wrong when you pushed your branch.
Please make sure to always only rebase your branch on the latest master, never do merge commits.
Once you have a clean branch locally, please force push it again.

@freke
Copy link
Contributor Author

freke commented Jul 27, 2018

@kaikreuzer sorry don't know what happed I was only planing to do a rebase, and something went very wrong :-/ will try to fixit

Re added the [WIP] for now...

@freke freke changed the title [SonyAudio]Sony Audio Control API [WIP][SonyAudio]Sony Audio Control API Jul 27, 2018
@kaikreuzer
Copy link
Contributor

@freke Thanks for the cleanup, looks much better again 👍 .
Please ping me once you have addressed my comments - would be nice to eventually merge this PR.

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @freke,

I just tested the binding with an HT-ST5000 and it works pretty smooth!
I found a few small further issues, see comments below.
One bigger issue that I noticed is that once the connection is created, I see around 30 (yes, thirty!) threads of WebSocketClient. I know that Jetty uses defaults that are rather meant for servers than for embedded hardware, so we might need to tweak the configuration of that client. What's more is that these threads keep running even if I stop the bundle completely - so there seems to be something wrong with the cleanup in the handler disposal. Could you please check?

Please let me know, if there's anything I can help you with to get things in a mergeable state. Thanks!

Bundle-Version: 0.10.0.qualifier
Export-Package: org.eclipse.smarthome.binding.sonyaudio,
org.eclipse.smarthome.binding.sonyaudio.handler
Import-Package: com.google.common.collect,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have meanwhile decided to deprecate the use of Guava, so it would be nice if you could remove this dependency (should be simply as it is only used once for an ImmutableSet).


public void handleVolumeCommand(Command command, ChannelUID channelUID) throws IOException {
if (command instanceof RefreshType) {
updateState(channelUID, new DecimalType(connection.getVolume() / 100.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use PercentType instead of DecimalType and you do not need to divide by 100.

if (command instanceof RefreshType) {
updateState(channelUID, new DecimalType(connection.getVolume() / 100.0));
}
if (command instanceof DecimalType) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for PercentType instead of DecimalType

updateState(channelUID, new DecimalType(connection.getVolume(zone) / 100.0));
}
if (command instanceof DecimalType) {
connection.setVolume(((DecimalType) command).intValue(), zone);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for PercentType instead of DecimalType


public void handleVolumeCommand(Command command, ChannelUID channelUID, int zone) throws IOException {
if (command instanceof RefreshType) {
updateState(channelUID, new DecimalType(connection.getVolume(zone) / 100.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use PercentType instead of DecimalType and you do not need to divide by 100.

public void updateVolume(int zone, int volume) {
switch (zone) {
case 0:
updateState(SonyAudioBindingConstants.CHANNEL_VOLUME, new DecimalType(volume / 100.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use PercentType instead of DecimalType and you do not need to divide by 100 - same for other zones

<description>Select the input source of the receiver</description>
<state>
<options>
<option value="btAudio">Bluetooth Audio</option>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be btaudio instead of btAudio - same for the other thing types.

@kaikreuzer
Copy link
Contributor

Ouch, you've just messed up your branch again :-(
Please never do any merge commits, you cannot properly recover from them. Always do "rebase on master" instead!

@kaikreuzer
Copy link
Contributor

Thanks for the updates! The HT-ZF9 is now nicely discovered. I have some issues with updates from the soundbar to the binding though; while power and input selection changes are correctly reported, I do not get updates of the volume or mute information (if changed on the soundbar itself; I can control volume and mute from the binding, though). Can you confirm this effect?

While the exceptions during startup are gone, the Thing status updates aren't really "user compatible" now:

2018-09-10 14:38:15.062 [DEBUG] [s.b.s.handler.SonyAudioHandler:133  ] - Handle command sonyaudio:STR-DN1080:00000000-0000-1010-8000-702605d65b4c:radio#broadcastFreq REFRESH
2018-09-10 14:38:15.065 [DEBUG] [.b.s.i.p.SonyAudioClientSocket:189  ] - callMethod send {"params":[],"id":5,"method":"getCurrentExternalTerminalsStatus","version":"1.0"}
2018-09-10 14:38:15.064 [DEBUG] [s.b.s.handler.SonyAudioHandler:133  ] - Handle command sonyaudio:STR-DN1080:00000000-0000-1010-8000-702605d65b4c:radio#broadcastSeekStation REFRESH
2018-09-10 14:38:15.066 [INFO ] [ome.event.ThingStatusInfoEvent:53   ] - 'sonyaudio:STR-DN1080:00000000-0000-1010-8000-702605d65b4c' updated: OFFLINE (COMMUNICATION_ERROR): java.io.IOException: Error during callMethod
2018-09-10 14:38:15.064 [DEBUG] [s.b.s.handler.SonyAudioHandler:257  ] - handleInputCommand RefreshType 4
2018-09-10 14:38:15.067 [INFO ] [ome.event.ThingStatusInfoEvent:53   ] - 'sonyaudio:STR-DN1080:00000000-0000-1010-8000-702605d65b4c' updated: OFFLINE (COMMUNICATION_ERROR): java.io.IOException: Audio Socket not connected
2018-09-10 14:38:15.067 [DEBUG] [.b.s.i.p.SonyAudioClientSocket:189  ] - callMethod send {"params":[{"output":"extOutput:zone?zone=4"}],"id":6,"method":"getPlayingContentInfo","version":"1.2"}
2018-09-10 14:38:15.068 [INFO ] [nt.ThingStatusInfoChangedEvent:53   ] - 'sonyaudio:STR-DN1080:00000000-0000-1010-8000-702605d65b4c' changed from OFFLINE (COMMUNICATION_ERROR): java.io.IOException: Error during callMethod to OFFLINE (COMMUNICATION_ERROR): java.io.IOException: Audio Socket not connected

As the devices are available on the network (in this case), I would not except an OFFLINE status at all, but the binding should actually establish the connection immediately.

@freke
Copy link
Contributor Author

freke commented Sep 10, 2018

@kaikreuzer One question is the device powered off then you get this error message?

@kaikreuzer
Copy link
Contributor

Yes, powered off, but being configured to be activated through the network.

@freke
Copy link
Contributor Author

freke commented Sep 10, 2018

I found why the HT-ZF9 only worked by pulling for volume and mute and not via notifications, just have to check so the change don't affected any other device.

For the Offline message:
I don't have that problem here then I'm testing, haven't set up all devices here right now so it could be one I haven't currently that is the problem.
@kaikreuzer Do you know if this is from all devices or only one specific?

EDIT: Think I have a theory my pulling interval is much shorter than default, so it might be the WebSocket timing out due to inactivity...

I have for one device (STR-DN1080) that is setup via files (not via Paper UI, STR-DN1080 is the only one I have tested to setup in this way) that then it starts it will switch between UNINITIALIZED, INITIALIZING, ONLINE and OFFLINE a few times before settling down on ONLINE, don't know if this is a problem or not?
But this is not the behavior then the device is set up via Paper UI, then it goes through the sequence once.

@cweitkamp
Copy link
Contributor

we can check if the caching implementation can be improved that way

A proposal: PR #6200

@kaikreuzer
Copy link
Contributor

Thanks for the updates @freke, I can confirm that the events now work smoothly for the HT-ZF9!

While testing, I made a few small changes to the code, which I have put into freke#3, which you can merge, if you are ok with them.

@kaikreuzer Do you know if this is from all devices or only one specific?

I have only seen this with the STR-DN1080 so far, all other go to ONLINE as expected, even if the device is turned off (but available on the network). Will have to do some further testing myself, if you cannot reproduce it.

@freke freke force-pushed the sonyaudio branch 2 times, most recently from 3de0bc4 to fbb6da3 Compare September 13, 2018 17:03
@freke
Copy link
Contributor Author

freke commented Sep 13, 2018

I have only seen this with the STR-DN1080 so far, all other go to ONLINE as expected, even if the device is turned off (but available on the network). Will have to do some further testing myself, if you cannot reproduce it.

@kaikreuzer I'm not 100% sure but I think I found the reason and I no longer any Errors or unexpected Offline/Online messages in my log, had it running all day today no issues.

@kaikreuzer
Copy link
Contributor

Hey @freke, some updates here:

But in the current implementation I can't I have to just invalidate the cache, can result in multiple updates in short time frame that could have been avoided.

#6200 has been merged, so you should be able to use this feature now.

What I am just contemplating is, whether we should enhance our HttpClientFactory (see also here to also offer a getCommonWebSocketClient() method.

I have implemented this yesterday and it has been merged today as #6258. Would be great if you'd adapt the code to make use of this new shared instance - let me know, if you have any questions on how to do that, I will certainly help!

Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few further small comments.

I'll do another full functional testing round during the next days - probably best after the code has been adapted to the new shared web socket client.

private ScheduledFuture<?> refreshJob;

private int currentRadioStation = 0;
private Map<Integer, String> input_zone = new HashMap<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to usually program in a different language - input_zone is not really following Java naming conventions, it should be inputZone instead. Same for all other new fields you have introduced for the caching below.

try {
SonyAudioConnection.SonyAudioInput result = input_cache[zone].getValue();
if (result != null) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove empty line

try {
connection = new SonyAudioConnection(ipAddress, port, path, this);

connection.connect(scheduler);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see this comment? Seems it isn't yet addressed?

connection.connect(scheduler);

// Start the connection checker
Runnable connectionChecker = new Runnable() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do that with lambdas like

Runnable connectionChecker = () -> {
...

logger.debug("SrsZr5Handler handleSoundSettings RefreshType");
Map<String, String> result = sound_settings_cache.getValue();
if (result != null) {
logger.debug("SrsZr5Handler Updateing sound field to {} {}", result.get("clearAudio"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: Updateing -> Updating

@Override
public void handleEvent(JsonObject json) {
int zone = 0;
JsonObject param = json.get("params").getAsJsonArray().get(0).getAsJsonObject();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see this comment? I really think the code should be hardened here to make it robust wrt missing json data.

SwitchNotifications switchNotifications = new SwitchNotifications(notifications.enabled,
notifications.disabled);
JsonElement switches = socket.callMethod(switchNotifications);
Gson mapper = new Gson();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see this comment?

@freke
Copy link
Contributor Author

freke commented Oct 7, 2018

Hi @kaikreuzer
Sorry for no update for a while, was away on business trip.

I have been trying to get the WebSocketFactory to work but I'm doing something wrong, see https://github.com/freke/smarthome/tree/common_websocket

Then I try to get the WebSocketFactory via @referenc setWebSocketFactory in SonyAudioHandlerFactory. WebSocketFactory get added to the OSGI-INF/*.xml
But setWebSocketFactory is never called (it did then I was trying to add HttpClientFactory).
My devices are discovered but when I try to add them, I get in the console "Cannot create thing, No binding found that supports creating a thing of type 'sonyaudio:HT-ZF9'"

Doing some thing something wrong... just can't figure out what.

Best Regards
David Åberg

@kaikreuzer
Copy link
Contributor

Hey @freke, sorry for my late reply this time, I have been on holiday for a week...

I just checked your code and it looks perfectly fine. Analysing it, I noticed that it was a stupid mistake on my end - the WebSocketFactory service is actually not at all registered with that interface, sorry for that 🙄. #6361 should fix this, so once this is merged, please rebase your branch on it and all should be fine.

@freke
Copy link
Contributor Author

freke commented Oct 16, 2018

Thanks @kaikreuzer, worked for me after update.

@kaikreuzer
Copy link
Contributor

Many thanks again, @freke!
The code looks all good to me now and I did further testing with multiple devices in parallel and the web socket connections appear to work well. I encountered some small random issues that I will still have to reliably reproduce and describe, but this is nothing that should block us from moving forward.

My impression is that the code is ready as an initial contribution, so the next step is to create a CQ (contribution questionnaire, I will take care of that, no worries) which means that the Eclipse IP team needs to approve the contribution. For this, we need it as a single commit, so may I ask you to squash all commits of this PR into a single one? That's the last thing for you to do right now! 😎

Signed-off-by: David AAberg <david.aberg@sony.com>
@freke
Copy link
Contributor Author

freke commented Nov 3, 2018

@kaikreuzer no problem, squashed :-)

@kaikreuzer
Copy link
Contributor

Perfect thanks! I've now created CQ 18054, so please refrain from doing any further changes on this branch.

@kaikreuzer kaikreuzer added CQ and removed CQ labels Nov 3, 2018
@kaikreuzer
Copy link
Contributor

Yeah, the CQ has been approved and we are allowed to check-in!
Many thanks again @freke for your work!
I guess we should next start discussing further features and/or how @tmrobert8 could extend the binding by "unofficial" features by an additional bundle.

@kaikreuzer kaikreuzer merged commit 216ee4d into eclipse-archived:master Nov 7, 2018
@freke
Copy link
Contributor Author

freke commented Nov 8, 2018

Thanks to you too @kaikreuzer, glad to help and assists as much as I can to @tmrobert8 openhab extension.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants