diff --git a/ConfigFile.cpp b/ConfigFile.cpp index d5cc863..2359e15 100644 --- a/ConfigFile.cpp +++ b/ConfigFile.cpp @@ -6,10 +6,10 @@ extern Preferences pref; -#define SHADE_HDR_VER 11 +#define SHADE_HDR_VER 12 #define SHADE_HDR_SIZE 24 -#define SHADE_REC_SIZE 248 -#define GROUP_REC_SIZE 176 +#define SHADE_REC_SIZE 252 +#define GROUP_REC_SIZE 180 bool ConfigFile::begin(const char* filename, bool readOnly) { this->file = LittleFS.open(filename, readOnly ? "r" : "w"); @@ -387,6 +387,7 @@ bool ShadeConfigFile::loadFile(SomfyShadeController *s, const char *filename) { if(this->header.version >= 10) { shade->flipPosition = this->readBool(false); } + if(this->header.version >= 12) shade->repeats = this->readUInt8(1); if(shade->getShadeId() == 255) shade->clear(); } for(uint8_t i = 0; i < this->header.groupRecords; i++) { @@ -408,7 +409,9 @@ bool ShadeConfigFile::loadFile(SomfyShadeController *s, const char *filename) { // Do this to eliminate gaps. if(shadeId > 0) group->linkedShades[lsd++] = shadeId; } - group->compressLinkedShadeIds(); + if(this->header.version >= 12) group->repeats = this->readUInt8(1); + if(group->getGroupId() == 255) group->clear(); + else group->compressLinkedShadeIds(); } pref.end(); if(opened) { @@ -425,9 +428,9 @@ bool ShadeConfigFile::writeGroupRecord(SomfyGroup *group) { this->writeUInt8(static_cast(group->proto)); this->writeUInt8(group->bitLength); for(uint8_t j = 0; j < SOMFY_MAX_GROUPED_SHADES; j++) { - if(j == SOMFY_MAX_GROUPED_SHADES - 1) this->writeUInt8(group->linkedShades[j], CFG_REC_END); - else this->writeUInt8(group->linkedShades[j]); + this->writeUInt8(group->linkedShades[j]); } + this->writeUInt8(group->repeats, CFG_REC_END); return true; } bool ShadeConfigFile::writeShadeRecord(SomfyShade *shade) { @@ -469,7 +472,8 @@ bool ShadeConfigFile::writeShadeRecord(SomfyShade *shade) { this->writeFloat(0.0f, 5); // currentTiltPos } this->writeBool(shade->flipCommands); - this->writeBool(shade->flipPosition, CFG_REC_END); + this->writeBool(shade->flipPosition); + this->writeUInt8(shade->repeats, CFG_REC_END); return true; } bool ShadeConfigFile::exists() { return LittleFS.exists("/shades.cfg"); } diff --git a/ConfigSettings.h b/ConfigSettings.h index 72bcff9..fe92f0c 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -3,7 +3,7 @@ #ifndef configsettings_h #define configsettings_h -#define FW_VERSION "v2.1.1" +#define FW_VERSION "v2.1.2" enum DeviceStatus { DS_OK = 0, DS_ERROR = 1, diff --git a/Somfy.cpp b/Somfy.cpp index ebf14db..808d14b 100644 --- a/Somfy.cpp +++ b/Somfy.cpp @@ -622,10 +622,13 @@ void SomfyShade::clear() { this->downTime = 10000; this->tiltTime = 7000; this->stepSize = 100; + this->repeats = 1; } void SomfyGroup::clear() { this->setGroupId(255); this->setRemoteAddress(0); + this->repeats = 1; + memset(&this->linkedShades[0], 0x00, sizeof(this->linkedShades)); } bool SomfyShade::linkRemote(uint32_t address, uint16_t rollingCode) { // Check to see if the remote is already linked. If it is @@ -914,13 +917,13 @@ void SomfyShade::checkMovement() { // not moving otherwise the my function will kick in. if(this->settingPos) { if(!isAtTarget()) { - if(this->target != 100.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->target != 100.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); delay(100); // We now need to move the tilt to the position we requested. this->moveToTiltTarget(this->tiltTarget); } else - if(this->target != 100.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->target != 100.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } this->direction = 0; this->tiltStart = curTime; @@ -959,13 +962,13 @@ void SomfyShade::checkMovement() { // not moving otherwise the my function will kick in. if(this->settingPos) { if(!isAtTarget()) { - if(this->target != 0.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->target != 0.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); delay(100); // We now need to move the tilt to the position we requested. this->moveToTiltTarget(this->tiltTarget); } else - if(this->target != 0.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->target != 0.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } this->direction = 0; this->tiltStart = curTime; @@ -1004,11 +1007,11 @@ void SomfyShade::checkMovement() { if(this->settingTiltPos) { if(this->tiltType == tilt_types::integrated) { // If this is an integrated tilt mechanism the we will simply let it finish. If it is not then we will stop it. - if(this->tiltTarget != 100.0 || this->currentPos != 100.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->tiltTarget != 100.0 || this->currentPos != 100.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } else { // This is a tilt motor so let it complete if it is going to 0. - if(this->tiltTarget != 100.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->tiltTarget != 100.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } } this->tiltDirection = 0; @@ -1052,11 +1055,11 @@ void SomfyShade::checkMovement() { if(this->settingTiltPos) { if(this->tiltType == tilt_types::integrated) { // If this is an integrated tilt mechanism the we will simply let it finish. If it is not then we will stop it. - if(this->tiltTarget != 0.0 || this->currentPos != 0.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->tiltTarget != 0.0 || this->currentPos != 0.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } else { // This is a tilt motor so let it complete if it is going to 0. - if(this->tiltTarget != 0.0) SomfyRemote::sendCommand(somfy_commands::My); + if(this->tiltTarget != 0.0) SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } } this->tiltDirection = 0; @@ -1824,7 +1827,7 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) { this->moveToMyPosition(); } else { - SomfyRemote::sendCommand(somfy_commands::My, 1); + SomfyRemote::sendCommand(somfy_commands::My, this->repeats); this->settingPos = false; this->settingMyPos = true; } @@ -1854,7 +1857,7 @@ void SomfyShade::setMyPosition(int8_t pos, int8_t tilt) { this->moveToMyPosition(); } else { - SomfyRemote::sendCommand(somfy_commands::My, 1); + SomfyRemote::sendCommand(somfy_commands::My, this->repeats); this->settingPos = false; this->settingMyPos = true; } @@ -1892,8 +1895,9 @@ void SomfyShade::moveToMyPosition() { if(this->myPos >= 0.0f && this->myPos <= 100.0f) this->target = this->myPos; if(this->myTiltPos >= 0.0f && this->myTiltPos <= 100.0f) this->tiltTarget = this->myTiltPos; this->settingPos = false; - SomfyRemote::sendCommand(somfy_commands::My); + SomfyRemote::sendCommand(somfy_commands::My, this->repeats); } +void SomfyShade::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); } void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat) { // This sendCommand function will always be called externally. sendCommand at the remote level // is expected to be called internally when the motor needs commanded. @@ -1923,6 +1927,7 @@ void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat) { SomfyRemote::sendCommand(cmd, repeat); } } +void SomfyGroup::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); } void SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat) { // This sendCommand function will always be called externally. sendCommand at the remote level // is expected to be called internally when the motor needs commanded. @@ -1954,15 +1959,15 @@ void SomfyGroup::sendCommand(somfy_commands cmd, uint8_t repeat) { } void SomfyShade::sendTiltCommand(somfy_commands cmd) { if(cmd == somfy_commands::Up) { - SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : 1); + SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats); this->tiltTarget = 0.0f; } else if(cmd == somfy_commands::Down) { - SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : 1); + SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats); this->tiltTarget = 100.0f; } else if(cmd == somfy_commands::My) { - SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : 1); + SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats); this->tiltTarget = this->currentTiltPos; } } @@ -1981,10 +1986,10 @@ void SomfyShade::moveToTiltTarget(float target) { Serial.print(this->currentTiltPos); Serial.print("% using "); Serial.println(translateSomfyCommand(cmd)); - SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : 1); + SomfyRemote::sendCommand(cmd, this->tiltType == tilt_types::tiltmotor ? TILT_REPEATS : this->repeats); } else - SomfyRemote::sendCommand(cmd); + SomfyRemote::sendCommand(cmd, this->repeats); } this->tiltTarget = target; } @@ -2013,7 +2018,7 @@ void SomfyShade::moveToTarget(float pos, float tilt) { } Serial.print("% using "); Serial.println(translateSomfyCommand(cmd)); - SomfyRemote::sendCommand(cmd); + SomfyRemote::sendCommand(cmd, this->repeats); this->settingPos = true; this->target = pos; if(tilt >= 0) { @@ -2084,6 +2089,7 @@ bool SomfyShade::fromJSON(JsonObject &obj) { } if(obj.containsKey("flipCommands")) this->flipCommands = obj["flipCommands"].as(); if(obj.containsKey("flipPosition")) this->flipPosition = obj["flipPosition"].as(); + if(obj.containsKey("repeats")) this->repeats = obj["repeats"]; if(obj.containsKey("tiltType")) { if(obj["tiltType"].is()) { if(strncmp(obj["tiltType"].as(), "none", 4) == 0) @@ -2124,6 +2130,7 @@ bool SomfyShade::toJSONRef(JsonObject &obj) { obj["proto"] = static_cast(this->proto); obj["flags"] = this->flags; obj["sunSensor"] = this->hasSunSensor(); + obj["repeats"] = this->repeats; SomfyRemote::toJSON(obj); return true; } @@ -2160,6 +2167,7 @@ bool SomfyShade::toJSON(JsonObject &obj) { obj["flipPosition"] = this->flipPosition; obj["inGroup"] = this->isInGroup(); obj["sunSensor"] = this->hasSunSensor(); + obj["repeats"] = this->repeats; SomfyRemote::toJSON(obj); JsonArray arr = obj.createNestedArray("linkedRemotes"); @@ -2177,7 +2185,8 @@ bool SomfyGroup::fromJSON(JsonObject &obj) { if(obj.containsKey("remoteAddress")) this->setRemoteAddress(obj["remoteAddress"]); if(obj.containsKey("bitLength")) this->bitLength = obj["bitLength"]; if(obj.containsKey("proto")) this->proto = static_cast(obj["proto"].as()); - if(obj.containsKey("sunSensor")) obj["sunSensor"] = this->hasSunSensor(); + //if(obj.containsKey("sunSensor")) this->hasSunSensor() = obj["sunSensor"]; This is calculated + if(obj.containsKey("repeats")) this->repeats = obj["repeats"]; if(obj.containsKey("linkedShades")) { uint8_t linkedShades[SOMFY_MAX_GROUPED_SHADES]; memset(linkedShades, 0x00, sizeof(linkedShades)); @@ -2199,6 +2208,7 @@ bool SomfyGroup::toJSON(JsonObject &obj) { obj["proto"] = static_cast(this->proto); obj["sunSensor"] = this->hasSunSensor(); obj["flags"] = this->flags; + obj["repeats"] = this->repeats; SomfyRemote::toJSON(obj); JsonArray arr = obj.createNestedArray("linkedShades"); for(uint8_t i = 0; i < SOMFY_MAX_GROUPED_SHADES; i++) { @@ -2440,6 +2450,7 @@ somfy_commands SomfyRemote::transformCommand(somfy_commands cmd) { } return cmd; } +void SomfyRemote::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); } void SomfyRemote::sendCommand(somfy_commands cmd, uint8_t repeat) { somfy_frame_t frame; frame.rollingCode = this->getNextRollingCode(); diff --git a/Somfy.h b/Somfy.h index 463b603..3a9214f 100644 --- a/Somfy.h +++ b/Somfy.h @@ -178,6 +178,7 @@ class SomfyRemote { bool flipCommands = false; uint8_t flags = 0; uint8_t bitLength = 0; + uint8_t repeats = 1; char *getRemotePrefId() {return m_remotePrefId;} virtual bool toJSON(JsonObject &obj); virtual void setRemoteAddress(uint32_t address); @@ -187,7 +188,8 @@ class SomfyRemote { uint16_t lastRollingCode = 0; bool hasSunSensor(); void setSunSensor(bool bHasSensor); - virtual void sendCommand(somfy_commands cmd, uint8_t repeat = 1); + virtual void sendCommand(somfy_commands cmd); + virtual void sendCommand(somfy_commands cmd, uint8_t repeat); somfy_commands transformCommand(somfy_commands cmd); }; class SomfyLinkedRemote : public SomfyRemote { @@ -255,7 +257,8 @@ class SomfyShade : public SomfyRemote { void moveToTarget(float pos, float tilt = -1.0f); void moveToTiltTarget(float target); void sendTiltCommand(somfy_commands cmd); - void sendCommand(somfy_commands cmd, uint8_t repeat = 1); + void sendCommand(somfy_commands cmd); + void sendCommand(somfy_commands cmd, uint8_t repeat); bool linkRemote(uint32_t remoteAddress, uint16_t rollingCode = 0); bool unlinkRemote(uint32_t remoteAddress); void emitState(const char *evt = "shadeState"); @@ -295,7 +298,8 @@ class SomfyGroup : public SomfyRemote { void updateFlags(); void emitState(const char *evt = "groupState"); void emitState(uint8_t num, const char *evt = "groupState"); - void sendCommand(somfy_commands cmd, uint8_t repeat = 1); + void sendCommand(somfy_commands cmd); + void sendCommand(somfy_commands cmd, uint8_t repeat); }; struct transceiver_config_t { bool printBuffer = false; diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index 4b2c395..f69571e 100644 Binary files a/SomfyController.ino.esp32.bin and b/SomfyController.ino.esp32.bin differ diff --git a/SomfyController.littlefs.bin b/SomfyController.littlefs.bin index 46375fa..754f796 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/Web.cpp b/Web.cpp index 009da9f..5863857 100644 --- a/Web.cpp +++ b/Web.cpp @@ -323,7 +323,7 @@ void Web::begin() { HTTPMethod method = apiServer.method(); uint8_t shadeId = 255; uint8_t target = 255; - uint8_t repeat = 1; + int8_t repeat = -1; somfy_commands command = somfy_commands::My; if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) { if (apiServer.hasArg("shadeId")) { @@ -373,8 +373,10 @@ void Web::begin() { // Send the command to the shade. if(target <= 100) shade->moveToTarget(shade->transformPosition(target)); - else + else if(repeat > 0) shade->sendCommand(command, repeat); + else + shade->sendCommand(command); DynamicJsonDocument sdoc(512); JsonObject sobj = sdoc.to(); shade->toJSON(sobj); @@ -390,7 +392,7 @@ void Web::begin() { if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; } HTTPMethod method = apiServer.method(); uint8_t groupId = 255; - uint8_t repeat = 1; + int8_t repeat = -1; somfy_commands command = somfy_commands::My; if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) { if (apiServer.hasArg("groupId")) { @@ -434,7 +436,8 @@ void Web::begin() { Serial.print("Received:"); Serial.println(apiServer.arg("plain")); // Send the command to the group. - group->sendCommand(command, repeat); + if(repeat != -1) group->sendCommand(command, repeat); + else group->sendCommand(command); DynamicJsonDocument sdoc(512); JsonObject sobj = sdoc.to(); group->toJSON(sobj); @@ -1068,7 +1071,7 @@ void Web::begin() { HTTPMethod method = server.method(); uint8_t shadeId = 255; uint8_t target = 255; - uint8_t repeat = 1; + int8_t repeat = -1; somfy_commands command = somfy_commands::My; if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) { if (server.hasArg("shadeId")) { @@ -1118,8 +1121,10 @@ void Web::begin() { // Send the command to the shade. if(target <= 100) shade->moveToTarget(shade->transformPosition(target)); - else + else if(repeat > 0) shade->sendCommand(command, repeat); + else + shade->sendCommand(command); DynamicJsonDocument sdoc(512); JsonObject sobj = sdoc.to(); shade->toJSON(sobj); @@ -1135,7 +1140,7 @@ void Web::begin() { if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; } HTTPMethod method = server.method(); uint8_t groupId = 255; - uint8_t repeat = 1; + int8_t repeat = -1; somfy_commands command = somfy_commands::My; if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) { if (server.hasArg("groupId")) { @@ -1179,7 +1184,8 @@ void Web::begin() { Serial.print("Received:"); Serial.println(server.arg("plain")); // Send the command to the group. - group->sendCommand(command, repeat); + if(repeat > 0) group->sendCommand(command, repeat); + else group->sendCommand(command); DynamicJsonDocument sdoc(512); JsonObject sobj = sdoc.to(); group->toJSON(sobj); diff --git a/data/appversion b/data/appversion index 7c32728..8f9174b 100644 --- a/data/appversion +++ b/data/appversion @@ -1 +1 @@ -2.1.1 \ No newline at end of file +2.1.2 \ No newline at end of file diff --git a/data/index.html b/data/index.html index 20d8c90..a0d02b7 100644 --- a/data/index.html +++ b/data/index.html @@ -3,11 +3,11 @@ - - - + + + - +
@@ -375,7 +375,7 @@
-
+
@@ -386,6 +386,24 @@
+
+ + +
+ +
+
+
+
+
+ + +
+