Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have the ability to use API/MQTT to change which waypoint to view #835

Open
crslen opened this issue Jun 7, 2023 · 17 comments
Open

Have the ability to use API/MQTT to change which waypoint to view #835

crslen opened this issue Jun 7, 2023 · 17 comments
Labels
enhancement New feature or request Implemented ✅ Feature has been implemented/added

Comments

@crslen
Copy link

crslen commented Jun 7, 2023

With the wyze cam pan v3 you can create up to 4 waypoints to see different views. Looking to have the ability to use API and/or MQTT to change which waypoint to view on the pan cam.

@mrlt8
Copy link
Owner

mrlt8 commented Jun 9, 2023

Does the pan_cruise command work for that?

Or would it be more like what K11012_setCruisePoints seems to be doing?

@crslen
Copy link
Author

crslen commented Jun 9, 2023

Pan Cruise will switch waypoints automatically every 10 seconds. That K11012_setCruisePoints sounds more like what I'm looking for.

mrlt8 added a commit that referenced this issue Jun 9, 2023
@mrlt8 mrlt8 added the enhancement New feature or request label Jun 9, 2023
@mrlt8
Copy link
Owner

mrlt8 commented Jun 9, 2023

This one is a little tricky because we need to send a list of positions, so it will probably need to be a json-based request. something like:

[{"vertical":"20","horizontal":"40","time":"10"},{"vertical":"20","horizontal":"120","time":"15"},{"vertical":"20","horizontal":"300","time":"10"}]

open to suggestions or ideas.

@crslen
Copy link
Author

crslen commented Jun 9, 2023

I'm using something similar to move the cameras left/right in home assistant with MQTT. If there's an option to just send the waypoint that is configured in the Wyze app that would be ideal. I'm not sure how to see what gets passed to the camera's from the app, or I would see whats happening to hopefully share more details.

mrlt8 added a commit that referenced this issue Jun 9, 2023
mrlt8 added a commit that referenced this issue Jun 9, 2023
@mrlt8
Copy link
Owner

mrlt8 commented Jun 9, 2023

hmm maybe GET cruise_points and use that with SET ptz_position?

@jhansche might have some suggestions?

mrlt8 added a commit that referenced this issue Jun 9, 2023
@crslen
Copy link
Author

crslen commented Jun 9, 2023

How do you find the commands that Wyze uses with the cameras?

@jhansche
Copy link
Contributor

hmm maybe GET cruise_points and use that with SET ptz_position?

Yeah I'm pretty sure this is how the manual waypoint selection works. I don't think it's just a "set position to waypoint 1", etc. You have to get the waypoints and then set the position. At least that's my assumption. I didn't trace what it does when doing that, but I didn't see any command that selects the waypoint by index.

@mrlt8
Copy link
Owner

mrlt8 commented Jun 10, 2023

Updated GET ptz_position and cruise_points to return a json response instead of the bytearray.

How do you find the commands that Wyze uses with the cameras?

most of the commands can be found by decompiling the wyze app and/or firmware.

mrlt8 added a commit that referenced this issue Jun 13, 2023
* SET cruise_points #835

* Don't send command if camera is disabled

* Get cruise points #835

* ptz_position #835

* GET ptz_position #835

* Return dictionary for PTZ/cruise points #835

* adjust time encoding

* Refactor encoding

* Use protocol 5 to match app

* version bump
@mrlt8
Copy link
Owner

mrlt8 commented Jun 13, 2023

This should now be available in v2.3.0. Also updated the wiki with additional info.

@mrlt8 mrlt8 added the Implemented ✅ Feature has been implemented/added label Jun 15, 2023
@a9s2w5
Copy link

a9s2w5 commented Jun 15, 2023

Just a suggestion/idea.

It would be really beneficial if the bridge had the capability to act as a proxy for standard onvif ptz commands. That is to say, in people's software of choice, they could just select onvif and the generic PTZ commands could be sent to Wyze PAN cams, the bridge acting as the intermediary. I believe the generic onvif commands look something like this.

function`` relativeMove(device, { movement, speed }) {
  return device.services.ptz
    .relativeMove({
      ProfileToken: getProfileToken(device),
      Translation: {
        x: movement.x,
        y: movement.y,
        z: movement.z,
      },
      Speed: {
        x: speed.x,
        y: speed.y,
        z: speed.z,
      },
    })
    .then(getData);
}

  .example(
    "onvif-ptz move --baseUrl=http://192.168.0.123:8080 -u=admin -p=admin -x=0.01 -y=0.02 -z=0.03"

I just quickly copied this from marklagendijk/node-onvif-ptz-cli

If it's possible to standardize them, so they could be used in other apps, that would go a long way. And I believe the Onvif protocols pretty much have standardized pretty much everything. The usefulness of this would be a big deal for many, I believe. Imagine being able to use any of the software that's out there and use some of the many functions within the bridge.

@mrlt8
Copy link
Owner

mrlt8 commented Jun 17, 2023

I believe onvif uses SOAP, however, I don't think there are any python-based onvif or soap libraries that can act as a server. Open to suggestions or ideas!

@jhansche
Copy link
Contributor

Finally getting around to testing this, and it looks useful @mrlt8. A couple notes, not sure if intentional?

  1. The REST response is a JSON object where both .response and .value contain the current set of cruise/waypoints - should we expect both of them, or is one redundant? IOW if I were going to start using one, is there one that is more likely to "survive" long term?
  2. The response is currently a string. Is that expected? I was expecting the JSON response to be parsed and available as JSON, but as it is now we only get a string, so we would have to re-parse that string after obtaining it.
  3. Not only does it have to be re-parsed, but it's not even valid JSON that can be parsed. That is, I would expect it to be in array notation, using [..] instead of just a string of comma-separated JSON object strings. This is especially odd because the documentation requires that we post a new value as JSON data, but then the response doesn't adhere to that same requirement 😞 So in other words, we should be able to GET the current value, modify one field in the JSON, and then SET that same object back - but right now that's not possible.
$ curl 'http://localhost:5000/api/pan-1/cruise_points' | json_pp
{
   "command" : "cruise_points",
   "payload" : "",
   "response" : "{'vertical': 122, 'horizontal': 242, 'time': 0, 'blank': 10},{'vertical': 145, 'horizontal': 185, 'time': 0, 'blank': 10},{'vertical': 116, 'horizontal': 122, 'time': 0, 'blank': 10}",
   "status" : "success",
   "value" : "{'vertical': 122, 'horizontal': 242, 'time': 0, 'blank': 10},{'vertical': 145, 'horizontal': 185, 'time': 0, 'blank': 10},{'vertical': 116, 'horizontal': 122, 'time': 0, 'blank': 10}"
}

Unfortunately the weirdly encoded response/value string makes it harder to work with something like the RESTful integration, or the MQTT integration where we're already getting the parsed JSON object and maybe don't have an easy way to re-parse the string after we extract it from e.g. value_json.response.

Re (2) and (3), what I was expecting would be for at least one of those 2 response fields to be fully JSON-path addressable:

{
  "command": "cruise_points",
  "payload": "",
  "status": "success",

  // Could still keep one field as a string if you want to preserve the actual response from the camera/api:
  "response": "{'vertical': 122, 'horizontal': 242, 'time': 0, 'blank': 10},.....",

  // but if one could be pre-parsed as a JSON array, it would be much more convenient to use;
  // or a new field especially for the parsed-as-json value, similar to the HA MQTT/REST synthetic "value_json" field
  "response_as_json": [
    {
      "vertical": 122,
      "horizontal": 242,
      "time": 0,
      "blank": 10
    },
    {
      "vertical": 145,
      "horizontal": 185,
      "time": 0,
      "blank": 10
    },
    {
      "vertical": 116,
      "horizontal": 122,
      "time": 0,
      "blank": 10
    }
  ]
}

This way we can address those values using value_json.response_as_json[0].vertical, etc.

This would also make it more reliable if all we want to do is, say, adjust the horizontal value for one waypoint. We could easy do that if the value is already valid JSON:

var current = value_json.response_as_json
current[1].horizontal = current[1].horizontal + 10
// POST the modified "current" object back to MQTT/REST without having to touch the rest of the data

Unrelated, but the response from my camera highlights: the wiki page says blank can be "1 or 0, typically 0"; but mine reports blank: 10. Do you know what that indicates?

@mrlt8
Copy link
Owner

mrlt8 commented Jul 17, 2023

Will try to work on this.

response is typically what the camera sends back, and value is what we try to use as the payload for the MQTT response. e.g. the camera would typically respond with a 1 for success when sending an off or 2 command, so the response would be 1 and the value would be 2 in this situation.

@jhansche
Copy link
Contributor

Obviously if it's a lot of effort then maybe it's not worth it - we can still parse the value, splitting it by },{, but then we have to fix the broken json objects then, adding back the } and {; Or use regex, like ((\{.*?\})[,]?)*, to pull out the individual objects.

More than likely though, if it's not coming back as accessible JSON, then most people would probably just ignore this command entirely, and make their own script to just set ptz_position with predefined coordinates, without taking configured cruise points into account at all 🤷‍♂️ Arguably that's probably a more sane approach anyway, it's just more convenient to use the app to nudge the camera where you want it, and then save that as a waypoint. But if we can already get the current ptz_position, we can do that without waypoints.

Or if the goal is specifically to set the camera to a specific configured waypoint (which appears to be the original ask in this ticket), a much more approachable solution would be set_ptz_waypoint(index: int) taking 0-3 or 1-4, and let the add-on do the rest, parsing the configured waypoints, extracting the coordinates, and then set ptz_position to match (or raise if OOB). I for one would not want to go through the effort to manually extract these and switch to it, but if I can just click a button and have it switch to the waypoint I want, then it may be useful.

I guess it comes down to weighing the value added vs level of effort. I can see an argument for this being not worth the effort, and an easier proposal being to configure your own HA scripts to move to exact coordinates, and don't even worry about waypoints at all.

mrlt8 added a commit that referenced this issue Jul 19, 2023
@mrlt8
Copy link
Owner

mrlt8 commented Jul 19, 2023

@jhansche Could you try out the latest dev branch? I added a SET cruise_point topic that will look up a cruise point/waypoint based on the index number from K11010GetCruisePoints then send the coordinates to K11018SetPTZPosition.

@jhansche
Copy link
Contributor

@mrlt8 It's a little slow to react (about 5.5 sec each time), but it works 👍

mrlt8 added a commit that referenced this issue Jul 20, 2023
* cache build

* Catch and disable MQTT on name resolution error

* Doorbell quick response

* Set camera time zone #916

* Set timezone on camera #916

* OSD toggle for logo/timestamp

* Add K10006 auth #742

* Fix /time_zone/get and return offset #916

* convert TZ offset to hours #916

* custom video filter #919

* Resend discovery message on HA online #907 #920

* Revert K10006 for WYZEDB3 #742

* Add more MQTT entities #921 #922

* Return json response/value for commands #835

* Fix threading issue on restart #902

* Fix SET cruise_points over MQTT

* SET cruise_point #835

* split into multiple jobs

* changelog
mrlt8 added a commit that referenced this issue Jul 24, 2023
* Start from index 1 for cruise_point/waypoint #835

* update_snapshot via MQTT

* fix camera status always online #907 #920

* Additional MQTT entities #921

* QSV related changes

* i965-va-drivers #736

* FIX power status #921

* Fix cruise_point type #921

Thanks @jhansche

* return index from command payload #921

* Update docker-image.yml

* Monitor and set preferred bitrate #929

* Default to `-` for cruise_point #921

* clear out stale entities #921

* changelog
@mtwhitley
Copy link

mtwhitley commented Mar 9, 2024

I believe onvif uses SOAP, however, I don't think there are any python-based onvif or soap libraries that can act as a server. Open to suggestions or ideas!

I know this is piggy-backing on a different topic, but I too am interested in ONVIF server support. I found this recent Python Soap Server library that I thought I’d pass along in case it would help. It might be too simple or more of a POC; I’m not sure. https://github.com/esmaily/python-soap-server

If it would be better for me to open a separate ticket for this enhancement request, I’m happy to do that. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Implemented ✅ Feature has been implemented/added
Projects
None yet
Development

No branches or pull requests

5 participants