Added shutter motor type and extended frequency range #77

This commit is contained in:
Robert Strouse 2023-06-25 08:48:36 -07:00
parent 415fec020e
commit e54621f171
10 changed files with 90 additions and 19 deletions

View file

@ -3,7 +3,7 @@
#ifndef configsettings_h
#define configsettings_h
#define FW_VERSION "v1.7.2"
#define FW_VERSION "v1.7.3"
enum DeviceStatus {
DS_OK = 0,
DS_ERROR = 1,

View file

@ -652,6 +652,10 @@ void SomfyShade::checkMovement() {
const bool sunFlag = this->flags & static_cast<uint8_t>(somfy_flags_t::SunFlag);
const bool isSunny = this->flags & static_cast<uint8_t>(somfy_flags_t::Sunny);
const bool isWindy = this->flags & static_cast<uint8_t>(somfy_flags_t::Windy);
// We need to first evaluate the sensor flags as these could be triggering movement from previous sensor inputs. So
// we must check this before setting the directional items or it will not get processed until the next loop.
// We are checking movement for essentially 3 types of motors.
// If this is an integrated tilt we need to first tilt in the direction we are moving then move. We know
@ -670,10 +674,8 @@ void SomfyShade::checkMovement() {
uint8_t currPos = floor(this->currentPos);
uint8_t currTiltPos = floor(this->currentTiltPos);
if (sunFlag)
{
if (isSunny && !isWindy)
{
if (sunFlag) {
if (isSunny && !isWindy) { // It is sunny and there is no wind so we should be extended
if (this->noWindDone
&& !this->sunDone
&& this->sunStart
@ -681,21 +683,17 @@ void SomfyShade::checkMovement() {
{
this->target = this->myPos >= 0 ? this->myPos : 100.0f;
this->sunDone = true;
Serial.printf("[%u] Sun -> done\r\n", this->shadeId);
}
if (!this->noWindDone
&& this->noWindStart
&& (curTime - this->noWindStart) >= SOMFY_NO_WIND_TIMEOUT)
{
this->target = 100.0f;
this->target = this->myPos >= 0 ? this->myPos : 100.0f;
this->noWindDone = true;
Serial.printf("[%u] No Wind -> done\r\n", this->shadeId);
}
}
if (!isSunny
&& !this->noSunDone
&& this->noSunStart
@ -703,7 +701,6 @@ void SomfyShade::checkMovement() {
{
this->target = 0.0f;
this->noSunDone = true;
Serial.printf("[%u] No Sun -> done\r\n", this->shadeId);
}
}
@ -715,7 +712,6 @@ void SomfyShade::checkMovement() {
{
this->target = 0.0f;
this->windDone = true;
Serial.printf("[%u] Wind -> done\r\n", this->shadeId);
}

View file

@ -48,6 +48,7 @@ enum class shade_types : byte {
blind = 0x01,
drapery = 0x02,
awning = 0x03,
shutter = 0x04
};
enum class tilt_types : byte {
none = 0x00,

Binary file not shown.

Binary file not shown.

27
Web.cpp
View file

@ -480,6 +480,7 @@ void Web::begin() {
server.send(200, _encoding_json, g_content);
});
server.on("/addShade", []() {
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
SomfyShade* shade = nullptr;
if (method == HTTP_POST || method == HTTP_PUT) {
@ -536,6 +537,7 @@ void Web::begin() {
});
server.on("/shade", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_GET) {
if (server.hasArg("shadeId")) {
@ -596,6 +598,7 @@ void Web::begin() {
});
server.on("/saveShade", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_PUT || method == HTTP_POST) {
// We are updating an existing shade.
@ -639,6 +642,7 @@ void Web::begin() {
});
server.on("/tiltCommand", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
uint8_t shadeId = 255;
uint8_t target = 255;
@ -703,6 +707,7 @@ void Web::begin() {
});
server.on("/shadeCommand", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
uint8_t shadeId = 255;
uint8_t target = 255;
@ -770,6 +775,7 @@ void Web::begin() {
});
server.on("/setMyPosition", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
uint8_t shadeId = 255;
int8_t pos = -1;
@ -826,6 +832,7 @@ void Web::begin() {
});
server.on("/setRollingCode", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_PUT || method == HTTP_POST) {
uint8_t shadeId = 255;
@ -874,6 +881,7 @@ void Web::begin() {
});
server.on("/setPaired", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
uint8_t shadeId = 255;
bool paired = false;
if(server.hasArg("plain")) {
@ -919,6 +927,7 @@ void Web::begin() {
});
server.on("/unpairShade", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_PUT || method == HTTP_POST) {
uint8_t shadeId = 255;
@ -1014,6 +1023,7 @@ void Web::begin() {
});
server.on("/linkRemote", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_PUT || method == HTTP_POST) {
// We are updating an existing shade by adding a linked remote.
@ -1062,6 +1072,7 @@ void Web::begin() {
});
server.on("/deleteShade", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
uint8_t shadeId = 255;
if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) {
@ -1102,6 +1113,7 @@ void Web::begin() {
});
server.on("/updateFirmware", HTTP_POST, []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
if (Update.hasError())
server.send(500, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Error updating firmware: \"}");
else
@ -1133,6 +1145,7 @@ void Web::begin() {
});
server.on("/updateShadeConfig", HTTP_POST, []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
server.sendHeader("Connection", "close");
server.send(200, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Updating Shade Config: \"}");
}, []() {
@ -1156,6 +1169,7 @@ void Web::begin() {
});
server.on("/updateApplication", HTTP_POST, []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
server.sendHeader("Connection", "close");
server.send(200, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Updating Application: \"}");
rebootDelay.reboot = true;
@ -1222,6 +1236,7 @@ void Web::begin() {
});
server.on("/reboot", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_POST || method == HTTP_PUT) {
Serial.println("Rebooting ESP...");
@ -1235,6 +1250,7 @@ void Web::begin() {
});
server.on("/saveRadio", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) {
@ -1271,6 +1287,7 @@ void Web::begin() {
});
server.on("/sendRemoteCommand", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
HTTPMethod method = server.method();
if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) {
somfy_frame_t frame;
@ -1320,7 +1337,12 @@ void Web::begin() {
});
server.on("/setgeneral", []() {
webServer.sendCORSHeaders();
DynamicJsonDocument doc(256);
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
DynamicJsonDocument doc(512);
Serial.print("Plain: ");
Serial.print(server.method());
Serial.println(server.arg("plain"));
DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) {
Serial.print("Error parsing JSON ");
@ -1350,6 +1372,7 @@ void Web::begin() {
});
server.on("/setNetwork", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
DynamicJsonDocument doc(1024);
DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) {
@ -1398,6 +1421,7 @@ void Web::begin() {
});
server.on("/connectwifi", []() {
webServer.sendCORSHeaders();
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
Serial.println("Settings WIFI connection...");
DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain"));
@ -1467,6 +1491,7 @@ void Web::begin() {
server.send(200, _encoding_json, g_content);
});
server.on("/connectmqtt", []() {
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
DynamicJsonDocument doc(512);
DeserializationError err = deserializeJson(doc, server.arg("plain"));
if (err) {

View file

@ -576,6 +576,37 @@ i.icss-window-shade {
background-size: 0.05em 0.05em;
background-color: rgba(71, 212, 255, 0);
}
i.icss-shutter {
width: 1.1em;
height: .75em;
background-color: transparent;
border: .05em solid transparent;
border-width: 0 .1em;
box-shadow: inset 0 0 0 0.01em, inset 0 0.01em 0px 0.04em;
margin: .2em 0 0;
}
i.icss-shutter:before {
width: 1.1em;
height: .2em;
border-bottom: .05em solid transparent;
box-shadow: inset 0 1em, 0 0em 0 -.1em;
top: -.1em;
left: -.09em;
}
i.icss-shutter:after {
width: calc(100% - .05em);
height: var(--shade-position, 0%);
left: 0.025em;
top: 0.025em;
border-bottom: solid 0.025em gray;
background-image: repeating-linear-gradient(var(--shade-color, currentColor) 0% 50%, rgba(71, 212, 255, 0) 0% 75%);
background-position: 0 0, 100% 100%;
background-size: 0.05em 0.05em;
background-color: rgba(71, 212, 255, 0);
}
i.icss-window-blind {
width: 1.1em;
height: .75em;

View file

@ -3,10 +3,10 @@
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="main.css?v=1.7.2" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.7.2" type="text/css" />
<link rel="stylesheet" href="main.css?v=1.7.3" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.7.3" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="index.js?v=1.7.2"></script>
<script type="text/javascript" src="index.js?v=1.7.3"></script>
</head>
<body>
<div id="divContainer" class="container" style="user-select:none;position:relative;border-radius:27px;">
@ -238,6 +238,7 @@
<div class="field-group" style="margin-top:-10px;">
<select id="selShadeType" name="shadeType" style="width:100%;" onchange="somfy.onShadeTypeChanged(this);">
<option value="0">Roller Shade</option>
<option value="4">Shutter</option>
<option value="1">Blind</option>
<option value="2">Drapery</option>
<option value="3">Awning</option>
@ -389,7 +390,7 @@
</div>
<div class="field-group" style="display:inline-block;width:auto;min-width:247px;margin-top:-20px;vertical-align:top;">
<div class="field-group">
<input id="slidFrequency" name="frequency" type="range" min="433330" max="433499" step="1" style="width:100%;" oninput="somfy.frequencyChanged(this);" />
<input id="slidFrequency" name="frequency" type="range" min="433330" max="434399" step="1" style="width:100%;" oninput="somfy.frequencyChanged(this);" />
<label for="slidRxBandwidth" style="display:block;font-size:1em;margin-top:0px;margin-left:7px;">
<span>Base Frequency </span>
<span style="float:right;display:inline-block;margin-right:7px;">

View file

@ -378,7 +378,7 @@ async function reopenSocket() {
await initSockets();
}
class General {
appVersion = 'v1.7.2';
appVersion = 'v1.7.3';
reloadApp = false;
async init() {
this.setAppVersion();
@ -1069,6 +1069,9 @@ class Somfy {
case 3:
divCtl += ' icss-awning';
break;
case 4:
divCtl += ' icss-shutter';
break;
default:
divCtl += ' icss-window-shade';
break;
@ -1434,19 +1437,29 @@ class Somfy {
document.getElementById('divTiltSettings').style.display = '';
if (ico.classList.contains('icss-window-shade')) ico.classList.remove('icss-window-shade');
if (ico.classList.contains('icss-awning')) ico.classList.remove('icss-awning');
if (ico.classList.contains('icss-shutter')) ico.classList.remove('icss-shutter');
if (!ico.classList.contains('icss-window-blind')) ico.classList.add('icss-window-blind');
break;
case 3:
document.getElementById('divTiltSettings').style.display = 'none';
if (ico.classList.contains('icss-window-shade')) ico.classList.remove('icss-window-shade');
if (ico.classList.contains('icss-window-blind')) ico.classList.remove('icss-window-blind');
if (ico.classList.contains('icss-shutter')) ico.classList.remove('icss-shutter');
if (!ico.classList.contains('icss-awning')) ico.classList.add('icss-awning');
break;
case 4:
document.getElementById('divTiltSettings').style.display = 'none';
if (ico.classList.contains('icss-window-shade')) ico.classList.remove('icss-window-shade');
if (ico.classList.contains('icss-window-blind')) ico.classList.remove('icss-window-blind');
if (ico.classList.contains('icss-awning')) ico.classList.remove('icss-awning');
if (!ico.classList.contains('icss-shutter')) ico.classList.add('icss-shutter');
break;
default:
if (ico.classList.contains('icss-window-blind')) ico.classList.remove('icss-window-blind');
if (ico.classList.contains('icss-awning')) ico.classList.remove('icss-awning');
if (!ico.classList.contains('icss-window-shade')) ico.classList.add('icss-window-shade');
if (ico.classList.contains('icss-shutter')) ico.classList.remove('icss-shutter');
document.getElementById('divTiltSettings').style.display = 'none';
tilt = false;
break;
@ -1534,6 +1547,10 @@ class Somfy {
ico.classList.remove('icss-window-shade');
ico.classList.add('icss-awning');
break;
case 4:
ico.classList.remove('icss-window-shade');
ico.classList.add('icss-shutter');
break;
}
let tilt = ico.parentElement.querySelector('i.icss-window-tilt');
tilt.style.display = shade.tiltType !== 0 ? '' : 'none';

View file

@ -509,7 +509,7 @@ div.waitoverlay > .lds-roller {
}
.shade-name {
text-align:left;
width: 170px;
width: 100%;
padding-left: 2px;
padding-right: 2px;
display: inline-block;