fix: report tilt and set-My commands the radio refused

moveToTiltTarget, sendTiltCommand and setMyPosition returned nothing, so
the web command queue counted tilt_command and set_my_position as sent
and never logged a refusal.  They now return false when the radio refused
a command they sent.

No native test: these live in Somfy.cpp, which the native env can't build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-13 15:06:25 +02:00
parent f0e8b1d896
commit 45776f64ce
3 changed files with 42 additions and 37 deletions

View file

@ -2386,25 +2386,26 @@ void SomfyShade::setMovement(int8_t dir) {
this->emitState(); this->emitState();
} }
} }
void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) { bool SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
if(!this->isIdle()) return; // Don't do this if it is moving. if(!this->isIdle()) return true; // Don't do this if it is moving.
bool sent = true;
if(this->tiltType == tilt_types::tiltonly) { if(this->tiltType == tilt_types::tiltonly) {
this->p_myPos(-1.0f); this->p_myPos(-1.0f);
if(tilt != floor(this->currentTiltPos)) { if(tilt != floor(this->currentTiltPos)) {
// The favorite is set once we get there, if the move went out. // The favorite is set once we get there, if the move went out.
if(tilt == floor(this->myTiltPos)) if(tilt == floor(this->myTiltPos))
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
else else
this->settingMyPos = this->moveToTarget(100, tilt); sent = this->settingMyPos = this->moveToTarget(100, tilt);
} }
else if(tilt == floor(this->myTiltPos)) { else if(tilt == floor(this->myTiltPos)) {
// Of so we need to clear the my position. These motors are finicky so send // Of so we need to clear the my position. These motors are finicky so send
// a my command to ensure we are actually at the my position then send the clear // a my command to ensure we are actually at the my position then send the clear
// command. There really is no other way to do this. // command. There really is no other way to do this.
if(this->currentTiltPos != this->myTiltPos) { if(this->currentTiltPos != this->myTiltPos) {
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
} }
else if(SomfyRemote::sendCommand(somfy_commands::My, this->repeats)) { else if((sent = SomfyRemote::sendCommand(somfy_commands::My, this->repeats))) {
this->settingPos = false; this->settingPos = false;
this->settingMyPos = true; this->settingMyPos = true;
} }
@ -2414,9 +2415,9 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
// is only committed once the motor was told about it. // is only committed once the motor was told about it.
const float oldTiltPos = this->myTiltPos; const float oldTiltPos = this->myTiltPos;
this->p_myTiltPos(this->currentTiltPos); this->p_myTiltPos(this->currentTiltPos);
this->sendSetMy(0, this->myPos, oldTiltPos); sent = this->sendSetMy(0, this->myPos, oldTiltPos);
this->emitState(); this->emitState();
return; return sent;
} }
this->commitMyPosition(); this->commitMyPosition();
this->emitState(); this->emitState();
@ -2426,18 +2427,18 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
if(pos != floor(this->currentPos) || tilt != floor(this->currentTiltPos)) { if(pos != floor(this->currentPos) || tilt != floor(this->currentTiltPos)) {
// The favorite is set once we get there, if the move went out. // The favorite is set once we get there, if the move went out.
if(pos == floor(this->myPos) && tilt == floor(this->myTiltPos)) if(pos == floor(this->myPos) && tilt == floor(this->myTiltPos))
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
else else
this->settingMyPos = this->moveToTarget(pos, tilt); sent = this->settingMyPos = this->moveToTarget(pos, tilt);
} }
else if(pos == floor(this->myPos) && tilt == floor(this->myTiltPos)) { else if(pos == floor(this->myPos) && tilt == floor(this->myTiltPos)) {
// Of so we need to clear the my position. These motors are finicky so send // Of so we need to clear the my position. These motors are finicky so send
// a my command to ensure we are actually at the my position then send the clear // a my command to ensure we are actually at the my position then send the clear
// command. There really is no other way to do this. // command. There really is no other way to do this.
if(this->currentPos != this->myPos || this->currentTiltPos != this->myTiltPos) { if(this->currentPos != this->myPos || this->currentTiltPos != this->myTiltPos) {
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
} }
else if(SomfyRemote::sendCommand(somfy_commands::My, this->repeats)) { else if((sent = SomfyRemote::sendCommand(somfy_commands::My, this->repeats))) {
this->settingPos = false; this->settingPos = false;
this->settingMyPos = true; this->settingMyPos = true;
} }
@ -2449,9 +2450,9 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
const float oldTiltPos = this->myTiltPos; const float oldTiltPos = this->myTiltPos;
this->p_myPos(this->currentPos); this->p_myPos(this->currentPos);
this->p_myTiltPos(this->currentTiltPos); this->p_myTiltPos(this->currentTiltPos);
this->sendSetMy(0, oldPos, oldTiltPos); sent = this->sendSetMy(0, oldPos, oldTiltPos);
this->emitState(); this->emitState();
return; return sent;
} }
this->commitMyPosition(); this->commitMyPosition();
this->emitState(); this->emitState();
@ -2460,18 +2461,18 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
if(pos != floor(this->currentPos)) { if(pos != floor(this->currentPos)) {
// The favorite is set once we get there, if the move went out. // The favorite is set once we get there, if the move went out.
if(pos == floor(this->myPos)) if(pos == floor(this->myPos))
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
else else
this->settingMyPos = this->moveToTarget(pos); sent = this->settingMyPos = this->moveToTarget(pos);
} }
else if(pos == floor(this->myPos)) { else if(pos == floor(this->myPos)) {
// Of so we need to clear the my position. These motors are finicky so send // Of so we need to clear the my position. These motors are finicky so send
// a my command to ensure we are actually at the my position then send the clear // a my command to ensure we are actually at the my position then send the clear
// command. There really is no other way to do this. // command. There really is no other way to do this.
if(this->myPos != this->currentPos) { if(this->myPos != this->currentPos) {
this->settingMyPos = this->moveToMyPosition(); sent = this->settingMyPos = this->moveToMyPosition();
} }
else if(SomfyRemote::sendCommand(somfy_commands::My, this->repeats)) { else if((sent = SomfyRemote::sendCommand(somfy_commands::My, this->repeats))) {
this->settingPos = false; this->settingPos = false;
this->settingMyPos = true; this->settingMyPos = true;
} }
@ -2483,9 +2484,11 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
const float oldTiltPos = this->myTiltPos; const float oldTiltPos = this->myTiltPos;
this->p_myPos(this->currentPos); this->p_myPos(this->currentPos);
this->p_myTiltPos(-1); this->p_myTiltPos(-1);
if(this->sendSetMy(0, oldPos, oldTiltPos)) this->emitState(); sent = this->sendSetMy(0, oldPos, oldTiltPos);
if(sent) this->emitState();
} }
} }
return sent;
} }
bool SomfyShade::moveToMyPosition() { bool SomfyShade::moveToMyPosition() {
if(!this->isIdle()) return true; if(!this->isIdle()) return true;
@ -2635,19 +2638,18 @@ bool SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz
this->emitState(); this->emitState();
return true; return true;
} }
void SomfyShade::sendTiltCommand(somfy_commands cmd) { bool SomfyShade::sendTiltCommand(somfy_commands cmd) {
const uint8_t repeat = this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats; const uint8_t repeat = this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats;
if(cmd == somfy_commands::Up) { float target;
if(SomfyRemote::sendCommand(cmd, repeat)) this->p_tiltTarget(0.0f); if(cmd == somfy_commands::Up) target = 0.0f;
} else if(cmd == somfy_commands::Down) target = 100.0f;
else if(cmd == somfy_commands::Down) { else if(cmd == somfy_commands::My) target = this->currentTiltPos;
if(SomfyRemote::sendCommand(cmd, repeat)) this->p_tiltTarget(100.0f); else return true;
} if(!SomfyRemote::sendCommand(cmd, repeat)) return false;
else if(cmd == somfy_commands::My) { this->p_tiltTarget(target);
if(SomfyRemote::sendCommand(cmd, repeat)) this->p_tiltTarget(this->currentTiltPos); return true;
}
} }
void SomfyShade::moveToTiltTarget(float target) { bool SomfyShade::moveToTiltTarget(float target) {
somfy_commands cmd = somfy_commands::My; somfy_commands cmd = somfy_commands::My;
if(target < this->currentTiltPos) if(target < this->currentTiltPos)
cmd = somfy_commands::Up; cmd = somfy_commands::Up;
@ -2659,7 +2661,7 @@ void SomfyShade::moveToTiltTarget(float target) {
if(cmd != somfy_commands::My) { if(cmd != somfy_commands::My) {
ESP_LOGI(TAG, "Moving Tilt to %.2f%% from %.2f%% using %s", ESP_LOGI(TAG, "Moving Tilt to %.2f%% from %.2f%% using %s",
target, this->currentTiltPos, translateSomfyCommand(cmd).c_str()); target, this->currentTiltPos, translateSomfyCommand(cmd).c_str());
if(!SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats)) return; if(!SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats)) return false;
} }
// If the blind is currently moving then the command to stop it // If the blind is currently moving then the command to stop it
// will occur on its own when the tilt target is set. // will occur on its own when the tilt target is set.
@ -2667,6 +2669,7 @@ void SomfyShade::moveToTiltTarget(float target) {
this->p_tiltTarget(target); this->p_tiltTarget(target);
} }
if(cmd != somfy_commands::My) this->settingTiltPos = true; if(cmd != somfy_commands::My) this->settingTiltPos = true;
return true;
} }
bool SomfyShade::moveToTarget(float pos, float tilt) { bool SomfyShade::moveToTarget(float pos, float tilt) {
ESP_LOGI(TAG, "[Shade %u] moveToTarget(pos=%.2f, tilt=%.2f) settingPos=%d direction=%d currentTarget=%.2f currentPos=%.2f", ESP_LOGI(TAG, "[Shade %u] moveToTarget(pos=%.2f, tilt=%.2f) settingPos=%d direction=%d currentTarget=%.2f currentPos=%.2f",

View file

@ -263,8 +263,9 @@ class SomfyShade : public SomfyRemote {
bool isAtTarget(); bool isAtTarget();
bool isToggle(); bool isToggle();
bool moveToTarget(float pos, float tilt = -1.0f); bool moveToTarget(float pos, float tilt = -1.0f);
void moveToTiltTarget(float target); // These return false when the radio refused a command they sent.
void sendTiltCommand(somfy_commands cmd); bool moveToTiltTarget(float target);
bool sendTiltCommand(somfy_commands cmd);
bool sendCommand(somfy_commands cmd); bool sendCommand(somfy_commands cmd);
bool sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize = 0); bool sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSize = 0);
bool linkRemote(uint32_t remoteAddress, uint16_t rollingCode = 0); bool linkRemote(uint32_t remoteAddress, uint16_t rollingCode = 0);
@ -273,7 +274,8 @@ class SomfyShade : public SomfyRemote {
void emitState(uint8_t num, const char *evt = "shadeState"); void emitState(uint8_t num, const char *evt = "shadeState");
void emitCommand(somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt = "shadeCommand"); void emitCommand(somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt = "shadeCommand");
void emitCommand(uint8_t num, somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt = "shadeCommand"); void emitCommand(uint8_t num, somfy_commands cmd, const char *source, uint32_t sourceAddress, const char *evt = "shadeCommand");
void setMyPosition(int8_t pos, int8_t tilt = -1); // False when the radio refused a command it sent.
bool setMyPosition(int8_t pos, int8_t tilt = -1);
bool moveToMyPosition(); bool moveToMyPosition();
void processWaitingFrame(); void processWaitingFrame();
void publish(); void publish();

View file

@ -160,8 +160,8 @@ void Web::processQueue() {
case web_cmd_t::tilt_command: { case web_cmd_t::tilt_command: {
SomfyShade *shade = somfy.getShadeById(cmd.shadeId); SomfyShade *shade = somfy.getShadeById(cmd.shadeId);
if(shade) { if(shade) {
if(cmd.target <= 100) shade->moveToTiltTarget(shade->transformPosition(cmd.target)); if(cmd.target <= 100) sent = shade->moveToTiltTarget(shade->transformPosition(cmd.target));
else shade->sendTiltCommand(cmd.command); else sent = shade->sendTiltCommand(cmd.command);
} }
break; break;
} }
@ -209,7 +209,7 @@ void Web::processQueue() {
} }
case web_cmd_t::set_my_position: { case web_cmd_t::set_my_position: {
SomfyShade *shade = somfy.getShadeById(cmd.shadeId); SomfyShade *shade = somfy.getShadeById(cmd.shadeId);
if(shade) shade->setMyPosition(cmd.position, cmd.tiltPosition); if(shade) sent = shade->setMyPosition(cmd.position, cmd.tiltPosition);
break; break;
} }
case web_cmd_t::unpair_shade: { case web_cmd_t::unpair_shade: {