mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-13 11:02:12 +01:00
Add dry contact support for IO Remote and Relays #165
This commit is contained in:
parent
87995bf707
commit
bb36ed0f82
9 changed files with 194 additions and 122 deletions
|
|
@ -492,6 +492,15 @@ bool EthernetSettings::toJSON(JsonObject &obj) {
|
||||||
obj["MDIOPin"] = this->MDIOPin;
|
obj["MDIOPin"] = this->MDIOPin;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool EthernetSettings::usesPin(uint8_t pin) {
|
||||||
|
if((this->CLKMode == 0 || this->CLKMode == 1) && pin == 0) return true;
|
||||||
|
else if(this->CLKMode == 2 && pin == 16) return true;
|
||||||
|
else if(this->CLKMode == 3 && pin == 17) return true;
|
||||||
|
else if(this->PWRPin == pin) return true;
|
||||||
|
else if(this->MDCPin == pin) return true;
|
||||||
|
else if(this->MDIOPin == pin) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool EthernetSettings::save() {
|
bool EthernetSettings::save() {
|
||||||
pref.begin("ETH");
|
pref.begin("ETH");
|
||||||
pref.clear();
|
pref.clear();
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ class EthernetSettings: BaseSettings {
|
||||||
bool load();
|
bool load();
|
||||||
bool save();
|
bool save();
|
||||||
void print();
|
void print();
|
||||||
|
bool usesPin(uint8_t pin);
|
||||||
};
|
};
|
||||||
class IPSettings: BaseSettings {
|
class IPSettings: BaseSettings {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
223
Somfy.cpp
223
Somfy.cpp
|
|
@ -806,24 +806,32 @@ void SomfyShade::setGPIOs() {
|
||||||
int8_t dir = this->direction;
|
int8_t dir = this->direction;
|
||||||
if(dir == 0 && this->tiltType == tilt_types::integrated)
|
if(dir == 0 && this->tiltType == tilt_types::integrated)
|
||||||
dir = this->tiltDirection;
|
dir = this->tiltDirection;
|
||||||
switch(dir) {
|
if(this->shadeType == shade_types::drycontact) {
|
||||||
case -1:
|
digitalWrite(this->gpioDown, this->currentPos == 100 ? HIGH : LOW);
|
||||||
digitalWrite(this->gpioDown, LOW);
|
this->gpioDir = this->currentPos == 100 ? 1 : -1;
|
||||||
digitalWrite(this->gpioUp, HIGH);
|
}
|
||||||
if(dir != this->gpioDir) Serial.printf("UP: true, DOWN: false\n");
|
else {
|
||||||
break;
|
switch(dir) {
|
||||||
case 1:
|
case -1:
|
||||||
digitalWrite(this->gpioUp, LOW);
|
digitalWrite(this->gpioDown, LOW);
|
||||||
digitalWrite(this->gpioDown, HIGH);
|
digitalWrite(this->gpioUp, HIGH);
|
||||||
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: true\n");
|
if(dir != this->gpioDir) Serial.printf("UP: true, DOWN: false\n");
|
||||||
break;
|
this->gpioDir = dir;
|
||||||
default:
|
break;
|
||||||
digitalWrite(this->gpioUp, LOW);
|
case 1:
|
||||||
digitalWrite(this->gpioDown, LOW);
|
digitalWrite(this->gpioUp, LOW);
|
||||||
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false\n");
|
digitalWrite(this->gpioDown, HIGH);
|
||||||
break;
|
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: true\n");
|
||||||
|
this->gpioDir = dir;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
digitalWrite(this->gpioUp, LOW);
|
||||||
|
digitalWrite(this->gpioDown, LOW);
|
||||||
|
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false\n");
|
||||||
|
this->gpioDir = dir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->gpioDir = dir;
|
|
||||||
}
|
}
|
||||||
else if(this->proto == radio_proto::GP_Remote) {
|
else if(this->proto == radio_proto::GP_Remote) {
|
||||||
if(millis() > this->gpioRelease) {
|
if(millis() > this->gpioRelease) {
|
||||||
|
|
@ -834,49 +842,62 @@ void SomfyShade::setGPIOs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SomfyRemote::triggerGPIOs(somfy_frame_t &frame) {
|
void SomfyRemote::triggerGPIOs(somfy_frame_t &frame) { }
|
||||||
|
void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
|
||||||
if(this->proto == radio_proto::GP_Remote) {
|
if(this->proto == radio_proto::GP_Remote) {
|
||||||
int8_t dir = 0;
|
int8_t dir = 0;
|
||||||
switch(frame.cmd) {
|
switch(frame.cmd) {
|
||||||
case somfy_commands::My:
|
case somfy_commands::My:
|
||||||
digitalWrite(this->gpioUp, LOW);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioDown, LOW);
|
digitalWrite(this->gpioUp, LOW);
|
||||||
digitalWrite(this->gpioMy, HIGH);
|
digitalWrite(this->gpioDown, LOW);
|
||||||
dir = 0;
|
digitalWrite(this->gpioMy, HIGH);
|
||||||
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false, MY: true\n");
|
dir = 0;
|
||||||
|
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false, MY: true\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case somfy_commands::Up:
|
case somfy_commands::Up:
|
||||||
digitalWrite(this->gpioMy, LOW);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioDown, LOW);
|
digitalWrite(this->gpioMy, LOW);
|
||||||
digitalWrite(this->gpioUp, HIGH);
|
digitalWrite(this->gpioDown, LOW);
|
||||||
dir = -1;
|
digitalWrite(this->gpioUp, HIGH);
|
||||||
Serial.printf("UP: true, DOWN: false, MY: false\n");
|
dir = -1;
|
||||||
|
Serial.printf("UP: true, DOWN: false, MY: false\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case somfy_commands::Toggle:
|
case somfy_commands::Toggle:
|
||||||
case somfy_commands::Down:
|
case somfy_commands::Down:
|
||||||
digitalWrite(this->gpioMy, LOW);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioUp, LOW);
|
digitalWrite(this->gpioMy, LOW);
|
||||||
|
digitalWrite(this->gpioUp, LOW);
|
||||||
|
}
|
||||||
digitalWrite(this->gpioDown, HIGH);
|
digitalWrite(this->gpioDown, HIGH);
|
||||||
dir = 1;
|
dir = 1;
|
||||||
Serial.printf("UP: false, DOWN: true, MY: false\n");
|
Serial.printf("UP: false, DOWN: true, MY: false\n");
|
||||||
break;
|
break;
|
||||||
case somfy_commands::MyUp:
|
case somfy_commands::MyUp:
|
||||||
digitalWrite(this->gpioDown, LOW);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioMy, HIGH);
|
digitalWrite(this->gpioDown, LOW);
|
||||||
digitalWrite(this->gpioUp, HIGH);
|
digitalWrite(this->gpioMy, HIGH);
|
||||||
Serial.printf("UP: true, DOWN: false, MY: true\n");
|
digitalWrite(this->gpioUp, HIGH);
|
||||||
|
Serial.printf("UP: true, DOWN: false, MY: true\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case somfy_commands::MyDown:
|
case somfy_commands::MyDown:
|
||||||
digitalWrite(this->gpioUp, LOW);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioMy, HIGH);
|
digitalWrite(this->gpioUp, LOW);
|
||||||
digitalWrite(this->gpioDown, HIGH);
|
digitalWrite(this->gpioMy, HIGH);
|
||||||
Serial.printf("UP: true, DOWN: false, MY: true\n");
|
digitalWrite(this->gpioDown, HIGH);
|
||||||
|
Serial.printf("UP: false, DOWN: true, MY: true\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case somfy_commands::MyUpDown:
|
case somfy_commands::MyUpDown:
|
||||||
digitalWrite(this->gpioUp, HIGH);
|
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
|
||||||
digitalWrite(this->gpioMy, HIGH);
|
digitalWrite(this->gpioUp, HIGH);
|
||||||
digitalWrite(this->gpioDown, HIGH);
|
digitalWrite(this->gpioMy, HIGH);
|
||||||
Serial.printf("UP: true, DOWN: true, MY: true\n");
|
digitalWrite(this->gpioDown, HIGH);
|
||||||
|
Serial.printf("UP: true, DOWN: true, MY: true\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->gpioRelease = millis() + (frame.repeats * 200);
|
this->gpioRelease = millis() + (frame.repeats * 200);
|
||||||
|
|
@ -2492,8 +2513,50 @@ bool SomfyShade::save() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool SomfyGroup::save() { somfy.commit(); return true; }
|
bool SomfyGroup::save() { somfy.commit(); return true; }
|
||||||
|
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) {
|
||||||
|
if(this->proto == radio_proto::GP_Relay && this->gpioUp == pin) return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(this->gpioUp == pin) return true;
|
||||||
|
else if(this->proto == radio_proto::GP_Remote && this->gpioMy == pin) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int8_t SomfyShade::validateJSON(JsonObject &obj) {
|
int8_t SomfyShade::validateJSON(JsonObject &obj) {
|
||||||
int8_t ret = 0;
|
int8_t ret = 0;
|
||||||
|
shade_types type = this->shadeType;
|
||||||
|
if(obj.containsKey("shadeType")) {
|
||||||
|
if(obj["shadeType"].is<const char *>()) {
|
||||||
|
if(strncmp(obj["shadeType"].as<const char *>(), "roller", 7) == 0)
|
||||||
|
type = shade_types::roller;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "ldrapery", 9) == 0)
|
||||||
|
type = shade_types::ldrapery;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "rdrapery", 9) == 0)
|
||||||
|
type = shade_types::rdrapery;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "cdrapery", 9) == 0)
|
||||||
|
type = shade_types::cdrapery;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "garage1", 7) == 0)
|
||||||
|
type = shade_types::garage1;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "garage3", 7) == 0)
|
||||||
|
type = shade_types::garage3;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "blind", 5) == 0)
|
||||||
|
type = shade_types::blind;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "awning", 7) == 0)
|
||||||
|
type = shade_types::awning;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "shutter", 8) == 0)
|
||||||
|
type = shade_types::shutter;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "drycontact", 11) == 0)
|
||||||
|
type = shade_types::drycontact;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->shadeType = static_cast<shade_types>(obj["shadeType"].as<uint8_t>());
|
||||||
|
}
|
||||||
|
}
|
||||||
if(obj.containsKey("proto")) {
|
if(obj.containsKey("proto")) {
|
||||||
radio_proto proto = this->proto;
|
radio_proto proto = this->proto;
|
||||||
if(proto == radio_proto::GP_Relay || proto == radio_proto::GP_Remote) {
|
if(proto == radio_proto::GP_Relay || proto == radio_proto::GP_Remote) {
|
||||||
|
|
@ -2502,63 +2565,29 @@ int8_t SomfyShade::validateJSON(JsonObject &obj) {
|
||||||
uint8_t upPin = obj.containsKey("gpioUp") ? obj["gpioUp"].as<uint8_t>() : this->gpioUp;
|
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 downPin = obj.containsKey("gpioDown") ? obj["gpioDown"].as<uint8_t>() : this->gpioDown;
|
||||||
uint8_t myPin = obj.containsKey("gpioMy") ? obj["gpioMy"].as<uint8_t>() : this->gpioMy;
|
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(proto == radio_proto::GP_Relay) myPin = 255;
|
||||||
if(somfy.transceiver.config.enabled) {
|
if(somfy.transceiver.config.enabled) {
|
||||||
if(somfy.transceiver.config.SCKPin == upPin || somfy.transceiver.config.SCKPin == downPin ||
|
if((upPin != 255 && somfy.transceiver.usesPin(upPin)) ||
|
||||||
somfy.transceiver.config.TXPin == upPin || somfy.transceiver.config.TXPin == downPin ||
|
(downPin != 255 && somfy.transceiver.usesPin(downPin)) ||
|
||||||
somfy.transceiver.config.RXPin == upPin || somfy.transceiver.config.RXPin == downPin ||
|
(myPin != 255 && somfy.transceiver.usesPin(myPin)))
|
||||||
somfy.transceiver.config.MOSIPin == upPin || somfy.transceiver.config.MOSIPin == downPin ||
|
ret = -10;
|
||||||
somfy.transceiver.config.MISOPin == upPin || somfy.transceiver.config.MISOPin == downPin ||
|
|
||||||
somfy.transceiver.config.CSNPin == upPin || somfy.transceiver.config.CSNPin == downPin)
|
|
||||||
ret = -10; // Pin in use with transceiver.
|
|
||||||
else if(proto == radio_proto::GP_Remote) {
|
|
||||||
if(somfy.transceiver.config.SCKPin == myPin ||
|
|
||||||
somfy.transceiver.config.TXPin == myPin ||
|
|
||||||
somfy.transceiver.config.RXPin == myPin ||
|
|
||||||
somfy.transceiver.config.MOSIPin == myPin ||
|
|
||||||
somfy.transceiver.config.MISOPin == myPin ||
|
|
||||||
somfy.transceiver.config.CSNPin == myPin)
|
|
||||||
ret = -10; // Pin in use with transceiver.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(settings.connType == conn_types::ethernet || settings.connType == conn_types::ethernetpref) {
|
if(settings.connType == conn_types::ethernet || settings.connType == conn_types::ethernetpref) {
|
||||||
if((settings.Ethernet.CLKMode == 0 || settings.Ethernet.CLKMode == 1) && (upPin == 0 || downPin == 0))
|
if((upPin != 255 && settings.Ethernet.usesPin(upPin)) ||
|
||||||
ret = -11; // Pin in use with ethernet.
|
(downPin != 255 && somfy.transceiver.usesPin(downPin)) ||
|
||||||
else if(proto == radio_proto::GP_Remote && ((settings.Ethernet.CLKMode == 0 || settings.Ethernet.CLKMode == 1) && myPin == 0))
|
(myPin != 255 && somfy.transceiver.usesPin(myPin)))
|
||||||
ret = -11; // Pin in use with ethernet.
|
|
||||||
else if((settings.Ethernet.CLKMode == 2 && (upPin == 16 || downPin == 16)) ||
|
|
||||||
(settings.Ethernet.CLKMode == 3 && (upPin == 17 || downPin == 17)))
|
|
||||||
ret = -11;
|
|
||||||
else if(proto == radio_proto::GP_Remote && (settings.Ethernet.CLKMode == 2 && myPin == 16 || settings.Ethernet.CLKMode == 3 && myPin == 17))
|
|
||||||
ret = -11;
|
|
||||||
else if(settings.Ethernet.PWRPin == upPin || settings.Ethernet.PWRPin == downPin ||
|
|
||||||
settings.Ethernet.MDCPin == upPin || settings.Ethernet.MDCPin == downPin ||
|
|
||||||
settings.Ethernet.MDIOPin == upPin || settings.Ethernet.MDIOPin == downPin)
|
|
||||||
ret = -11;
|
|
||||||
else if(proto == radio_proto::GP_Remote && (settings.Ethernet.PWRPin == myPin ||
|
|
||||||
settings.Ethernet.MDCPin == myPin || settings.Ethernet.MDIOPin == myPin))
|
|
||||||
ret = -11;
|
ret = -11;
|
||||||
}
|
}
|
||||||
if(ret == 0) {
|
if(ret == 0) {
|
||||||
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
|
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
|
||||||
SomfyShade *shade = &somfy.shades[i];
|
SomfyShade *shade = &somfy.shades[i];
|
||||||
if(shade->getShadeId() == this->getShadeId() || shade->getShadeId() == 255) continue;
|
if(shade->getShadeId() == this->getShadeId() || shade->getShadeId() == 255) continue;
|
||||||
if(shade->proto == radio_proto::GP_Relay || shade->proto == radio_proto::GP_Remote) {
|
if((upPin != 255 && shade->usesPin(upPin)) ||
|
||||||
if(shade->gpioUp == upPin || shade->gpioDown == upPin || shade->gpioDown == upPin || shade->gpioDown == downPin) {
|
(downPin != 255 && shade->usesPin(downPin)) ||
|
||||||
ret = -12;
|
(myPin != 255 && shade->usesPin(myPin))){
|
||||||
break;
|
ret = -12;
|
||||||
}
|
break;
|
||||||
else if(proto == radio_proto::GP_Remote && (shade->gpioUp == myPin || shade->gpioDown == myPin)) {
|
|
||||||
ret = -12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if(shade->proto == radio_proto::GP_Remote && (shade->gpioMy == upPin || shade->gpioMy == downPin)) {
|
|
||||||
ret = -12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if(shade->proto == radio_proto::GP_Remote && proto == radio_proto::GP_Remote && (shade->gpioMy == myPin)) {
|
|
||||||
ret = -12;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2600,6 +2629,8 @@ int8_t SomfyShade::fromJSON(JsonObject &obj) {
|
||||||
this->shadeType = shade_types::awning;
|
this->shadeType = shade_types::awning;
|
||||||
else if(strncmp(obj["shadeType"].as<const char *>(), "shutter", 8) == 0)
|
else if(strncmp(obj["shadeType"].as<const char *>(), "shutter", 8) == 0)
|
||||||
this->shadeType = shade_types::shutter;
|
this->shadeType = shade_types::shutter;
|
||||||
|
else if(strncmp(obj["shadeType"].as<const char *>(), "drycontact", 11) == 0)
|
||||||
|
this->shadeType = shade_types::drycontact;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this->shadeType = static_cast<shade_types>(obj["shadeType"].as<uint8_t>());
|
this->shadeType = static_cast<shade_types>(obj["shadeType"].as<uint8_t>());
|
||||||
|
|
@ -3708,6 +3739,18 @@ bool Transceiver::fromJSON(JsonObject& obj) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool Transceiver::usesPin(uint8_t pin) {
|
||||||
|
if(this->config.enabled) {
|
||||||
|
if(this->config.SCKPin == pin ||
|
||||||
|
this->config.TXPin == pin ||
|
||||||
|
this->config.RXPin == pin ||
|
||||||
|
this->config.MOSIPin == pin ||
|
||||||
|
this->config.MISOPin == pin ||
|
||||||
|
this->config.CSNPin == pin)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool Transceiver::save() {
|
bool Transceiver::save() {
|
||||||
this->config.save();
|
this->config.save();
|
||||||
this->config.apply();
|
this->config.apply();
|
||||||
|
|
|
||||||
6
Somfy.h
6
Somfy.h
|
|
@ -214,7 +214,7 @@ class SomfyRemote {
|
||||||
void repeatFrame(uint8_t repeat);
|
void repeatFrame(uint8_t repeat);
|
||||||
virtual uint16_t p_lastRollingCode(uint16_t code);
|
virtual uint16_t p_lastRollingCode(uint16_t code);
|
||||||
somfy_commands transformCommand(somfy_commands cmd);
|
somfy_commands transformCommand(somfy_commands cmd);
|
||||||
void triggerGPIOs(somfy_frame_t &frame);
|
virtual void triggerGPIOs(somfy_frame_t &frame);
|
||||||
|
|
||||||
};
|
};
|
||||||
class SomfyLinkedRemote : public SomfyRemote {
|
class SomfyLinkedRemote : public SomfyRemote {
|
||||||
|
|
@ -304,7 +304,8 @@ class SomfyShade : public SomfyRemote {
|
||||||
void clear();
|
void clear();
|
||||||
int8_t transformPosition(float fpos);
|
int8_t transformPosition(float fpos);
|
||||||
void setGPIOs();
|
void setGPIOs();
|
||||||
|
void triggerGPIOs(somfy_frame_t &frame);
|
||||||
|
bool usesPin(uint8_t pin);
|
||||||
// State Setters
|
// State Setters
|
||||||
int8_t p_direction(int8_t dir);
|
int8_t p_direction(int8_t dir);
|
||||||
int8_t p_tiltDirection(int8_t dir);
|
int8_t p_tiltDirection(int8_t dir);
|
||||||
|
|
@ -450,6 +451,7 @@ class Transceiver {
|
||||||
void endFrequencyScan();
|
void endFrequencyScan();
|
||||||
void processFrequencyScan(bool received = false);
|
void processFrequencyScan(bool received = false);
|
||||||
void emitFrequencyScan(uint8_t num = 255);
|
void emitFrequencyScan(uint8_t num = 255);
|
||||||
|
bool usesPin(uint8_t pin);
|
||||||
};
|
};
|
||||||
class SomfyShadeController {
|
class SomfyShadeController {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -293,8 +293,8 @@
|
||||||
<option value="0">RTS</option>
|
<option value="0">RTS</option>
|
||||||
<option value="1">RTW</option>
|
<option value="1">RTW</option>
|
||||||
<option value="2">RTV</option>
|
<option value="2">RTV</option>
|
||||||
<option value="8">Relay</option>
|
<option value="8">IO-Relay</option>
|
||||||
<option value="9">Remote</option>
|
<option value="9">IO-Remote</option>
|
||||||
</select>
|
</select>
|
||||||
<label for="selShadeProto">Protocol</label>
|
<label for="selShadeProto">Protocol</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -306,12 +306,12 @@
|
||||||
<label for="selShadeBitLength">Bit Length</label>
|
<label for="selShadeBitLength">Bit Length</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="divGPIOControl" class="field-group">
|
<div id="divGPIOControl" class="field-group">
|
||||||
<div class="field-group" style="">
|
<div id="divGPIOUp" class="field-group" style="">
|
||||||
<select id="selShadeGPIOUp" data-bind="gpioUp" data-datatype="int" style="width:70px;">
|
<select id="selShadeGPIOUp" data-bind="gpioUp" data-datatype="int" style="width:70px;">
|
||||||
</select>
|
</select>
|
||||||
<label for="selShadeGPIOUp">UP</label>
|
<label for="selShadeGPIOUp">UP</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group" style="">
|
<div id="divGPIODown" class="field-group" style="">
|
||||||
<select id="selShadeGPIODown" data-bind="gpioDown" data-datatype="int" style="width:70px;">
|
<select id="selShadeGPIODown" data-bind="gpioDown" data-datatype="int" style="width:70px;">
|
||||||
</select>
|
</select>
|
||||||
<label for="selShadeGPIODown">Down</label>
|
<label for="selShadeGPIODown">Down</label>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
var errors = [
|
var errors = [
|
||||||
{ code: -10, desc: "Pin setting in use for Transceiver" },
|
{ code: -10, desc: "Pin setting in use for Transceiver. Output pins cannot be re-used." },
|
||||||
{ code: -11, desc: "Pin setting in use for Ethernet Adapter" },
|
{ code: -11, desc: "Pin setting in use for Ethernet Adapter. Output pins cannot be re-used." },
|
||||||
{ code: -12, desc: "Pin setting in use on another motor" }
|
{ code: -12, desc: "Pin setting in use on another motor. Output pins cannot be re-used." }
|
||||||
]
|
]
|
||||||
document.oncontextmenu = (event) => {
|
document.oncontextmenu = (event) => {
|
||||||
if (event.target && event.target.tagName.toLowerCase() === 'input' && (event.target.type.toLowerCase() === 'text' || event.target.type.toLowerCase() === 'password'))
|
if (event.target && event.target.tagName.toLowerCase() === 'input' && (event.target.type.toLowerCase() === 'text' || event.target.type.toLowerCase() === 'password'))
|
||||||
|
|
@ -3112,15 +3112,25 @@ class Somfy {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
if (obj.proto === 8 || obj.proto === 9) {
|
if (obj.proto === 8 || obj.proto === 9) {
|
||||||
if (obj.gpioUp === obj.gpioDown) {
|
switch (obj.shadeType) {
|
||||||
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down GPIO selections must be unique.');
|
case 5: // Garage 1-button
|
||||||
valid = false;
|
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.');
|
||||||
}
|
valid = false;
|
||||||
if (obj.proto === 9) {
|
}
|
||||||
if (obj.gpioMy === obj.gpioUp || obj.gpioMy === obj.gpioDown) {
|
break;
|
||||||
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down and my GPIO selections must be unique.');
|
case 9: // Dry contact.
|
||||||
valid = false;
|
break;
|
||||||
|
default:
|
||||||
|
if (obj.gpioUp === obj.gpioDown) {
|
||||||
|
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down GPIO selections must be unique.');
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
else if (obj.proto === 9 && (obj.gpioMy === obj.gpioUp || obj.gpioMy === obj.gpioDown)) {
|
||||||
|
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down and my GPIO selections must be unique.');
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|
|
||||||
|
|
@ -167,20 +167,27 @@
|
||||||
#somfyShade[data-shadetype="6"] #divStepSettings {
|
#somfyShade[data-shadetype="6"] #divStepSettings {
|
||||||
display: none;
|
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="9"] #divGPIOUp,
|
||||||
|
#somfyShade[data-proto="9"][data-shadetype="9"] #divGPIOMy,
|
||||||
|
#somfyShade[data-proto="8"][data-shadetype="9"] #divGPIOUp {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.group-draggable,
|
.group-draggable,
|
||||||
.shade-draggable {
|
.shade-draggable {
|
||||||
height:32px;
|
height: 32px;
|
||||||
border-top:solid 2px transparent;
|
border-top: solid 2px transparent;
|
||||||
cursor:grab;
|
cursor: grab;
|
||||||
|
}
|
||||||
|
.group-draggable.dragging *,
|
||||||
|
.group-draggable.over *,
|
||||||
|
.shade-draggable.dragging *,
|
||||||
|
.shade-draggable.over * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.group-draggable.over,
|
||||||
|
.shade-draggable.over {
|
||||||
|
border-top: solid 2px var(--shade-color, '#00bcd4');
|
||||||
}
|
}
|
||||||
.group-draggable.dragging *,
|
|
||||||
.group-draggable.over *,
|
|
||||||
.shade-draggable.dragging *,
|
|
||||||
.shade-draggable.over * {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.group-draggable.over,
|
|
||||||
.shade-draggable.over {
|
|
||||||
border-top: solid 2px var(--shade-color, '#00bcd4');
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue