mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-12 18:42:10 +01:00
This commit is contained in:
parent
a6c7601458
commit
a823d2349a
11 changed files with 273 additions and 18 deletions
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef configsettings_h
|
||||
#define configsettings_h
|
||||
|
||||
#define FW_VERSION "v2.1.7"
|
||||
#define FW_VERSION "v2.1.8"
|
||||
enum DeviceStatus {
|
||||
DS_OK = 0,
|
||||
DS_ERROR = 1,
|
||||
|
|
|
|||
40
MQTT.cpp
40
MQTT.cpp
|
|
@ -126,6 +126,24 @@ void MQTTClass::receive(const char *topic, byte*payload, uint32_t length) {
|
|||
if(val > 0) shade->sendCommand(somfy_commands::SunFlag);
|
||||
else shade->sendCommand(somfy_commands::Flag);
|
||||
}
|
||||
else if(strncmp(command, "position", sizeof(command)) == 0) {
|
||||
if(val >= 0 && val <= 100) {
|
||||
shade->target = shade->currentPos = (float)val;
|
||||
shade->emitState();
|
||||
}
|
||||
}
|
||||
else if(strncmp(command, "tiltPosition", sizeof(command)) == 0) {
|
||||
if(val >= 0 && val <= 100) {
|
||||
shade->tiltTarget = shade->currentTiltPos = (float)val;
|
||||
shade->emitState();
|
||||
}
|
||||
}
|
||||
else if(strncmp(command, "sunny", sizeof(command)) == 0) {
|
||||
if(val >= 0) shade->sendSensorCommand(-1, val, shade->repeats);
|
||||
}
|
||||
else if(strncmp(command, "windy", sizeof(command)) == 0) {
|
||||
if(val >= 0) shade->sendSensorCommand(val, -1, shade->repeats);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strncmp(entityType, "groups", sizeof(entityType)) == 0) {
|
||||
|
|
@ -146,6 +164,12 @@ void MQTTClass::receive(const char *topic, byte*payload, uint32_t length) {
|
|||
else
|
||||
group->sendCommand(somfy_commands::SunFlag);
|
||||
}
|
||||
else if(strncmp(command, "sunny", sizeof(command)) == 0) {
|
||||
if(val >= 0) group->sendSensorCommand(-1, val, group->repeats);
|
||||
}
|
||||
else if(strncmp(command, "windy", sizeof(command)) == 0) {
|
||||
if(val >= 0) group->sendSensorCommand(val, -1, group->repeats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -172,7 +196,15 @@ bool MQTTClass::connect() {
|
|||
this->subscribe("shades/+/mypos/set");
|
||||
this->subscribe("shades/+/myTiltPos/set");
|
||||
this->subscribe("shades/+/sunFlag/set");
|
||||
this->subscribe("shades/+/sunny/set");
|
||||
this->subscribe("shades/+/windy/set");
|
||||
this->subscribe("shades/+/position/set");
|
||||
this->subscribe("shades/+/tiltPosition/set");
|
||||
this->subscribe("groups/+/direction/set");
|
||||
this->subscribe("groups/+/sunFlag/set");
|
||||
this->subscribe("groups/+/sunny/set");
|
||||
this->subscribe("groups/+/windy/set");
|
||||
|
||||
mqttClient.setCallback(MQTTClass::receive);
|
||||
this->lastConnect = millis();
|
||||
return true;
|
||||
|
|
@ -198,6 +230,14 @@ bool MQTTClass::disconnect() {
|
|||
this->unsubscribe("shades/+/myTiltPos/set");
|
||||
this->unsubscribe("shades/+/sunFlag/set");
|
||||
this->unsubscribe("groups/+/direction/set");
|
||||
this->unsubscribe("shades/+/sunny/set");
|
||||
this->unsubscribe("shades/+/windy/set");
|
||||
this->unsubscribe("shades/+/position/set");
|
||||
this->unsubscribe("shades/+/tiltPosition/set");
|
||||
this->unsubscribe("groups/+/direction/set");
|
||||
this->unsubscribe("groups/+/sunFlag/set");
|
||||
this->unsubscribe("groups/+/sunny/set");
|
||||
this->unsubscribe("groups/+/windy/set");
|
||||
mqttClient.disconnect();
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
29
Somfy.cpp
29
Somfy.cpp
|
|
@ -143,7 +143,6 @@ void somfy_frame_t::decodeFrame(byte* frame) {
|
|||
// We reuse this memory address so we must reset the processed
|
||||
// flag. This will ensure we can see frames on the first beat.
|
||||
this->processed = false;
|
||||
Serial.println("Processed set to false");
|
||||
// Pull in the data for an 80-bit step command.
|
||||
if(this->cmd == somfy_commands::StepDown) this->cmd = (somfy_commands)((decoded[1] >> 4) | ((decoded[8] & 0x08) << 4));
|
||||
this->rollingCode = decoded[3] + (decoded[2] << 8);
|
||||
|
|
@ -856,6 +855,7 @@ void SomfyShade::checkMovement() {
|
|||
&& this->noSunStart
|
||||
&& (curTime - this->noSunStart) >= SOMFY_NO_SUN_TIMEOUT)
|
||||
{
|
||||
if(this->tiltType == tilt_types::tiltonly) this->tiltTarget = 0.0f;
|
||||
this->target = 0.0f;
|
||||
this->noSunDone = true;
|
||||
Serial.printf("[%u] No Sun -> done\r\n", this->shadeId);
|
||||
|
|
@ -867,6 +867,7 @@ void SomfyShade::checkMovement() {
|
|||
&& this->windStart
|
||||
&& (curTime - this->windStart) >= SOMFY_WIND_TIMEOUT)
|
||||
{
|
||||
if(this->tiltType == tilt_types::tiltonly) this->tiltTarget = 0.0f;
|
||||
this->target = 0.0f;
|
||||
this->windDone = true;
|
||||
Serial.printf("[%u] Wind -> done\r\n", this->shadeId);
|
||||
|
|
@ -2635,6 +2636,32 @@ somfy_commands SomfyRemote::transformCommand(somfy_commands cmd) {
|
|||
}
|
||||
return cmd;
|
||||
}
|
||||
void SomfyRemote::sendSensorCommand(int8_t isWindy, int8_t isSunny, uint8_t repeat) {
|
||||
uint8_t flags = (this->flags >> 4) & 0x0F;
|
||||
if(isWindy > 0) flags |= 0x01;
|
||||
if(isSunny > 0) flags |= 0x02;
|
||||
if(isWindy == 0) flags &= ~0x01;
|
||||
if(isSunny == 0) flags &= ~0x02;
|
||||
|
||||
// Now ship this off as an 80 bit command.
|
||||
this->lastFrame.remoteAddress = this->getRemoteAddress();
|
||||
this->lastFrame.repeats = repeat;
|
||||
this->lastFrame.bitLength = this->bitLength;
|
||||
this->lastFrame.rollingCode = (uint16_t)flags;
|
||||
this->lastFrame.encKey = 160; // Sensor commands are always encryption code 160.
|
||||
this->lastFrame.cmd = somfy_commands::Sensor;
|
||||
this->lastFrame.processed = false;
|
||||
Serial.print("CMD:");
|
||||
Serial.print(translateSomfyCommand(this->lastFrame.cmd));
|
||||
Serial.print(" ADDR:");
|
||||
Serial.print(this->lastFrame.remoteAddress);
|
||||
Serial.print(" RCODE:");
|
||||
Serial.print(this->lastFrame.rollingCode);
|
||||
Serial.print(" REPEAT:");
|
||||
Serial.println(repeat);
|
||||
somfy.sendFrame(this->lastFrame, repeat);
|
||||
somfy.processFrame(this->lastFrame, true);
|
||||
}
|
||||
void SomfyRemote::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); }
|
||||
void SomfyRemote::sendCommand(somfy_commands cmd, uint8_t repeat) {
|
||||
this->lastFrame.rollingCode = this->getNextRollingCode();
|
||||
|
|
|
|||
1
Somfy.h
1
Somfy.h
|
|
@ -201,6 +201,7 @@ class SomfyRemote {
|
|||
void setLight(bool bHasLight);
|
||||
virtual void sendCommand(somfy_commands cmd);
|
||||
virtual void sendCommand(somfy_commands cmd, uint8_t repeat);
|
||||
void sendSensorCommand(int8_t isWindy, int8_t isSunny, uint8_t repeat);
|
||||
void repeatFrame(uint8_t repeat);
|
||||
somfy_commands transformCommand(somfy_commands cmd);
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
161
Web.cpp
161
Web.cpp
|
|
@ -696,6 +696,133 @@ void Web::handleDiscovery(WebServer &server) {
|
|||
else
|
||||
server.send(500, _encoding_text, "Invalid http method");
|
||||
}
|
||||
void Web::handleSetPositions(WebServer &server) {
|
||||
webServer.sendCORSHeaders(server);
|
||||
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
|
||||
HTTPMethod method = apiServer.method();
|
||||
uint8_t shadeId = (server.hasArg("shadeId")) ? atoi(server.arg("shadeId").c_str()) : 255;
|
||||
int8_t pos = (server.hasArg("position")) ? atoi(server.arg("position").c_str()) : -1;
|
||||
int8_t tiltPos = (server.hasArg("tiltPosition")) ? atoi(server.arg("tiltPosition").c_str()) : -1;
|
||||
if(server.hasArg("plain")) {
|
||||
DynamicJsonDocument doc(512);
|
||||
DeserializationError err = deserializeJson(doc, server.arg("plain"));
|
||||
if (err) {
|
||||
switch (err.code()) {
|
||||
case DeserializationError::InvalidInput:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
|
||||
break;
|
||||
case DeserializationError::NoMemory:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
|
||||
break;
|
||||
default:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
if(obj.containsKey("shadeId")) shadeId = obj["shadeId"];
|
||||
if(obj.containsKey("position")) pos = obj["position"];
|
||||
if(obj.containsKey("tiltPosition")) tiltPos = obj["tiltPosition"];
|
||||
}
|
||||
}
|
||||
if(shadeId != 255) {
|
||||
SomfyShade *shade = somfy.getShadeById(shadeId);
|
||||
if(shade) {
|
||||
if(pos >= 0) shade->target = shade->currentPos = pos;
|
||||
if(tiltPos >= 0 && shade->tiltType != tilt_types::none) shade->tiltTarget = shade->currentTiltPos = tiltPos;
|
||||
shade->emitState();
|
||||
DynamicJsonDocument sdoc(2048);
|
||||
JsonObject sobj = sdoc.to<JsonObject>();
|
||||
shade->toJSON(sobj);
|
||||
serializeJson(sdoc, g_content);
|
||||
server.send(200, _encoding_json, g_content);
|
||||
}
|
||||
else
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"An invalid shadeId was provided\"}"));
|
||||
}
|
||||
else {
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"shadeId was not provided\"}"));
|
||||
}
|
||||
}
|
||||
void Web::handleSetSensor(WebServer &server) {
|
||||
webServer.sendCORSHeaders(server);
|
||||
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
|
||||
HTTPMethod method = apiServer.method();
|
||||
uint8_t shadeId = (server.hasArg("shadeId")) ? atoi(server.arg("shadeId").c_str()) : 255;
|
||||
uint8_t groupId = (server.hasArg("groupId")) ? atoi(server.arg("groupId").c_str()) : 255;
|
||||
int8_t sunny = (server.hasArg("sunny")) ? toBoolean(server.arg("sunny").c_str(), false) ? 1 : 0 : -1;
|
||||
int8_t windy = (server.hasArg("windy")) ? atoi(server.arg("windy").c_str()) : -1;
|
||||
int8_t repeat = (server.hasArg("repeat")) ? atoi(server.arg("repeat").c_str()) : -1;
|
||||
if(server.hasArg("plain")) {
|
||||
DynamicJsonDocument doc(512);
|
||||
DeserializationError err = deserializeJson(doc, server.arg("plain"));
|
||||
if (err) {
|
||||
switch (err.code()) {
|
||||
case DeserializationError::InvalidInput:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
|
||||
break;
|
||||
case DeserializationError::NoMemory:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
|
||||
break;
|
||||
default:
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
if(obj.containsKey("shadeId")) shadeId = obj["shadeId"].as<uint8_t>();
|
||||
if(obj.containsKey("groupId")) groupId = obj["groupId"].as<uint8_t>();
|
||||
if(obj.containsKey("sunny")) {
|
||||
if(obj["sunny"].is<bool>())
|
||||
sunny = obj["sunny"].as<bool>() ? 1 : 0;
|
||||
else
|
||||
sunny = obj["sunny"].as<int8_t>();
|
||||
}
|
||||
if(obj.containsKey("windy")) {
|
||||
if(obj["windy"].is<bool>())
|
||||
windy = obj["windy"].as<bool>() ? 1 : 0;
|
||||
else
|
||||
windy = obj["windy"].as<int8_t>();
|
||||
}
|
||||
if(obj.containsKey("repeat")) repeat = obj["repeat"].as<uint8_t>();
|
||||
}
|
||||
}
|
||||
if(shadeId != 255) {
|
||||
SomfyShade *shade = somfy.getShadeById(shadeId);
|
||||
if(shade) {
|
||||
shade->sendSensorCommand(windy, sunny, repeat >= 0 ? (uint8_t)repeat : shade->repeats);
|
||||
shade->emitState();
|
||||
DynamicJsonDocument sdoc(2048);
|
||||
JsonObject sobj = sdoc.to<JsonObject>();
|
||||
shade->toJSON(sobj);
|
||||
serializeJson(sdoc, g_content);
|
||||
server.send(200, _encoding_json, g_content);
|
||||
}
|
||||
else
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"An invalid shadeId was provided\"}"));
|
||||
|
||||
}
|
||||
else if(groupId != 255) {
|
||||
SomfyGroup *group = somfy.getGroupById(groupId);
|
||||
if(group) {
|
||||
group->sendSensorCommand(windy, sunny, repeat >= 0 ? (uint8_t)repeat : group->repeats);
|
||||
group->emitState();
|
||||
DynamicJsonDocument sdoc(2048);
|
||||
JsonObject sobj = sdoc.to<JsonObject>();
|
||||
group->toJSON(sobj);
|
||||
serializeJson(sdoc, g_content);
|
||||
server.send(200, _encoding_json, g_content);
|
||||
}
|
||||
else
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"An invalid groupId was provided\"}"));
|
||||
}
|
||||
else {
|
||||
server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"shadeId was not provided\"}"));
|
||||
}
|
||||
}
|
||||
|
||||
void Web::handleNotFound(WebServer &server) {
|
||||
HTTPMethod method = server.method();
|
||||
Serial.printf("Request %s 404-%d ", server.uri().c_str(), method);
|
||||
|
|
@ -743,13 +870,16 @@ void Web::begin() {
|
|||
apiServer.on("/repeatCommand", []() { webServer.handleRepeatCommand(apiServer); });
|
||||
apiServer.on("/shade", HTTP_GET, [] () { webServer.handleShade(apiServer); });
|
||||
apiServer.on("/group", HTTP_GET, [] () { webServer.handleGroup(apiServer); });
|
||||
|
||||
apiServer.on("/setPositions", []() { webServer.handleSetPositions(apiServer); });
|
||||
apiServer.on("/setSensor", []() { webServer.handleSetSensor(apiServer); });
|
||||
|
||||
// Web Interface
|
||||
server.on("/tiltCommand", []() { webServer.handleTiltCommand(server); });
|
||||
server.on("/repeatCommand", []() { webServer.handleRepeatCommand(server); });
|
||||
server.on("/shadeCommand", []() { webServer.handleShadeCommand(server); });
|
||||
server.on("/groupCommand", []() { webServer.handleGroupCommand(server); });
|
||||
|
||||
server.on("/setPositions", []() { webServer.handleSetPositions(server); });
|
||||
server.on("/setSensor", []() { webServer.handleSetSensor(server); });
|
||||
server.on("/upnp.xml", []() { SSDP.schema(server.client()); });
|
||||
server.on("/", []() { webServer.handleStreamFile(server, "/index.html", _encoding_html); });
|
||||
server.on("/login", []() { webServer.handleLogin(server); });
|
||||
|
|
@ -1623,14 +1753,15 @@ void Web::begin() {
|
|||
if (Update.hasError())
|
||||
server.send(500, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Error updating firmware: \"}");
|
||||
else
|
||||
server.send(200, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Updating firmware: \"}");
|
||||
server.send(200, _encoding_json, "{\"status\":\"SUCCESS\",\"desc\":\"Successfully updated firmware\"}");
|
||||
rebootDelay.reboot = true;
|
||||
rebootDelay.rebootTime = millis() + 500;
|
||||
}, []() {
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
webServer.uploadSuccess = false;
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
Serial.printf("Update: %s - %d\n", upload.filename.c_str(), upload.totalSize);
|
||||
//if(!Update.begin(upload.totalSize, U_SPIFFS)) {
|
||||
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
|
||||
Update.printError(Serial);
|
||||
}
|
||||
|
|
@ -1639,10 +1770,16 @@ void Web::begin() {
|
|||
mqtt.end();
|
||||
}
|
||||
}
|
||||
else if(upload.status == UPLOAD_FILE_ABORTED) {
|
||||
Serial.printf("Upload of %s aborted\n", upload.filename.c_str());
|
||||
Update.abort();
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
/* flashing firmware to ESP*/
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(Serial);
|
||||
Serial.printf("Upload of %s aborted invalid size %d\n", upload.filename.c_str(), upload.currentSize);
|
||||
Update.abort();
|
||||
}
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_END) {
|
||||
|
|
@ -1683,14 +1820,18 @@ void Web::begin() {
|
|||
webServer.sendCORSHeaders(server);
|
||||
if(server.method() == HTTP_OPTIONS) { server.send(200, "OK"); return; }
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Updating Application: \"}");
|
||||
if (Update.hasError())
|
||||
server.send(500, _encoding_json, "{\"status\":\"ERROR\",\"desc\":\"Error updating application: \"}");
|
||||
else
|
||||
server.send(200, _encoding_json, "{\"status\":\"SUCCESS\",\"desc\":\"Successfully updated application\"}");
|
||||
rebootDelay.reboot = true;
|
||||
rebootDelay.rebootTime = millis() + 500;
|
||||
}, []() {
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
webServer.uploadSuccess = false;
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
Serial.printf("Update: %s %d\n", upload.filename.c_str(), upload.totalSize);
|
||||
//if(!Update.begin(upload.totalSize, U_SPIFFS)) {
|
||||
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { //start with max available size and tell it we are updating the file system.
|
||||
Update.printError(Serial);
|
||||
}
|
||||
|
|
@ -1699,10 +1840,17 @@ void Web::begin() {
|
|||
mqtt.end();
|
||||
}
|
||||
}
|
||||
else if(upload.status == UPLOAD_FILE_ABORTED) {
|
||||
Serial.printf("Upload of %s aborted\n", upload.filename.c_str());
|
||||
Update.abort();
|
||||
somfy.commit();
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
/* flashing littlefs to ESP*/
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(Serial);
|
||||
Serial.printf("Upload of %s aborted invalid size %d\n", upload.filename.c_str(), upload.currentSize);
|
||||
Update.abort();
|
||||
}
|
||||
}
|
||||
else if (upload.status == UPLOAD_FILE_END) {
|
||||
|
|
@ -1712,6 +1860,7 @@ void Web::begin() {
|
|||
somfy.commit();
|
||||
}
|
||||
else {
|
||||
somfy.commit();
|
||||
Update.printError(Serial);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
Web.h
2
Web.h
|
|
@ -22,6 +22,8 @@ class Web {
|
|||
void handleNotFound(WebServer &server);
|
||||
void handleShade(WebServer &server);
|
||||
void handleGroup(WebServer &server);
|
||||
void handleSetPositions(WebServer &server);
|
||||
void handleSetSensor(WebServer &server);
|
||||
void begin();
|
||||
void loop();
|
||||
void end();
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2.1.7
|
||||
2.1.8
|
||||
|
|
@ -3,11 +3,11 @@
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="main.css?v=2.1.7" type="text/css" />
|
||||
<link rel="stylesheet" href="widgets.css?v=2.1.7" type="text/css" />
|
||||
<link rel="stylesheet" href="icons.css?v=2.1.7" type="text/css" />
|
||||
<link rel="stylesheet" href="main.css?v=2.1.8" type="text/css" />
|
||||
<link rel="stylesheet" href="widgets.css?v=2.1.8" type="text/css" />
|
||||
<link rel="stylesheet" href="icons.css?v=2.1.8" type="text/css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<script type="text/javascript" src="index.js?v=2.1.7"></script>
|
||||
<script type="text/javascript" src="index.js?v=2.1.8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="divContainer" class="container main" data-auth="false">
|
||||
|
|
@ -611,6 +611,24 @@
|
|||
<div class="button-outline" style="width:127px;text-align:center;border-radius:33%;font-size:2em;padding:10px;" data-cmd="Flag" onmousedown="somfy.sendVRCommand(this);" ontouchstart="somfy.sendVRCommand(this);"><div class="button-sunflag" data-on="false" style="margin:0px;"><i class="icss-sun-c" style="background:transparent;"></i><i class="icss-sun-o" style="left:0px;color:white;"></i></div><span>off</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vr-button">
|
||||
<span>
|
||||
<span>Sensor</span>
|
||||
<span style="display:inline-block;vertical-align:middle;margin-left:14px;">
|
||||
<span style="display:block">
|
||||
<input id="cbSunny" type="checkbox" data-bind="sunny" style="display:inline-block;" />
|
||||
<label for="cbSunny" style="display:inline-block;cursor:pointer;">Sunny</label>
|
||||
</span>
|
||||
<span style="display:block">
|
||||
<input id="cbWindy" type="checkbox" data-bind="windy" style="display:inline-block;" />
|
||||
<label for="cbWindy" style="display:inline-block;cursor:pointer;">Windy</label>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div>
|
||||
<div class="button-outline" style="width:127px;text-align:center;border-radius:33%;font-size:2em;padding:10px;" data-cmd="Sensor" onmousedown="somfy.sendVRCommand(this);" ontouchstart="somfy.sendVRCommand(this);"><div class="button-sunflag" data-on="false" style="margin:0px;"></div><span>send</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="divRadioSettings" style="display:none;">
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ Number.prototype.fmt = function (format, empty) {
|
|||
if (rd.length === 0 && rw.length === 0) return '';
|
||||
return pfx + rw + rd + sfx;
|
||||
};
|
||||
var baseUrl = window.location.protocol === 'file:' ? 'http://ESPSomfyRTS.local' : '';
|
||||
var baseUrl = window.location.protocol === 'file:' ? 'http://ESPSomfyRTS' : '';
|
||||
//var baseUrl = '';
|
||||
function makeBool(val) {
|
||||
if (typeof val === 'boolean') return val;
|
||||
|
|
@ -519,6 +519,7 @@ async function initSockets() {
|
|||
}
|
||||
else {
|
||||
(async () => {
|
||||
ui.clearErrors();
|
||||
await general.loadGeneral();
|
||||
await wifi.loadNetwork();
|
||||
await somfy.loadSomfy();
|
||||
|
|
@ -1200,7 +1201,7 @@ var security = new Security();
|
|||
|
||||
class General {
|
||||
initialized = false;
|
||||
appVersion = 'v2.1.7';
|
||||
appVersion = 'v2.1.8';
|
||||
reloadApp = false;
|
||||
init() {
|
||||
if (this.initialized) return;
|
||||
|
|
@ -3415,6 +3416,8 @@ class Somfy {
|
|||
address: opt.getAttribute('data-address'),
|
||||
cmd: el.getAttribute('data-cmd')
|
||||
};
|
||||
ui.fromElement(el.parentElement.parentElement, o);
|
||||
console.log(o);
|
||||
switch (o.type) {
|
||||
case 'shade':
|
||||
o.shadeId = parseInt(opt.getAttribute('data-shadeId'), 10);
|
||||
|
|
@ -3432,17 +3435,28 @@ class Somfy {
|
|||
}
|
||||
if (err) return;
|
||||
if (mouseDown) {
|
||||
if (o.type === 'group')
|
||||
if (o.cmd === 'Sensor')
|
||||
somfy.sendSetSensor(o);
|
||||
else if (o.type === 'group')
|
||||
somfy.sendGroupRepeat(o.groupId, o.cmd, null, fnRepeatCommand);
|
||||
else
|
||||
somfy.sendCommandRepeat(o.shadeId, o.cmd, null, fnRepeatCommand);
|
||||
}
|
||||
}
|
||||
if (o.type === 'group')
|
||||
if (o.cmd === 'Sensor') {
|
||||
somfy.sendSetSensor(o);
|
||||
|
||||
}
|
||||
else if (o.type === 'group')
|
||||
somfy.sendGroupCommand(o.groupId, o.cmd, null, (err, group) => { fnRepeatCommand(err, group); });
|
||||
else
|
||||
somfy.sendCommand(o.shadeId, o.cmd, null, (err, shade) => { fnRepeatCommand(err, shade); });
|
||||
}
|
||||
sendSetSensor(obj, cb) {
|
||||
putJSON('/setSensor', obj, (err, device) => {
|
||||
if (typeof cb === 'function') cb(err, device);
|
||||
});
|
||||
}
|
||||
sendGroupCommand(groupId, command, repeat, cb) {
|
||||
console.log(`Sending Group command ${groupId}-${command}`);
|
||||
let obj = { groupId: groupId };
|
||||
|
|
@ -4026,7 +4040,6 @@ class Firmware {
|
|||
let prog = el.querySelector('div[id="progFileUpload"]');
|
||||
prog.style.display = '';
|
||||
btnSelectFile.style.visibility = 'hidden';
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
//xhr.open('POST', service, true);
|
||||
xhr.open('POST', baseUrl.length > 0 ? `${baseUrl}${service}` : service, true);
|
||||
|
|
@ -4057,6 +4070,11 @@ class Firmware {
|
|||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
btnCancel.addEventListener('click', (e) => {
|
||||
console.log('Cancel clicked');
|
||||
xhr.abort();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
var firmware = new Firmware();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue