Add support for 1 button gates #388

This commit is contained in:
Robert Strouse 2024-06-18 14:05:43 -07:00
parent c528fda55a
commit 2b59f330a9
10 changed files with 83 additions and 22 deletions

View file

@ -3,7 +3,7 @@
#ifndef configsettings_h
#define configsettings_h
#include "WResp.h"
#define FW_VERSION "v2.4.4"
#define FW_VERSION "v2.4.5"
enum class conn_types_t : byte {
unset = 0x00,
wifi = 0x01,

View file

@ -992,7 +992,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
int8_t dir = 0;
switch(frame.cmd) {
case somfy_commands::My:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
if(this->shadeType != shade_types::drycontact && !this->isToggle()) {
digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioMy, p_on);
@ -1001,7 +1001,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
}
break;
case somfy_commands::Up:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
if(this->shadeType != shade_types::drycontact && !this->isToggle() && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioMy, p_off);
digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioUp, p_on);
@ -1011,7 +1011,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
break;
case somfy_commands::Toggle:
case somfy_commands::Down:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
if(this->shadeType != shade_types::drycontact && !this->isToggle() && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioMy, p_off);
digitalWrite(this->gpioUp, p_off);
}
@ -1020,7 +1020,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
Serial.printf("UP: false, DOWN: true, MY: false\n");
break;
case somfy_commands::MyUp:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
if(this->shadeType != shade_types::drycontact && !this->isToggle() && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioUp, p_on);
@ -1028,7 +1028,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
}
break;
case somfy_commands::MyDown:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
if(this->shadeType != shade_types::drycontact && !this->isToggle() && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioDown, p_on);
@ -1036,7 +1036,7 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
}
break;
case somfy_commands::MyUpDown:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
if(this->shadeType != shade_types::drycontact && this->isToggle() && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioUp, p_on);
digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioDown, p_on);
@ -1504,6 +1504,9 @@ void SomfyShade::publishDisco() {
case shade_types::lgate:
case shade_types::cgate:
case shade_types::rgate:
case shade_types::lgate1:
case shade_types::cgate1:
case shade_types::rgate1:
case shade_types::ldrapery:
case shade_types::rdrapery:
case shade_types::cdrapery:
@ -2392,7 +2395,7 @@ void SomfyShade::processFrame(somfy_frame_t &frame, bool internal) {
break;
case somfy_commands::My:
if(this->shadeType == shade_types::drycontact2) return;
if(this->shadeType == shade_types::garage1) {
if(this->isToggle()) { // This is a one button device
if(this->lastFrame.processed) return;
this->lastFrame.processed = true;
if(!this->isIdle()) this->p_target(this->currentPos);
@ -2925,7 +2928,7 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz
}
}
else if(cmd == somfy_commands::My) {
if(this->shadeType == shade_types::garage1 || this->shadeType == shade_types::drycontact)
if(this->isToggle() || this->shadeType == shade_types::drycontact)
SomfyRemote::sendCommand(cmd, repeat);
else if(this->shadeType == shade_types::drycontact2) return;
else if(this->isIdle()) {
@ -2942,7 +2945,7 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat, uint8_t stepSiz
if(this->bitLength != 80) SomfyRemote::sendCommand(somfy_commands::My, repeat, stepSize);
else SomfyRemote::sendCommand(somfy_commands::Toggle, repeat);
}
else if(this->shadeType == shade_types::garage1 && cmd == somfy_commands::Prog) {
else if(this->isToggle() && cmd == somfy_commands::Prog) {
SomfyRemote::sendCommand(somfy_commands::Toggle, repeat, stepSize);
}
else {
@ -3024,8 +3027,8 @@ void SomfyShade::moveToTiltTarget(float target) {
}
void SomfyShade::moveToTarget(float pos, float tilt) {
somfy_commands cmd = somfy_commands::My;
if(this->shadeType == shade_types::garage1) {
// Overload this as we cannot seek a position on a garage door.
if(this->isToggle()) {
// Overload this as we cannot seek a position on a garage door or single button device.
this->p_target(pos);
this->p_currentPos(pos);
this->emitState();
@ -3107,12 +3110,24 @@ bool SomfyShade::save() {
}
bool SomfyRoom::save() { somfy.commit(); return true; }
bool SomfyGroup::save() { somfy.commit(); return true; }
bool SomfyShade::isToggle() {
switch(this->shadeType) {
case shade_types::garage1:
case shade_types::lgate1:
case shade_types::cgate1:
case shade_types::rgate1:
return true;
default:
break;
}
return false;
}
bool SomfyShade::usesPin(uint8_t pin) {
if(this->proto != radio_proto::GP_Remote && this->proto != radio_proto::GP_Relay) return false;
if(this->gpioDown == pin) return true;
else if(this->shadeType == shade_types::drycontact)
return this->gpioDown == pin;
else if(this->shadeType == shade_types::garage1) {
else if(this->isToggle()) {
if(this->proto == radio_proto::GP_Relay && this->gpioUp == pin) return true;
}
else if(this->shadeType == shade_types::drycontact2) {
@ -3164,7 +3179,9 @@ int8_t SomfyShade::validateJSON(JsonObject &obj) {
uint8_t upPin = obj.containsKey("gpioUp") ? obj["gpioUp"].as<uint8_t>() : this->gpioUp;
uint8_t downPin = obj.containsKey("gpioDown") ? obj["gpioDown"].as<uint8_t>() : this->gpioDown;
uint8_t myPin = obj.containsKey("gpioMy") ? obj["gpioMy"].as<uint8_t>() : this->gpioMy;
if(type == shade_types::drycontact || (type == shade_types::garage1 && proto == radio_proto::GP_Remote)) upPin = myPin = 255;
if(type == shade_types::drycontact ||
((type == shade_types::garage1 || type == shade_types::lgate1 || type == shade_types::cgate1 || type == shade_types::rgate1)
&& proto == radio_proto::GP_Remote)) upPin = myPin = 255;
else if(type == shade_types::drycontact2) myPin = 255;
if(proto == radio_proto::GP_Relay) myPin = 255;
if(somfy.transceiver.config.enabled) {

View file

@ -67,7 +67,10 @@ enum class shade_types : byte {
drycontact2 = 0x0A,
lgate = 0x0B,
cgate = 0x0C,
rgate = 0x0D
rgate = 0x0D,
lgate1 = 0x0E,
cgate1 = 0x0F,
rgate1 = 0x10
};
enum class tilt_types : byte {
none = 0x00,
@ -322,6 +325,7 @@ class SomfyShade : public SomfyRemote {
void setMovement(int8_t dir);
void setTarget(float target);
bool isAtTarget();
bool isToggle();
void moveToTarget(float pos, float tilt = -1.0f);
void moveToTiltTarget(float target);
void sendTiltCommand(somfy_commands cmd);

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
2.4.4
2.4.5

View file

@ -8,9 +8,9 @@
<meta name="apple-mobile-web-app-title" content="ESPSomfy RTS App">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="main.css?v=2.4.4c" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.4.4c" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.4.4c" type="text/css" />
<link rel="stylesheet" href="main.css?v=2.4.5c" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.4.5c" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.4.5c" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" />
<!-- iPad retina icon -->
@ -114,7 +114,7 @@
rel="apple-touch-startup-image">
<script type="text/javascript" src="index.js?v=2.4.4c"></script>
<script type="text/javascript" src="index.js?v=2.4.5c"></script>
</head>
<body>
<div id="divContainer" class="container main" data-auth="false">
@ -517,6 +517,10 @@
<option value="11">Gate (left)</option>
<option value="12">Gate (center)</option>
<option value="13">Gate (right)</option>
<option value="14">Gate (1-button left)</option>
<option value="15">Gate (1-button center)</option>
<option value="16">Gate (1-button right)</option>
</select>
<label for="selShadeType">Type</label>
</div>

View file

@ -1270,7 +1270,7 @@ var security = new Security();
class General {
initialized = false;
appVersion = 'v2.4.4';
appVersion = 'v2.4.5';
reloadApp = false;
init() {
if (this.initialized) return;
@ -1926,6 +1926,9 @@ class Somfy {
{ type: 11, name: 'Gate (left)', ico: 'icss-lgate', lift: true, fcmd: true, fpos: true },
{ type: 12, name: 'Gate (center)', ico: 'icss-cgate', lift: true, fcmd: true, fpos: true },
{ type: 13, name: 'Gate (right)', ico: 'icss-rgate', lift: true, fcmd: true, fpos: true },
{ type: 14, name: 'Gate (1-button left)', ico: 'icss-lgate', lift: true, fcmd: true, fpos: true },
{ type: 15, name: 'Gate (1-button center)', ico: 'icss-cgate', lift: true, fcmd: true, fpos: true },
{ type: 16, name: 'Gate (1-button right)', ico: 'icss-rgate', lift: true, fcmd: true, fpos: true },
];
init() {
if (this.initialized) return;
@ -3246,6 +3249,9 @@ class Somfy {
if (obj.proto === 8 || obj.proto === 9) {
switch (obj.shadeType) {
case 5: // Garage 1-button
case 14: // Gate left 1-button
case 15: // Gate center 1-button
case 16: // Gate right 1-button
case 10: // Two button dry contact
if (obj.proto !== 9 && obj.gpioUp === obj.gpioDown) {
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down GPIO selections must be unique.');
@ -4140,6 +4146,9 @@ class Somfy {
case 5:
case 9:
case 10:
case 14:
case 15:
case 16:
return;
}
let tiltType = parseInt(shade.getAttribute('data-tilt'), 10) || 0;

View file

@ -150,6 +150,9 @@
.shadectl-buttons div.button-outline {
display: inline-block;
}
.shadectl-buttons[data-shadetype="14"] > .cmd-button[data-cmd="sunflag"],
.shadectl-buttons[data-shadetype="15"] > .cmd-button[data-cmd="sunflag"],
.shadectl-buttons[data-shadetype="16"] > .cmd-button[data-cmd="sunflag"],
.shadectl-buttons[data-shadetype="6"] > .cmd-button[data-cmd="sunflag"],
.shadectl-buttons[data-shadetype="5"] > .cmd-button[data-cmd="sunflag"],
.shadectl-buttons[data-shadetype="9"] > .cmd-button[data-cmd="sunflag"],
@ -159,6 +162,15 @@
.shadectl-buttons[data-shadetype="5"] > .button-outline[data-cmd="my"],
.shadectl-buttons[data-shadetype="5"] > .button-outline[data-cmd="up"],
.shadectl-buttons[data-shadetype="5"] > .button-outline[data-cmd="down"],
.shadectl-buttons[data-shadetype="14"] > .button-outline[data-cmd="my"],
.shadectl-buttons[data-shadetype="14"] > .button-outline[data-cmd="up"],
.shadectl-buttons[data-shadetype="14"] > .button-outline[data-cmd="down"],
.shadectl-buttons[data-shadetype="15"] > .button-outline[data-cmd="my"],
.shadectl-buttons[data-shadetype="15"] > .button-outline[data-cmd="up"],
.shadectl-buttons[data-shadetype="15"] > .button-outline[data-cmd="down"],
.shadectl-buttons[data-shadetype="16"] > .button-outline[data-cmd="my"],
.shadectl-buttons[data-shadetype="16"] > .button-outline[data-cmd="up"],
.shadectl-buttons[data-shadetype="16"] > .button-outline[data-cmd="down"],
.shadectl-buttons[data-shadetype="10"] > .button-outline[data-cmd="my"] {
display: none;
}
@ -174,10 +186,13 @@
.shadectl-buttons[data-shadetype="10"] > .button-outline[data-cmd="down"] i {
top:.3em;
}
.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"]):not([data-shadetype="14"]):not([data-shadetype="15"]):not([data-shadetype="16"]) > .button-outline[data-cmd="toggle"] {
display: none;
}
.somfyShadeCtl[data-shadetype="5"] .shadectl-mypos,
.somfyShadeCtl[data-shadetype="14"] .shadectl-mypos,
.somfyShadeCtl[data-shadetype="15"] .shadectl-mypos,
.somfyShadeCtl[data-shadetype="16"] .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,
@ -239,12 +254,24 @@
#somfyShade[data-proto="8"] #divGPIOMy,
#somfyShade[data-bitlength="56"] #divStepSettings,
#somfyShade[data-shadetype="5"] #divStepSettings,
#somfyShade[data-shadetype="14"] #divStepSettings,
#somfyShade[data-shadetype="15"] #divStepSettings,
#somfyShade[data-shadetype="16"] #divStepSettings,
#somfyShade[data-shadetype="6"] #divStepSettings {
display: none;
}
#somfyShade[data-proto="9"][data-shadetype="5"] #divGPIOUp,
#somfyShade[data-proto="9"][data-shadetype="5"] #divGPIOMy,
#somfyShade[data-proto="8"][data-shadetype="5"] #divGPIOMy,
#somfyShade[data-proto="9"][data-shadetype="14"] #divGPIOUp,
#somfyShade[data-proto="9"][data-shadetype="14"] #divGPIOMy,
#somfyShade[data-proto="8"][data-shadetype="14"] #divGPIOMy,
#somfyShade[data-proto="9"][data-shadetype="15"] #divGPIOUp,
#somfyShade[data-proto="9"][data-shadetype="15"] #divGPIOMy,
#somfyShade[data-proto="8"][data-shadetype="15"] #divGPIOMy,
#somfyShade[data-proto="9"][data-shadetype="16"] #divGPIOUp,
#somfyShade[data-proto="9"][data-shadetype="16"] #divGPIOMy,
#somfyShade[data-proto="8"][data-shadetype="16"] #divGPIOMy,
#somfyShade[data-proto="9"][data-shadetype="9"] #divGPIOUp,
#somfyShade[data-proto="9"][data-shadetype="9"] #divGPIOMy,
#somfyShade[data-proto="8"][data-shadetype="9"] #divGPIOUp {