Added functionality to support low level triggers for GPIO types #206

This commit is contained in:
Robert Strouse 2023-12-20 09:18:45 -08:00
parent 0c36c8e746
commit c0621d82ec
9 changed files with 75 additions and 44 deletions

View file

@ -7,9 +7,9 @@
extern Preferences pref; extern Preferences pref;
#define SHADE_HDR_VER 16 #define SHADE_HDR_VER 17
#define SHADE_HDR_SIZE 56 #define SHADE_HDR_SIZE 56
#define SHADE_REC_SIZE 268 #define SHADE_REC_SIZE 272
#define GROUP_REC_SIZE 184 #define GROUP_REC_SIZE 184
#define TRANS_REC_SIZE 74 #define TRANS_REC_SIZE 74
@ -667,10 +667,10 @@ bool ShadeConfigFile::readShadeRecord(SomfyShade *shade) {
shade->gpioUp = this->readUInt8(shade->gpioUp); shade->gpioUp = this->readUInt8(shade->gpioUp);
shade->gpioDown = this->readUInt8(shade->gpioDown); shade->gpioDown = this->readUInt8(shade->gpioDown);
} }
if(this->header.version > 15) { if(this->header.version > 15)
shade->gpioMy = this->readUInt8(shade->gpioMy); shade->gpioMy = this->readUInt8(shade->gpioMy);
} if(this->header.version > 16)
shade->gpioFlags = this->readUInt8(shade->gpioFlags);
if(shade->getShadeId() == 255) shade->clear(); if(shade->getShadeId() == 255) shade->clear();
else if(shade->tiltType == tilt_types::tiltonly) { else if(shade->tiltType == tilt_types::tiltonly) {
shade->myPos = shade->currentPos = shade->target = 100.0f; shade->myPos = shade->currentPos = shade->target = 100.0f;
@ -785,7 +785,8 @@ bool ShadeConfigFile::writeShadeRecord(SomfyShade *shade) {
this->writeUInt8(shade->sortOrder); this->writeUInt8(shade->sortOrder);
this->writeUInt8(shade->gpioUp); this->writeUInt8(shade->gpioUp);
this->writeUInt8(shade->gpioDown); this->writeUInt8(shade->gpioDown);
this->writeUInt8(shade->gpioMy, CFG_REC_END); this->writeUInt8(shade->gpioMy);
this->writeUInt8(shade->gpioFlags, CFG_REC_END);
return true; return true;
} }
bool ShadeConfigFile::writeSettingsRecord() { bool ShadeConfigFile::writeSettingsRecord() {

View file

@ -3,7 +3,7 @@
#ifndef configsettings_h #ifndef configsettings_h
#define configsettings_h #define configsettings_h
#define FW_VERSION "v2.2.2c" #define FW_VERSION "v2.2.2d"
enum DeviceStatus { enum DeviceStatus {
DS_OK = 0, DS_OK = 0,
DS_ERROR = 1, DS_ERROR = 1,

View file

@ -811,43 +811,46 @@ bool SomfyShade::isInGroup() {
void SomfyShade::setGPIOs() { void SomfyShade::setGPIOs() {
if(this->proto == radio_proto::GP_Relay) { if(this->proto == radio_proto::GP_Relay) {
// Determine whether the direction needs to be set. // Determine whether the direction needs to be set.
uint8_t p_on = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? HIGH : LOW;
uint8_t p_off = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? LOW : HIGH;
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;
else if(this->tiltType == tilt_types::tiltonly) else if(this->tiltType == tilt_types::tiltonly)
dir = this->tiltDirection; dir = this->tiltDirection;
if(this->shadeType == shade_types::drycontact) { if(this->shadeType == shade_types::drycontact) {
digitalWrite(this->gpioDown, this->currentPos == 100 ? HIGH : LOW); digitalWrite(this->gpioDown, this->currentPos == 100 ? p_on : p_off);
this->gpioDir = this->currentPos == 100 ? 1 : -1; this->gpioDir = this->currentPos == 100 ? 1 : -1;
} }
else if(this->shadeType == shade_types::drycontact2) { else if(this->shadeType == shade_types::drycontact2) {
if(this->currentPos == 100) { if(this->currentPos == 100) {
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioUp, HIGH); digitalWrite(this->gpioUp, p_on);
} }
else { else {
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, HIGH); digitalWrite(this->gpioDown, p_on);
} }
this->gpioDir = this->currentPos == 100 ? 1 : -1; this->gpioDir = this->currentPos == 100 ? 1 : -1;
} }
else { else {
switch(dir) { switch(dir) {
case -1: case -1:
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioUp, HIGH); digitalWrite(this->gpioUp, p_on);
if(dir != this->gpioDir) Serial.printf("UP: true, DOWN: false\n"); if(dir != this->gpioDir) Serial.printf("UP: true, DOWN: false\n");
this->gpioDir = dir; this->gpioDir = dir;
break; break;
case 1: case 1:
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, HIGH); digitalWrite(this->gpioDown, p_on);
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: true\n"); if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: true\n");
this->gpioDir = dir; this->gpioDir = dir;
break; break;
default: default:
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false\n"); if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false\n");
this->gpioDir = dir; this->gpioDir = dir;
break; break;
@ -856,9 +859,11 @@ void SomfyShade::setGPIOs() {
} }
else if(this->proto == radio_proto::GP_Remote) { else if(this->proto == radio_proto::GP_Remote) {
if(millis() > this->gpioRelease) { if(millis() > this->gpioRelease) {
digitalWrite(this->gpioUp, LOW); uint8_t p_on = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? HIGH : LOW;
digitalWrite(this->gpioDown, LOW); uint8_t p_off = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? LOW : HIGH;
digitalWrite(this->gpioMy, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioMy, p_off);
this->gpioRelease = 0; this->gpioRelease = 0;
} }
} }
@ -866,22 +871,24 @@ void SomfyShade::setGPIOs() {
void SomfyRemote::triggerGPIOs(somfy_frame_t &frame) { } void SomfyRemote::triggerGPIOs(somfy_frame_t &frame) { }
void SomfyShade::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) {
uint8_t p_on = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? HIGH : LOW;
uint8_t p_off = this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger == 0x00 ? LOW : HIGH;
int8_t dir = 0; int8_t dir = 0;
switch(frame.cmd) { switch(frame.cmd) {
case somfy_commands::My: case somfy_commands::My:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) { if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1) {
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioMy, HIGH); digitalWrite(this->gpioMy, p_on);
dir = 0; dir = 0;
if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false, MY: true\n"); if(dir != this->gpioDir) Serial.printf("UP: false, DOWN: false, MY: true\n");
} }
break; break;
case somfy_commands::Up: 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->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioMy, LOW); digitalWrite(this->gpioMy, p_off);
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioUp, HIGH); digitalWrite(this->gpioUp, p_on);
dir = -1; dir = -1;
Serial.printf("UP: true, DOWN: false, MY: false\n"); Serial.printf("UP: true, DOWN: false, MY: false\n");
} }
@ -889,34 +896,34 @@ void SomfyShade::triggerGPIOs(somfy_frame_t &frame) {
case somfy_commands::Toggle: case somfy_commands::Toggle:
case somfy_commands::Down: 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->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioMy, LOW); digitalWrite(this->gpioMy, p_off);
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
} }
digitalWrite(this->gpioDown, HIGH); digitalWrite(this->gpioDown, p_on);
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:
if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) { if(this->shadeType != shade_types::drycontact && this->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioDown, LOW); digitalWrite(this->gpioDown, p_off);
digitalWrite(this->gpioMy, HIGH); digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioUp, HIGH); digitalWrite(this->gpioUp, p_on);
Serial.printf("UP: true, DOWN: false, MY: true\n"); Serial.printf("UP: true, DOWN: false, MY: true\n");
} }
break; break;
case somfy_commands::MyDown: 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->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioUp, LOW); digitalWrite(this->gpioUp, p_off);
digitalWrite(this->gpioMy, HIGH); digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioDown, HIGH); digitalWrite(this->gpioDown, p_on);
Serial.printf("UP: false, DOWN: true, MY: true\n"); Serial.printf("UP: false, DOWN: true, MY: true\n");
} }
break; break;
case somfy_commands::MyUpDown: 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->shadeType != shade_types::garage1 && this->shadeType != shade_types::drycontact2) {
digitalWrite(this->gpioUp, HIGH); digitalWrite(this->gpioUp, p_on);
digitalWrite(this->gpioMy, HIGH); digitalWrite(this->gpioMy, p_on);
digitalWrite(this->gpioDown, HIGH); digitalWrite(this->gpioDown, p_on);
Serial.printf("UP: true, DOWN: true, MY: true\n"); Serial.printf("UP: true, DOWN: true, MY: true\n");
} }
break; break;
@ -2777,6 +2784,9 @@ int8_t SomfyShade::fromJSON(JsonObject &obj) {
if(obj.containsKey("proto")) this->proto = static_cast<radio_proto>(obj["proto"].as<uint8_t>()); if(obj.containsKey("proto")) this->proto = static_cast<radio_proto>(obj["proto"].as<uint8_t>());
if(obj.containsKey("sunSensor")) this->setSunSensor(obj["sunSensor"]); if(obj.containsKey("sunSensor")) this->setSunSensor(obj["sunSensor"]);
if(obj.containsKey("light")) this->setLight(obj["light"]); if(obj.containsKey("light")) this->setLight(obj["light"]);
if(obj.containsKey("gpioFlags")) this->gpioFlags = obj["gpioFlags"];
if(obj.containsKey("gpioLLTrigger")) this->gpioFlags = obj["gpioLLTrigger"].as<bool>() ? this->gpioFlags |= (uint8_t)gpio_flags_t::LowLevelTrigger : this->gpioFlags &= ~(uint8_t)gpio_flags_t::LowLevelTrigger;
if(obj.containsKey("shadeType")) { if(obj.containsKey("shadeType")) {
if(obj["shadeType"].is<const char *>()) { if(obj["shadeType"].is<const char *>()) {
if(strncmp(obj["shadeType"].as<const char *>(), "roller", 7) == 0) if(strncmp(obj["shadeType"].as<const char *>(), "roller", 7) == 0)
@ -2904,6 +2914,8 @@ bool SomfyShade::toJSON(JsonObject &obj) {
obj["gpioUp"] = this->gpioUp; obj["gpioUp"] = this->gpioUp;
obj["gpioDown"] = this->gpioDown; obj["gpioDown"] = this->gpioDown;
obj["gpioMy"] = this->gpioMy; obj["gpioMy"] = this->gpioMy;
obj["gpioLLTrigger"] = ((this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger) == 0) ? false : true;
Serial.println(this->gpioFlags);
SomfyRemote::toJSON(obj); SomfyRemote::toJSON(obj);
JsonArray arr = obj.createNestedArray("linkedRemotes"); JsonArray arr = obj.createNestedArray("linkedRemotes");
for(uint8_t i = 0; i < SOMFY_MAX_LINKED_REMOTES; i++) { for(uint8_t i = 0; i < SOMFY_MAX_LINKED_REMOTES; i++) {

View file

@ -153,6 +153,9 @@ enum class somfy_flags_t : byte {
Sunny = 0x20, Sunny = 0x20,
Lighted = 0x40 Lighted = 0x40
}; };
enum class gpio_flags_t : byte {
LowLevelTrigger = 0x01
};
struct somfy_frame_t { struct somfy_frame_t {
bool valid = false; bool valid = false;
bool processed = false; bool processed = false;
@ -186,6 +189,7 @@ class SomfyRemote {
uint32_t m_remoteAddress = 0; uint32_t m_remoteAddress = 0;
public: public:
radio_proto proto = radio_proto::RTS; radio_proto proto = radio_proto::RTS;
uint8_t gpioFlags = 0;
int8_t gpioDir = 0; int8_t gpioDir = 0;
uint8_t gpioUp = 0; uint8_t gpioUp = 0;
uint8_t gpioDown = 0; uint8_t gpioDown = 0;

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.2c" type="text/css" /> <link rel="stylesheet" href="main.css?v=2.2.2d" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.2.2c" type="text/css" /> <link rel="stylesheet" href="widgets.css?v=2.2.2d" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.2.2c" type="text/css" /> <link rel="stylesheet" href="icons.css?v=2.2.2d" 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.2c"></script> <script type="text/javascript" src="index.js?v=2.2.2d"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container main" data-auth="false"> <div id="divContainer" class="container main" data-auth="false">
@ -415,6 +415,12 @@
</label> </label>
</div> </div>
</div> </div>
<div id="divLLTrigger" style="margin-top:-10px;">
<div class="field-group">
<input id="cbLLTrigger" name="hasLLTrigger" data-bind="gpioLLTrigger" type="checkbox" style="" />
<label for="cbLLTrigger" style="display:block;font-size:1em;margin-top:0px;margin-left:7px;display:inline-block;">Low Level Trigger</label>
</div>
</div>
<div id="divSunSensor" style="margin-top:-10px;"> <div id="divSunSensor" style="margin-top:-10px;">
<div class="field-group"> <div class="field-group">
<input id="cbHasSunsensor" name="hasSunSensor" data-bind="sunSensor" type="checkbox" style="" /> <input id="cbHasSunsensor" name="hasSunSensor" data-bind="sunSensor" type="checkbox" style="" />

View file

@ -1252,7 +1252,7 @@ var security = new Security();
class General { class General {
initialized = false; initialized = false;
appVersion = 'v2.2.2c'; appVersion = 'v2.2.2d';
reloadApp = false; reloadApp = false;
init() { init() {
if (this.initialized) return; if (this.initialized) return;

View file

@ -211,6 +211,14 @@
width: 70px; width: 70px;
display: inline-block; display: inline-block;
} }
#somfyShade #divLLTrigger {
display:none;
}
#somfyShade[data-proto="8"] #divLLTrigger,
#somfyShade[data-proto="9"] #divLLTrigger {
display: block;
}
#somfyShade[data-proto="8"] #divStepSettings, #somfyShade[data-proto="8"] #divStepSettings,
#somfyShade[data-proto="9"] #divStepSettings, #somfyShade[data-proto="9"] #divStepSettings,
#somfyShade[data-proto="8"] #divGPIOMy, #somfyShade[data-proto="8"] #divGPIOMy,