Prepare for v2.2.1 release

* Fixed issue with my position setting out of order when the flip position bit is set.
* Fixed issue with changes to the my labels when a tilt type changes.
* Fixed issue with isAtPosition method to accommodate both tilt and lift capabilities.
* Ensure target position is always the end position during movement checks.  Previously, this was only an approximation.
This commit is contained in:
Robert Strouse 2023-11-02 10:35:44 -07:00
parent 946778080c
commit 7592a2fc89
6 changed files with 53 additions and 27 deletions

View file

@ -779,7 +779,12 @@ bool SomfyGroup::hasShadeId(uint8_t shadeId) {
} }
return false; return false;
} }
bool SomfyShade::isAtTarget() { return this->currentPos == this->target && this->currentTiltPos == this->tiltTarget; } bool SomfyShade::isAtTarget() {
float epsilon = .00001;
if(this->tiltType == tilt_types::tiltonly) return fabs(this->currentTiltPos - this->tiltTarget) < epsilon;
else if(this->tiltType == tilt_types::none) return fabs(this->currentPos - this->target) < epsilon;
return fabs(this->currentPos - this->target) < epsilon && fabs(this->currentTiltPos - this->tiltTarget) < epsilon;
}
bool SomfyRemote::hasSunSensor() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::SunSensor)) > 0;} bool SomfyRemote::hasSunSensor() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::SunSensor)) > 0;}
bool SomfyRemote::hasLight() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::Light)) > 0; } bool SomfyRemote::hasLight() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::Light)) > 0; }
void SomfyRemote::setSunSensor(bool bHasSensor ) { bHasSensor ? this->flags |= static_cast<uint8_t>(somfy_flags_t::SunSensor) : this->flags &= ~(static_cast<uint8_t>(somfy_flags_t::SunSensor)); } void SomfyRemote::setSunSensor(bool bHasSensor ) { bHasSensor ? this->flags |= static_cast<uint8_t>(somfy_flags_t::SunSensor) : this->flags &= ~(static_cast<uint8_t>(somfy_flags_t::SunSensor)); }
@ -928,7 +933,7 @@ void SomfyShade::checkMovement() {
// moving. If this is only a tilt action then the regular tilt action should operate fine. // moving. If this is only a tilt action then the regular tilt action should operate fine.
int8_t currDir = this->direction; int8_t currDir = this->direction;
int8_t currTiltDir = this->tiltDirection; int8_t currTiltDir = this->tiltDirection;
this->p_direction(floor(this->currentPos) == floor(this->target) ? 0 : floor(this->currentPos) > floor(this->target) ? -1 : 1); this->p_direction(this->currentPos == this->target ? 0 : this->currentPos > this->target ? -1 : 1);
bool tilt_first = this->tiltType == tilt_types::integrated && ((this->direction == -1 && this->currentTiltPos != 0.0f) || (this->direction == 1 && this->currentTiltPos != 100.0f)); bool tilt_first = this->tiltType == tilt_types::integrated && ((this->direction == -1 && this->currentTiltPos != 0.0f) || (this->direction == 1 && this->currentTiltPos != 100.0f));
this->p_tiltDirection(this->currentTiltPos == this->tiltTarget ? 0 : this->currentTiltPos > this->tiltTarget ? -1 : 1); this->p_tiltDirection(this->currentTiltPos == this->tiltTarget ? 0 : this->currentTiltPos > this->tiltTarget ? -1 : 1);
@ -1020,6 +1025,7 @@ void SomfyShade::checkMovement() {
} }
if(this->currentPos >= this->target) { if(this->currentPos >= this->target) {
this->p_currentPos(this->target); this->p_currentPos(this->target);
//if(this->settingMyPos) Serial.printf("IsAtTarget: %d %f=%f\n", this->isAtTarget(), this->currentPos, this->target);
// If we need to stop the shade do this before we indicate that we are // If we need to stop the shade do this before we indicate that we are
// not moving otherwise the my function will kick in. // not moving otherwise the my function will kick in.
if(this->settingPos) { if(this->settingPos) {
@ -1069,6 +1075,8 @@ void SomfyShade::checkMovement() {
} }
if(this->currentPos <= this->target) { if(this->currentPos <= this->target) {
this->p_currentPos(this->target); this->p_currentPos(this->target);
//if(this->settingMyPos) Serial.printf("IsAtTarget: %d %f=%f\n", this->isAtTarget(), this->currentPos, this->target);
// If we need to stop the shade do this before we indicate that we are // If we need to stop the shade do this before we indicate that we are
// not moving otherwise the my function will kick in. // not moving otherwise the my function will kick in.
if(this->settingPos) { if(this->settingPos) {
@ -1625,6 +1633,7 @@ float SomfyShade::p_tiltTarget(float target) {
float SomfyShade::p_myPos(float pos) { float SomfyShade::p_myPos(float pos) {
float old = this->myPos; float old = this->myPos;
if(old != pos) { if(old != pos) {
//if(this->transformPosition(pos) == 0) Serial.println("MyPos = %.2f", pos);
this->myPos = pos; this->myPos = pos;
if(this->transformPosition(old) != this->transformPosition(pos)) if(this->transformPosition(old) != this->transformPosition(pos))
this->publish("mypos", this->transformPosition(this->myPos)); this->publish("mypos", this->transformPosition(this->myPos));
@ -1716,7 +1725,10 @@ void SomfyGroup::emitState(uint8_t num, const char *evt) {
else sockEmit.sendToClient(num, &e); else sockEmit.sendToClient(num, &e);
this->publish(); this->publish();
} }
int8_t SomfyShade::transformPosition(float fpos) { return static_cast<int8_t>(this->flipPosition && fpos >= 0.00f ? floor(100.0f - fpos) : floor(fpos)); } int8_t SomfyShade::transformPosition(float fpos) {
if(fpos < 0) return -1;
return static_cast<int8_t>(this->flipPosition && fpos >= 0.00f ? floor(100.0f - fpos) : floor(fpos));
}
bool SomfyShade::isIdle() { return this->direction == 0 && this->tiltDirection == 0; } bool SomfyShade::isIdle() { return this->direction == 0 && this->tiltDirection == 0; }
void SomfyShade::processWaitingFrame() { void SomfyShade::processWaitingFrame() {
if(this->shadeId == 255) { if(this->shadeId == 255) {
@ -2039,8 +2051,8 @@ void SomfyShade::processFrame(somfy_frame_t &frame, bool internal) {
if(this->lastFrame.processed) return; if(this->lastFrame.processed) return;
this->lastFrame.processed = true; this->lastFrame.processed = true;
if(!this->isIdle()) this->p_target(this->currentPos); if(!this->isIdle()) this->p_target(this->currentPos);
else if(this->currentPos == 100.0f) this->p_target(0); else if(this->currentPos == 100.0f) this->p_target(0.0f);
else if(this->currentPos == 0.0f) this->p_target(100); else if(this->currentPos == 0.0f) this->p_target(100.0f);
else this->p_target(this->lastMovement == -1 ? 100 : 0); else this->p_target(this->lastMovement == -1 ? 100 : 0);
this->emitCommand(cmd, internal ? "internal" : "remote", frame.remoteAddress); this->emitCommand(cmd, internal ? "internal" : "remote", frame.remoteAddress);
return; return;
@ -2129,6 +2141,7 @@ void SomfyShade::processFrame(somfy_frame_t &frame, bool internal) {
else if(this->currentPos == 100.0f) this->p_target(0); else if(this->currentPos == 100.0f) this->p_target(0);
else if(this->currentPos == 0.0f) this->p_target(100); else if(this->currentPos == 0.0f) this->p_target(100);
else this->p_target(this->lastMovement == -1 ? 100 : 0); else this->p_target(this->lastMovement == -1 ? 100 : 0);
this->emitCommand(cmd, internal ? "internal" : "remote", frame.remoteAddress);
break; break;
default: default:
dir = 0; dir = 0;
@ -2157,7 +2170,6 @@ void SomfyShade::processInternalCommand(somfy_commands cmd, uint8_t repeat) {
this->p_target(0.0f); this->p_target(0.0f);
} }
else if(this->tiltType == tilt_types::tiltonly) { else if(this->tiltType == tilt_types::tiltonly) {
this->p_myPos(100.0f);
this->p_target(100.0f); this->p_target(100.0f);
this->p_currentPos(100.0f); this->p_currentPos(100.0f);
this->p_tiltTarget(0.0f); this->p_tiltTarget(0.0f);
@ -2176,7 +2188,6 @@ void SomfyShade::processInternalCommand(somfy_commands cmd, uint8_t repeat) {
this->p_target(100.0f); this->p_target(100.0f);
} }
else if(this->tiltType == tilt_types::tiltonly) { else if(this->tiltType == tilt_types::tiltonly) {
this->p_myPos(100.0f);
this->p_target(100.0f); this->p_target(100.0f);
this->p_currentPos(100.0f); this->p_currentPos(100.0f);
this->p_tiltTarget(100.0f); this->p_tiltTarget(100.0f);
@ -2195,9 +2206,7 @@ void SomfyShade::processInternalCommand(somfy_commands cmd, uint8_t repeat) {
} }
else { else {
if(this->tiltType == tilt_types::tiltonly) { if(this->tiltType == tilt_types::tiltonly) {
this->p_myPos(100.0f);
this->p_target(100.0f); this->p_target(100.0f);
this->p_currentPos(100.0f);
} }
else this->p_target(this->currentPos); else this->p_target(this->currentPos);
this->p_tiltTarget(this->currentTiltPos); this->p_tiltTarget(this->currentTiltPos);
@ -2311,7 +2320,7 @@ void SomfyShade::setMovement(int8_t dir) {
void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) { void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) {
if(!this->isIdle()) return; // Don't do this if it is moving. if(!this->isIdle()) return; // Don't do this if it is moving.
if(this->tiltType == tilt_types::tiltonly) { if(this->tiltType == tilt_types::tiltonly) {
this->p_myPos(100.0f); this->p_myPos(-1.0f);
if(tilt != floor(this->currentTiltPos)) { if(tilt != floor(this->currentTiltPos)) {
this->settingMyPos = true; this->settingMyPos = true;
if(tilt == floor(this->myTiltPos)) if(tilt == floor(this->myTiltPos))
@ -2406,7 +2415,7 @@ void SomfyShade::moveToMyPosition() {
if(!this->isIdle()) return; if(!this->isIdle()) return;
if(this->tiltType == tilt_types::tiltonly) { if(this->tiltType == tilt_types::tiltonly) {
this->p_currentPos(100.0f); this->p_currentPos(100.0f);
this->p_myPos(100.0f); this->p_myPos(-1.0f);
} }
if(this->currentPos == this->myPos) { if(this->currentPos == this->myPos) {
if(this->tiltType != tilt_types::none) { if(this->tiltType != tilt_types::none) {
@ -2565,7 +2574,7 @@ void SomfyShade::moveToTarget(float pos, float tilt) {
} }
if(this->tiltType == tilt_types::tiltonly) { if(this->tiltType == tilt_types::tiltonly) {
this->p_target(100.0f); this->p_target(100.0f);
this->p_myPos(100.0f); this->p_myPos(-1.0f);
this->p_currentPos(100.0f); this->p_currentPos(100.0f);
pos = 100; pos = 100;
if(tilt < this->currentTiltPos) cmd = somfy_commands::Up; if(tilt < this->currentTiltPos) cmd = somfy_commands::Up;

Binary file not shown.

Binary file not shown.

View file

@ -3,11 +3,11 @@
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="main.css?v=2.2.0" type="text/css" /> <link rel="stylesheet" href="main.css?v=2.2.1b" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.2.0" type="text/css" /> <link rel="stylesheet" href="widgets.css?v=2.2.1b" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.2.0" type="text/css" /> <link rel="stylesheet" href="icons.css?v=2.2.1b" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="index.js?v=2.2.0"></script> <script type="text/javascript" src="index.js?v=2.2.1b"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container main" data-auth="false"> <div id="divContainer" class="container main" data-auth="false">

View file

@ -1252,7 +1252,7 @@ var security = new Security();
class General { class General {
initialized = false; initialized = false;
appVersion = 'v2.2.0'; appVersion = 'v2.2.1b';
reloadApp = false; reloadApp = false;
init() { init() {
if (this.initialized) return; if (this.initialized) return;
@ -2098,7 +2098,7 @@ class Somfy {
} }
for (let i = 0; i < shades.length; i++) { for (let i = 0; i < shades.length; i++) {
let shade = shades[i]; let shade = shades[i];
divCfg += `<div class="somfyShade shade-draggable" draggable="true" data-shadeid="${shade.shadeId}" data-remoteaddress="${shade.remoteAddress}" data-tilt="${shade.tiltType}" data-shadetype="${shade.shadeType}">`; divCfg += `<div class="somfyShade shade-draggable" draggable="true" data-mypos="${shade.myPos}" data-shadeid="${shade.shadeId}" data-remoteaddress="${shade.remoteAddress}" data-tilt="${shade.tiltType}" data-shadetype="${shade.shadeType}">`;
divCfg += `<div class="button-outline" onclick="somfy.openEditShade(${shade.shadeId});"><i class="icss-edit"></i></div>`; divCfg += `<div class="button-outline" onclick="somfy.openEditShade(${shade.shadeId});"><i class="icss-edit"></i></div>`;
//divCfg += `<i class="shade-icon" data-position="${shade.position || 0}%"></i>`; //divCfg += `<i class="shade-icon" data-position="${shade.position || 0}%"></i>`;
divCfg += `<span class="shade-name">${shade.name}</span>`; divCfg += `<span class="shade-name">${shade.name}</span>`;
@ -2106,7 +2106,7 @@ class Somfy {
divCfg += `<div class="button-outline" onclick="somfy.deleteShade(${shade.shadeId});"><i class="icss-trash"></i></div>`; divCfg += `<div class="button-outline" onclick="somfy.deleteShade(${shade.shadeId});"><i class="icss-trash"></i></div>`;
divCfg += '</div>'; divCfg += '</div>';
divCtl += `<div class="somfyShadeCtl" data-shadeId="${shade.shadeId}" data-direction="${shade.direction}" data-remoteaddress="${shade.remoteAddress}" data-position="${shade.position}" data-target="${shade.target}" data-mypos="${shade.myPos}" data-mytiltpos="${shade.myTiltPos} data-shadetype="${shade.shadeType}" data-tilt="${shade.tiltType}"`; divCtl += `<div class="somfyShadeCtl" data-shadeId="${shade.shadeId}" data-direction="${shade.direction}" data-remoteaddress="${shade.remoteAddress}" data-position="${shade.position}" data-target="${shade.target}" data-mypos="${shade.myPos}" data-mytiltpos="${shade.myTiltPos}" data-shadetype="${shade.shadeType}" data-tilt="${shade.tiltType}"`;
divCtl += ` data-windy="${(shade.flags & 0x10) === 0x10 ? 'true' : false}" data-sunny=${(shade.flags & 0x20) === 0x20 ? 'true' : 'false'}`; divCtl += ` data-windy="${(shade.flags & 0x10) === 0x10 ? 'true' : false}" data-sunny=${(shade.flags & 0x20) === 0x20 ? 'true' : 'false'}`;
if (shade.tiltType !== 0) { if (shade.tiltType !== 0) {
divCtl += ` data-tiltposition="${shade.tiltPosition}" data-tiltdirection="${shade.tiltDirection}" data-tilttarget="${shade.tiltTarget}"`; divCtl += ` data-tiltposition="${shade.tiltPosition}" data-tiltdirection="${shade.tiltDirection}" data-tilttarget="${shade.tiltTarget}"`;
@ -2149,12 +2149,7 @@ class Somfy {
divCtl += `<div class="shade-name">`; divCtl += `<div class="shade-name">`;
divCtl += `<span class="shadectl-name">${shade.name}</span>`; divCtl += `<span class="shadectl-name">${shade.name}</span>`;
if (shade.tiltType === 3) divCtl += `<span class="shadectl-mypos"><label class="my-pos"></label><span class="my-pos">${shade.myPos === -1 ? '---' : shade.myPos + '%'}</span><label class="my-pos-tilt"></label><span class="my-pos-tilt">${shade.myTiltPos === -1 ? '---' : shade.myTiltPos + '%'}</span >`;
divCtl += `<span class="shadectl-mypos"><label>My Tilt: </label><span id="spanMyTiltPos">${shade.myTiltPos > 0 ? shade.myTiltPos + '%' : '---'}</span>`
else if (shade.shadeType !== 5 && shade.shadeType !== 9) {
divCtl += `<span class="shadectl-mypos"><label>My: </label><span id="spanMyPos">${shade.myPos > 0 ? shade.myPos + '%' : '---'}</span>`;
if (shade.myTiltPos > 0 && shade.tiltType !== 3) divCtl += `<label> Tilt: </label><span id="spanMyTiltPos">${shade.myTiltPos > 0 ? shade.myTiltPos + '%' : '---'}</span>`;
}
divCtl += '</div>'; divCtl += '</div>';
divCtl += `<div class="shadectl-buttons" data-shadeType="${shade.shadeType}">`; divCtl += `<div class="shadectl-buttons" data-shadeType="${shade.shadeType}">`;
divCtl += `<div class="button-light cmd-button" data-cmd="light" data-shadeid="${shade.shadeId}" data-on="${shade.flags & 0x08 ? 'true' : 'false'}" style="${!shade.light ? 'display:none' : ''}"><i class="icss-lightbuld-c"></i><i class="icss-lightbulb-o"></i></div>`; divCtl += `<div class="button-light cmd-button" data-cmd="light" data-shadeid="${shade.shadeId}" data-on="${shade.flags & 0x08 ? 'true' : 'false'}" style="${!shade.light ? 'display:none' : ''}"><i class="icss-lightbuld-c"></i><i class="icss-lightbulb-o"></i></div>`;
@ -2701,9 +2696,9 @@ class Somfy {
divs[i].setAttribute('data-tiltposition', state.tiltPosition); divs[i].setAttribute('data-tiltposition', state.tiltPosition);
divs[i].setAttribute('data-tilttarget', state.tiltTarget); divs[i].setAttribute('data-tilttarget', state.tiltTarget);
} }
let span = divs[i].querySelector('#spanMyPos'); let span = divs[i].querySelector('span.my-pos');
if (span) span.innerHTML = typeof state.myPos !== 'undefined' && state.myPos >= 0 ? `${state.myPos}%` : '---'; if (span) span.innerHTML = typeof state.myPos !== 'undefined' && state.myPos >= 0 ? `${state.myPos}%` : '---';
span = divs[i].querySelector('#spanMyTiltPos'); span = divs[i].querySelector('span.my-pos-tilt');
if (span) span.innerHTML = typeof state.myTiltPos !== 'undefined' && state.myTiltPos >= 0 ? `${state.myTiltPos}%` : '---'; if (span) span.innerHTML = typeof state.myTiltPos !== 'undefined' && state.myTiltPos >= 0 ? `${state.myTiltPos}%` : '---';
} }
} }

View file

@ -148,6 +148,27 @@
.shadectl-buttons:not([data-shadetype="5"]):not([data-shadetype="9"]) > .button-outline[data-cmd="toggle"] { .shadectl-buttons:not([data-shadetype="5"]):not([data-shadetype="9"]) > .button-outline[data-cmd="toggle"] {
display: none; display: none;
} }
.somfyShadeCtl[data-shadetype="5"] .shadectl-mypos,
.somfyShadeCtl[data-shadetype="9"] .shadectl-mypos,
.somfyShadeCtl[data-tilt="3"] .shadectl-mypos .my-pos,
.somfyShadeCtl:not([data-shadetype="1"]) .shadectl-mypos .my-pos-tilt {
display: none;
}
.somfyShadeCtl:not([data-shadetype="1"][data-tilt="3"]) .shadectl-mypos label.my-pos:after {
content: "My:"
}
.somfyShadeCtl[data-shadetype="1"][data-tilt="3"] .shadectl-mypos label.my-pos {
display:none;
}
.somfyShadeCtl[data-shadetype="1"][data-tilt="3"] .shadectl-mypos label.my-pos-tilt:after {
content:"My Tilt:";
}
.somfyShadeCtl:not([data-shadetype="1"][data-tilt="3"]) .shadectl-mypos label.my-pos-tilt:after {
content:"Tilt:";
}
.somfyShadeCtl .shadectl-mypos span.my-pos {
margin-right:14px;
}
#somfyShade #divGPIOControl { #somfyShade #divGPIOControl {
display: none; display: none;
} }
@ -204,3 +225,4 @@
.shade-draggable.over { .shade-draggable.over {
border-top: solid 2px var(--shade-color, '#00bcd4'); border-top: solid 2px var(--shade-color, '#00bcd4');
} }