Skip to content

Fix PTZ preset list parsing by making Preset.command optional (#326)#406

Open
Tahutipai wants to merge 1 commit into
QuantumEntangledAndy:masterfrom
Tahutipai:fix/preset-command-optional-326
Open

Fix PTZ preset list parsing by making Preset.command optional (#326)#406
Tahutipai wants to merge 1 commit into
QuantumEntangledAndy:masterfrom
Tahutipai:fix/preset-command-optional-326

Conversation

@Tahutipai
Copy link
Copy Markdown

Summary

Fixes #326. The camera's reply to /query/ptz/preset lists saved presets with <id>, <name>, and <imageName> only — it does not include a <command> element. The current Preset struct treats command as a required field, so deserialization fails with Custom("missing field \command`"). This error cascades to Unable to parse Payload XML`, causes the camera thread to reconnect, and the ongoing PTZ command is lost. The net effect is that PTZ preset calls silently fail: the camera never moves, and the logs fill with reconnect spam.

The fix makes command default to an empty string on deserialization (#[serde(default)]) while still serializing cleanly for outbound setPos / toPos requests (skip_serializing_if = "String::is_empty").

Root cause

XML returned by the camera for /query/ptz/preset:

<preset>
  <id>0</id>
  <name>BasePoint</name>
  <imageName>preset_0</imageName>
</preset>

Current struct (crates/core/src/bc/xml.rs):

pub struct Preset {
    pub id: u8,
    pub name: Option<String>,
    pub command: String,   // required — but not in list-response XML
}

Same command field is still required when neolink sends setPos / toPos commands to the camera — those paths are unaffected.

Reproduced on

  • Reolink E1 (basic), firmware v3.2.0.4858_2508273531
  • Previously reported by PTZ preset reporting errog #326 reporter on Reolink Argus PT Ultra, firmware v3.0.0.3492_24050816

Test plan

  • Built locally (cargo build --release)
  • Deployed patched binary to running Neolink container via bind mount
  • Confirmed camera physically moves to saved presets by numeric ID via MQTT
  • Confirmed logs no longer show missing field \command`` errors or reconnect loops
  • RTSP stream unaffected (runs alongside MQTT via mqtt-rtsp mode)

…ntangledAndy#326)

This commit fixes the issue where the camera would not move to
saved PTZ preset positions. Every PTZ preset command was causing
a connection loss and reconnect loop, so the pan/tilt command
never actually reached the camera.

Root cause: the camera's reply to `/query/ptz/preset` lists saved
presets with `<id>`, `<name>`, and `<imageName>` only — no
`<command>` element. Deserializing this response into the `Preset`
struct fails with `Custom("missing field \`command\`")`, which is
escalated to `Unable to parse Payload XML`, triggering the
reconnect loop.

Reproduced on Reolink E1 (basic) with firmware
v3.2.0.4858_2508273531, and previously reported on Reolink Argus
PT Ultra in QuantumEntangledAndy#326.

`command` is still required for the outbound `setPos` / `toPos`
requests, so the field stays on the struct. Using `#[serde(default)]`
lets it default to an empty string on deserialization and
`skip_serializing_if = "String::is_empty"` keeps serialization
clean when unset. Same approach used for other optional fields
in this file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PTZ preset reporting errog

1 participant