Hunter Douglas PowerView Gen 3 integration

Fully agree.

Minor correction: I suppose if they were to declare capabilities in Swagger as an enum rather than a plain number, then they might give you a list of valid values; but unfortunately it still wouldn’t tell you what those values mean…

I’m in the same boat. I just got a Gen 3 PowerView system installed. If there are any logs/testing/debug/etc I can provide to help develop support for Gen 3, I’m happy to help!

BTW: A bunch of the other big vendors have produced drivers for the Gen3, so local control definitely seems possible today: Hunter Douglas - Control Concepts

Apropos Gen 3 hubs: I found the following link, which implies that some commercial companies have developed integrations for Gen3 hubs. The web page has an email link, and I have already emailed them asking for information about the Gen 3 API. And they have forwarded my mail to the expert in charge (who has not yet responded). I will keep you informed if I get any response.

@wbradmoore / @DocBrown can you try the following on your Gen 3 hubs and post the results?

  1. Enable Swagger on your hub: http://powerview-g3.local/gateway/swagger?enable=true
  2. Get the Swagger results: http://powerview-g3.local:3002

@andrewfg, here is the info from my Gen 3 hub:

Hope this helps,
Steve

1 Like

Hi Steve, that’s excellent thank you. I am slightly hoping though, that the data might be available in a more portable format than a 6 foot tall jpeg :slight_smile: … could you look at your browser and see if there is a way to download and save that Swagger page as a ‘YAML’ file? (perhaps the following might give some tips…)

@Kingy444 judging by @srose 's screenshot above, I think we have two errors / omissions in the capabilities table…

  1. I think we have capabilities 3 and 4 mixed up.
  2. And capabilities 10 is missing…

@srose could you also please try the following uri in your browser?

  • http://{hub-ip-address:80}/home/shades

or perhaps…

  • http://{hub-ip-address}/home/shades

@andrewfg:

Both http://{hub-ip-addrss}:80/home/shades and http://{hub-ip-addrss}/home/shades both return the same data.

Here is the /home data :

{"remotes":[{"members":[{"group":3,"_id":42,"shd_Id":13},{"_id":41,"shd_Id":9,"group":2},{"group":1,"_id":43,"shd_Id":37}],"bleName":"PR:6905","accelGlow":true,"_id":17,"v":74,"mac":"","name":"Living Room Remote"}],"modDate":{"seconds":1661403270,"nanoseconds":628828000},"automations":[{"min":30,"scene_Id":26,"days":127,"hour":0,"type":14,"bleId":126,"_id":31,"errorShd_Ids":[],"enabled":false},{"errorShd_Ids":[],"days":127,"enabled":true,"scene_Id":22,"hour":8,"min":30,"type":0,"bleId":152,"_id":30}],"scenes":[{"name":"Three Quarter Sheer","members":[{"_id":50,"pos":{"pos2":0,"pos1":7425},"shd_Id":13},{"_id":48,"pos":{"pos2":0,"pos1":7562},"shd_Id":9},{"shd_Id":37,"pos":{"pos1":7575,"pos2":0},"_id":49}],"room_Id":1,"bleId":61172,"modDate":{"seconds":1661135209,"nanoseconds":984549000},"icon":"186","_id":47,"color":"7"},{"_id":22,"icon":"54","name":"All Sheer","members":[{"pos":{"pos2":0,"pos1":10000},"_id":23,"shd_Id":9},{"shd_Id":13,"_id":24,"pos":{"pos1":10000,"pos2":0}},{"shd_Id":37,"_id":46,"pos":{"pos2":0,"pos1":10000}}],"color":"7","room_Id":1,"bleId":64879,"modDate":{"seconds":1661135082,"nanoseconds":366430000}},{"color":"7","name":"Evening","members":[{"pos":{"pos2":0,"pos1":0},"_id":45,"shd_Id":37},{"shd_Id":13,"pos":{"pos1":0,"pos2":0},"_id":28},{"shd_Id":9,"pos":{"pos2":0,"pos1":0},"_id":27}],"modDate":{"seconds":1660973271,"nanoseconds":898972000},"_id":26,"icon":"54","room_Id":1,"bleId":11187},{"modDate":{"seconds":1657912414,"nanoseconds":438369000},"color":"7","icon":"183","name":"Living Room Open","bleId":45057,"members":[{"pos":{"pos2":10000,"pos1":0},"shd_Id":37,"_id":38},{"_id":10,"shd_Id":9,"pos":{"pos1":0,"pos2":10000}},{"pos":{"pos2":10000,"pos1":0},"shd_Id":13,"_id":14}],"_id":3,"room_Id":1},{"room_Id":1,"modDate":{"seconds":1661403155,"nanoseconds":740761000},"_id":5,"bleId":45058,"name":"Living Room Closed","members":[{"_id":15,"shd_Id":13,"pos":{"pos2":0,"pos1":0}},{"pos":{"pos2":0,"pos1":0},"_id":11,"shd_Id":9},{"shd_Id":37,"pos":{"pos2":0,"pos1":0},"_id":39}],"color":"7","icon":"185"}],"owner":"xxxxxx","rooms":[{"name":"Living Room","color":"7","icon":"54","shades":[{"id":37,"type":9,"name":"TGVmdA==","ptName":"Left","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":1,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-56,"bleName":"DUE:1D9E"},{"id":9,"type":9,"name":"Q2VudGVy","ptName":"Center","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":0,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-63,"bleName":"DUE:8C67"},{"id":13,"type":9,"name":"UmlnaHQ=","ptName":"Right","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":1,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-67,"bleName":"DUE:C28C"}],"groups":[],"_id":1,"type":0}],"_schemaVersion":29,"aHome":true,"createdDate":"07-15-2022","id":"xxxxxx","modApp":"IOS: com.hunterdouglas.powerview v14303","home":{"gtwsNeedReconfig":false,"name":"xxxxx","key":"xxxxxx","tz":"America/xxxxx","power":2,"loc":{"latitude":99,"longitude":-99},"autosEnabled":true},"createdBy":"HDIT","gateways":[{"v":"3.1.398","ssid":"xxxxxx","model":"Std","aux":false,"_id":32,"name":"Home Gateway","radio1V":"3.0.39","shd_Ids":[9,37,13],"serial":"xxxxxx","ip":"192.168.2.134"}],"gHome":true}

and here is the /home/shades data

[{"id":37,"type":9,"name":"TGVmdA==","ptName":"Left","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":1,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-55,"bleName":"DUE:1D9E"},{"id":9,"type":9,"name":"Q2VudGVy","ptName":"Center","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":0,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-61,"bleName":"DUE:8C67"},{"id":13,"type":9,"name":"UmlnaHQ=","ptName":"Right","motion":null,"capabilities":7,"powerType":2,"batteryStatus":3,"roomId":1,"firmware":{"revision":3,"subRevision":0,"build":359},"positions":{"primary":1,"secondary":0,"tilt":0,"velocity":9998},"signalStrength":-66,"bleName":"DUE:C28C"}]

I’ve removed some info that is specific to my installation and replaced it with ‘xxx…xxx’.

cheers,
Steve

Hi Andrew,

I can produce an .html file, but don’t see a way to attach it. If you can point me in the right direction, I’ll forward it.

Cheers,
Steve

Yay!

@Kingy444 you can see the similarities and differences between Gen 2 and Gen 3 shades data; I think many fields are one-to-one (e.g. type, name, capabilities) but others are distinctly different (e.g. positions)

I think that the html file would not help us directly. However it is possible that somewhere close to the the top of the html code there could be a source uri; and if one were to open that uri, it might give us the yaml data.

Sorry, the html file doesn’t seem to point to anything directly.


<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Swagger UI</title>
  <link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
  <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" /><link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
  
  <style>
    html
    {
      box-sizing: border-box;
      overflow: -moz-scrollbars-vertical;
      overflow-y: scroll;
    }
    *,
    *:before,
    *:after
    {
      box-sizing: inherit;
    }

    body {
      margin:0;
      background: #fafafa;
    }
  </style>
</head>

<body>

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
  <defs>
    <symbol viewBox="0 0 20 20" id="unlocked">
      <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
    </symbol>

    <symbol viewBox="0 0 20 20" id="locked">
      <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
    </symbol>

    <symbol viewBox="0 0 20 20" id="close">
      <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
    </symbol>

    <symbol viewBox="0 0 20 20" id="large-arrow">
      <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
    </symbol>

    <symbol viewBox="0 0 20 20" id="large-arrow-down">
      <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
    </symbol>


    <symbol viewBox="0 0 24 24" id="jump-to">
      <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
    </symbol>

    <symbol viewBox="0 0 24 24" id="expand">
      <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
    </symbol>

  </defs>
</svg>

<div id="swagger-ui"></div>

<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script src="./swagger-ui-init.js"> </script>

<style>
  .swagger-ui .topbar .download-url-wrapper { display: none } undefined
</style>
</body>

</html>

The swagger-ui-init.js file seems to contain all the html for the actual display. That is a large file, that is too large to attach :frowning:

@srose / @DocBrown thank you for your detective work. If you are using the Chrome browser you may be able to get the .yaml (or .json) file as follows: in Chrome open its developer tools by pressing CTRL+SHIFT+I; select ‘disable cache’; then reload the main Swagger page; you should see something like the following; and if there is a .json or .yaml file, right click on it to download.

image

@Kingy444 the attached part of the Gen3 screenshot indicates that in Gen 1/2 we have Capabilities 3 and 4 reversed. And Capabilities 10 missing. => Any comments?

Sorry, I could not find any json or yaml. I tried several different possible URLs, but nothing returned the desired result.

Yea I saw that in th huge screenshot posted the GitHub

Hadn’t had a chance to compare to the current classes in HA but we knew we had some odd things with type 3/4 class reporting. Should probably swap them around to match the swagger.

Type 10 should be an easy one to include too assuming it takes all the same as 90 degree tilt except full rotation

It’s great to have this - be great if we could get a dump of all the shade types and their Friendly Names so we could include that (aesthetic obviously)

I saw a couple things in the git screenshot that made me think. Im hoping the new /home/shades takes the same call to update the positioning and rather than using position1/position2 it uses the primary/secondary/tilt attributes.
I was ‘worried’ about another call (don’t recall the one) that indicated position might be percentage based in v3 (which is nice) but a fair change to code implementation on our end to maintain support for all gen hubs

I concur. But we also need to change 1) the force override for types 54/55/56, and 2) the standard declaration for types 69/70/71

I concur again.

I am having a call with the developer, so can ask for this.

It seems that the JSON is slightly different on some fields. (So we would need to use a different flavour of the JSON deserializer/serializer). And as you say they have changed from ‘positions’ from having four possible elements (‘position1’, ‘posKind1’, ‘position2’, poskind2’) to four possible elements (‘primary’, ‘secondary’, ‘tilt’, ‘velocity’); not completely sure about the last one though.

Also the respective position values are now real numbers between 0.0 and 1.0 rather than integers 0…64k (resp. 0…32k).

EDIT: the Swagger page says 0.0 represents fully closed, and 1.0 represents fully open; so the coordinate reversal for TDBU shades is no longer required. (But it also says 1.0 represents fully open for tilt, and I think that must be an error for 180 degree tilt since both the 0 and the 180 degree positions are closed, and 0.5 is probably the fully open position…)

But perhaps the biggest change is that they have implemented an eventing system, so that instead of polling frequently for the shade data, you should subscribe to receive event call-backs in real time instead.

Ok. Thanks very much for trying.

Hi!

I just recently had some gen3 stuff installed and conveniently am also just now setting up home assistant for the first time today :muscle:

Building on what you all have already done (thanks so much!) I was able to get the swagger server running on my gen3 gateway, and use that to find where they were storing the json configuration. It was stuffed into a javascript variable in the file “swagger-ui-init.js”. Converted that to a JSON string, saved it, loaded it into the online swagger editor, clicked convert, and voila! Here you should fine the YAML: openapi.yaml - Google Drive :slight_smile:

Please let me know if there’s any other ways I can help here!