Added API Services for Tilt HomeAssistant

Added api services to support blind definitions in Home Assistant.  Stop tilt function when my button is pressed and the tilt operation is in progress.  Bump to v1.3.2
This commit is contained in:
Robert Strouse 2023-03-04 09:59:00 -08:00
parent 259e437233
commit 71e5b8a648
7 changed files with 71 additions and 5 deletions

View file

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

View file

@ -822,6 +822,7 @@ void SomfyShade::processFrame(somfy_frame_t &frame, bool internal) {
dir = 0; dir = 0;
break; break;
} }
if(dir == 0 && this->hasTilt && this->tiltDirection != 0) this->setTiltMovement(0);
this->setMovement(dir); this->setMovement(dir);
} }
void SomfyShade::setTiltMovement(int8_t dir) { void SomfyShade::setTiltMovement(int8_t dir) {

Binary file not shown.

Binary file not shown.

65
Web.cpp
View file

@ -177,6 +177,71 @@ void Web::begin() {
apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Shade with the specified id not found.\"}")); apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Shade with the specified id not found.\"}"));
} }
}); });
apiServer.on("/tiltCommand", []() {
webServer.sendCORSHeaders();
HTTPMethod method = apiServer.method();
uint8_t shadeId = 255;
uint8_t target = 255;
somfy_commands command = somfy_commands::My;
if (method == HTTP_GET || method == HTTP_PUT || method == HTTP_POST) {
if (server.hasArg("shadeId")) {
shadeId = atoi(apiServer.arg("shadeId").c_str());
if (apiServer.hasArg("command")) command = translateSomfyCommand(apiServer.arg("command"));
else if(apiServer.hasArg("target")) target = atoi(apiServer.arg("target").c_str());
}
else if (apiServer.hasArg("plain")) {
Serial.println("Sending Shade Tilt Command");
DynamicJsonDocument doc(256);
DeserializationError err = deserializeJson(doc, apiServer.arg("plain"));
if (err) {
switch (err.code()) {
case DeserializationError::InvalidInput:
apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Invalid JSON payload\"}"));
break;
case DeserializationError::NoMemory:
apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Out of memory parsing JSON\"}"));
break;
default:
apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"General JSON Deserialization failed\"}"));
break;
}
return;
}
else {
JsonObject obj = doc.as<JsonObject>();
if (obj.containsKey("shadeId")) shadeId = obj["shadeId"];
else apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No shade id was supplied.\"}"));
if (obj.containsKey("command")) {
String scmd = obj["command"];
command = translateSomfyCommand(scmd);
}
else if(obj.containsKey("target")) {
target = obj["target"].as<uint8_t>();
}
}
}
else apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No shade object supplied.\"}"));
}
SomfyShade* shade = somfy.getShadeById(shadeId);
if (shade) {
Serial.print("Received:");
Serial.println(apiServer.arg("plain"));
// Send the command to the shade.
if(target >= 0 && target <= 100)
shade->moveToTiltTarget(target);
else
shade->sendTiltCommand(command);
DynamicJsonDocument sdoc(256);
JsonObject sobj = sdoc.to<JsonObject>();
shade->toJSON(sobj);
serializeJson(sdoc, g_content);
apiServer.send(200, _encoding_json, g_content);
}
else {
apiServer.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Shade with the specified id not found.\"}"));
}
});
server.on("/upnp.xml", []() { server.on("/upnp.xml", []() {
SSDP.schema(server.client()); SSDP.schema(server.client());
}); });

View file

@ -3,10 +3,10 @@
<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=1.3.1" type="text/css" /> <link rel="stylesheet" href="main.css?v=1.3.2" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.3.1" type="text/css" /> <link rel="stylesheet" href="icons.css?v=1.3.2" 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=1.3.1"></script> <script type="text/javascript" src="index.js?v=1.3.2"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container" style="user-select:none;position:relative;"> <div id="divContainer" class="container" style="user-select:none;position:relative;">

View file

@ -355,7 +355,7 @@ async function reopenSocket() {
await initSockets(); await initSockets();
} }
class General { class General {
appVersion = 'v1.3.1'; appVersion = 'v1.3.2';
reloadApp = false; reloadApp = false;
async init() { async init() {
this.setAppVersion(); this.setAppVersion();