fix: keep a tilt-only shade's lift at 100 whatever sends the command

The web and group Up/Down put a tilt-only shade's lift back at 100, but a
remote's Up/Down/My, a group's My and the web's My while moving left a
lift that something had moved, and the simulation then ran it. Every
Up/Down/My path now pins the lift at 100 and acts on the tilt only.
Reconcile Q22 in SHADE_BEHAVIOUR_PLAN.md, which also records Q23 (the
integrated tilt turn-back) as deferred.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-16 22:47:53 +02:00
parent 7220f38fcd
commit 38d4ce5058
4 changed files with 79 additions and 56 deletions

View file

@ -450,6 +450,7 @@ void ShadeBehaviour::onWaitingFrame(uint32_t now) {
else {
if(this->s.myPos >= 0.0f && this->s.myPos <= 100.0f) this->p_target(this->s.myPos);
if(this->s.myTiltPos >= 0.0f && this->s.myTiltPos <= 100.0f) this->p_tiltTarget(this->s.myTiltPos);
this->pinTiltOnlyLift();
}
this->setMovement(0, now);
this->lastFrame.processed = true;
@ -458,6 +459,7 @@ void ShadeBehaviour::onWaitingFrame(uint32_t now) {
else {
this->p_target(this->s.currentPos);
this->p_tiltTarget(this->s.currentTiltPos);
this->pinTiltOnlyLift();
}
if(this->lastFrame.repeats > SETMY_REPEATS + 2) this->lastFrame.processed = true;
if(this->lastFrame.processed) {
@ -572,6 +574,7 @@ void ShadeBehaviour::onFrame(somfy_frame_t &frame, bool internal, uint32_t now)
}
else {
// If from a remote we will simply be going up.
this->pinTiltOnlyLift();
if(this->settings.tiltType == tilt_types::tiltonly && !internal) this->p_tiltTarget(0.0f);
else if(!internal) {
if(this->settings.tiltType != tilt_types::tiltonly) this->p_target(0.0f);
@ -601,6 +604,7 @@ void ShadeBehaviour::onFrame(somfy_frame_t &frame, bool internal, uint32_t now)
}
else {
this->lastFrame.processed = true;
this->pinTiltOnlyLift();
if(!internal) {
if(this->settings.tiltType != tilt_types::tiltonly) this->p_target(100.0f);
if(this->settings.tiltType != tilt_types::none) this->p_tiltTarget(100.0f);
@ -642,6 +646,7 @@ void ShadeBehaviour::onFrame(somfy_frame_t &frame, bool internal, uint32_t now)
if(this->lastFrame.processed) return;
ESP_LOGI(TAG, "Moving to My target");
this->lastFrame.processed = true;
this->pinTiltOnlyLift();
if(this->s.myTiltPos >= 0.0f && this->s.myTiltPos <= 100.0f) this->p_tiltTarget(this->s.myTiltPos);
if(this->s.myPos >= 0.0f && this->s.myPos <= 100.0f && this->settings.tiltType != tilt_types::tiltonly) this->p_target(this->s.myPos);
this->emitCommand(cmd, internal ? "internal" : "remote", frame.remoteAddress);
@ -650,6 +655,7 @@ void ShadeBehaviour::onFrame(somfy_frame_t &frame, bool internal, uint32_t now)
else {
if(this->lastFrame.processed) return;
this->lastFrame.processed = true;
this->pinTiltOnlyLift();
if(!internal) {
if(this->settings.tiltType != tilt_types::tiltonly) this->p_target(this->s.currentPos);
this->p_tiltTarget(this->s.currentTiltPos);
@ -767,12 +773,11 @@ void ShadeBehaviour::onGroupCommand(somfy_commands cmd, uint8_t repeat, uint32_t
else {
if(this->s.myTiltPos >= 0.0f && this->s.myTiltPos <= 100.0f) this->p_tiltTarget(this->s.myTiltPos);
if(this->s.myPos >= 0.0f && this->s.myPos <= 100.0f && this->settings.tiltType != tilt_types::tiltonly) this->p_target(this->s.myPos);
this->pinTiltOnlyLift();
}
}
else {
if(this->settings.tiltType == tilt_types::tiltonly) {
this->p_target(100.0f);
}
if(this->settings.tiltType == tilt_types::tiltonly) this->pinTiltOnlyLift();
else this->p_target(this->s.currentPos);
this->p_tiltTarget(this->s.currentTiltPos);
}
@ -895,6 +900,11 @@ bool ShadeBehaviour::sendSetMy(uint16_t delayMs, float oldPos, float oldTiltPos,
this->p_myTiltPos(oldTiltPos);
return false;
}
void ShadeBehaviour::pinTiltOnlyLift() {
if(this->settings.tiltType != tilt_types::tiltonly) return;
this->p_target(100.0f);
this->p_currentPos(100.0f);
}
void ShadeBehaviour::runToLimit(int8_t dir, bool tilt, uint32_t since) {
// The motor didn't get a stop at the target so it keeps going until its end
// limit. Carry on simulating that from where and when it should have stopped.
@ -1123,6 +1133,7 @@ bool ShadeBehaviour::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t ste
if(!this->transmit(cmd, repeat, 0, 0, false, now).sent) return false;
if(this->settings.tiltType != tilt_types::tiltonly) this->p_target(this->s.currentPos);
this->p_tiltTarget(this->s.currentTiltPos);
this->pinTiltOnlyLift();
}
}
else if(cmd == somfy_commands::Toggle) {

View file

@ -135,6 +135,8 @@ class ShadeBehaviour {
bool storeMyPosition(float pos, float tiltPos, uint32_t now);
// Repeats for a tilt command, more for a separate tilt motor.
uint8_t tiltRepeats() const;
// A tilt-only shade has no lift to move: it stays all the way down.
void pinTiltOnlyLift();
void runToLimit(int8_t dir, bool tilt, uint32_t since);
// Sets the targets the sun or wind sends the shade to.
void applySensorMove(SensorMove move);