tuck182 / harmony-java-client

Java client for communicating with a Harmony Hub
Other
27 stars 13 forks source link

Newer Harmony Hubs have wacky IQ flows for startActivity #5

Open digitaldan opened 9 years ago

digitaldan commented 9 years ago

Hi Matt, I think the title sums this up nicely ;-)

So I have four hubs, one original, one 2nd gen and two new ones.

As a refresher, when you send an IQ packet with the startActivity payload, you receive back a series of response IQ packets with the error code "100" (continue) as each device starts up, then finally a packet with an error code of "200" which means we are done. At least on the first gen device.....

On later models this has changed. Now when you send the start activity packet, you immediately get a response with the error code of "200"..... but now 2 things happen which are screwy. First is that you still receive the series of error code "100" packets AFTER the 200 packet, still in response to the original IQ message (so same iq id). Second, the mime type changes from "vnd.logitech.harmony/vnd.logitech.harmony.engine?startactivity" to "harmony.engine?startActivity" on these packets.

The result is that the library 1) throws up on the unknown mime type and 2) it thinks the activity is done starting before it is. Because it gets the 200 so soon, it quickly sends a getCurrentActivity, which will not get a reply until the activity is truly done starting, and so the client times out.

I have some hacks to get around this, but they are hacks and probably not a great long term solution. Below is a sample XML flow.

<iq id='8bC2B-48' from='1111/main' type='get'>
  <oa xmlns="connect.logitech.com" mime="vnd.logitech.harmony/vnd.logitech.harmony.engine?startactivity">activityId=10609811:timestamp=135632</oa>
</iq>
<iq/>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='vnd.logitech.harmony/vnd.logitech.harmony.engine?startactivity' errorcode='200' errorstring='OK'></oa>
</iq>
<message content-length="635" />
<message from="HarmonyOne_Pop@qa1.com" to="ab903454-7bee-4410-9eea-bb5355bb667e">
  <event xmlns="connect.logitech.com" type="connect.stateDigest?notify">
    <![CDATA[{"sleepTimerId":-1,"contentVersion":70,"activityId":"10609811","syncStatus":0,"time":1426640265,"stateVersion":99,"tzOffset":"-25200","mode":3,"hubSwVersion":"4.3.48","tzoffset":"-25200","sequence":false,"discoveryServer":"https:\/\/svcs.myharmony.com\/Discovery\/Discovery.svc","activityStatus":1,"runningActivityList":"","tz":"PST8PDT,M3.2.0,M11.1.0","wifiStatus":1,"configVersion":76,"hubUpdate":false,"updates":{"106":"4.3.48"},"accountId":"5594045"}]]>
  </event>
</message>
<iq id='8bC2B-50' from='1111/main' type='get'>
  <oa xmlns="connect.logitech.com" mime="vnd.logitech.harmony/vnd.logitech.harmony.engine?getCurrentActivity"></oa>
</iq>
<iq/>
<iq id="8bC2B-50" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='vnd.logitech.harmony/vnd.logitech.harmony.engine?getCurrentActivity' errorcode='200' errorstring='OK'>
    <![CDATA[result=-1]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=1:total=13:deviceId=21715546]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=2:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=3:total=13:deviceId=21715547]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=4:total=13:deviceId=21715549]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=5:total=13:deviceId=21715549]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=6:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=7:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=8:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=9:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=10:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=11:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='100' errorstring='Continue'>
    <![CDATA[done=12:total=13:deviceId=21715545]]>
  </oa>
</iq>
<iq id="8bC2B-48" to="1111/main" type="get">
  <oa xmlns='connect.logitech.com' mime='harmony.engine?startActivity' errorcode='401' errorstring='Bluetooth not paired'>
    <![CDATA[done=13:total=13:deviceId=21715546]]>
  </oa>
</iq>
tuck182 commented 9 years ago

Hmm. Is it possible to detect which version you're talking to at init and modify the code flow based on that? That's probably the easiest thing to do.

digitaldan commented 9 years ago

yes, although I may be able to modify the code to support both, I'll put together a PR to look at as a starting point. One question, MessageStartActivity now has two mime types, whats your opinion on supporting this? I could create a MessageStartActivityAlt class which is basically a duplicate, we could have MessageStartActivity contain both a MIME_TYPE and MIME_TYPE_ALT string, or we could try to do some matching (like endsWith) when we match mime types to message classes?