mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-13 02:52:11 +01:00
parent
1cb9746cc8
commit
4d49a048f4
11 changed files with 737 additions and 301 deletions
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
extern Preferences pref;
|
||||
|
||||
#define SHADE_HDR_VER 14
|
||||
#define SHADE_HDR_VER 15
|
||||
#define SHADE_HDR_SIZE 56
|
||||
#define SHADE_REC_SIZE 256
|
||||
#define SHADE_REC_SIZE 264
|
||||
#define GROUP_REC_SIZE 184
|
||||
#define TRANS_REC_SIZE 74
|
||||
|
||||
|
|
@ -657,6 +657,11 @@ bool ShadeConfigFile::readShadeRecord(SomfyShade *shade) {
|
|||
if(this->header.version >= 12) shade->repeats = this->readUInt8(1);
|
||||
if(this->header.version >= 13) shade->sortOrder = this->readUInt8(shade->getShadeId() - 1);
|
||||
else shade->sortOrder = shade->getShadeId() - 1;
|
||||
if(this->header.version > 14) {
|
||||
shade->gpioUp = this->readUInt8(shade->gpioUp);
|
||||
shade->gpioDown = this->readUInt8(shade->gpioDown);
|
||||
}
|
||||
|
||||
if(shade->getShadeId() == 255) shade->clear();
|
||||
else if(shade->tiltType == tilt_types::tiltonly) {
|
||||
shade->myPos = shade->currentPos = shade->target = 100.0f;
|
||||
|
|
@ -758,7 +763,9 @@ bool ShadeConfigFile::writeShadeRecord(SomfyShade *shade) {
|
|||
this->writeBool(shade->flipCommands);
|
||||
this->writeBool(shade->flipPosition);
|
||||
this->writeUInt8(shade->repeats);
|
||||
this->writeUInt8(shade->sortOrder, CFG_REC_END);
|
||||
this->writeUInt8(shade->sortOrder);
|
||||
this->writeUInt8(shade->gpioUp);
|
||||
this->writeUInt8(shade->gpioDown, CFG_REC_END);
|
||||
return true;
|
||||
}
|
||||
bool ShadeConfigFile::writeSettingsRecord() {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ class EthernetSettings: BaseSettings {
|
|||
bool load();
|
||||
bool save();
|
||||
void print();
|
||||
|
||||
};
|
||||
class IPSettings: BaseSettings {
|
||||
public:
|
||||
|
|
|
|||
6
MQTT.cpp
6
MQTT.cpp
|
|
@ -186,9 +186,13 @@ bool MQTTClass::connect() {
|
|||
snprintf(this->clientId, sizeof(this->clientId), "client-%08x%08x", (uint32_t)((mac >> 32) & 0xFFFFFFFF), (uint32_t)(mac & 0xFFFFFFFF));
|
||||
if(strlen(settings.MQTT.protocol) > 0 && strlen(settings.MQTT.hostname) > 0) {
|
||||
mqttClient.setServer(settings.MQTT.hostname, settings.MQTT.port);
|
||||
if(mqttClient.connect(this->clientId, settings.MQTT.username, settings.MQTT.password)) {
|
||||
char lwtTopic[128] = "status";
|
||||
if(strlen(settings.MQTT.rootTopic) > 0)
|
||||
snprintf(lwtTopic, sizeof(lwtTopic), "%s/status", settings.MQTT.rootTopic);
|
||||
if(mqttClient.connect(this->clientId, settings.MQTT.username, settings.MQTT.password, lwtTopic, 0, true, "offline")) {
|
||||
Serial.print("Successfully connected MQTT client ");
|
||||
Serial.println(this->clientId);
|
||||
this->publish("status", "online", true);
|
||||
somfy.publish();
|
||||
this->subscribe("shades/+/target/set");
|
||||
this->subscribe("shades/+/tiltTarget/set");
|
||||
|
|
|
|||
32
Somfy.h
32
Somfy.h
|
|
@ -16,15 +16,17 @@
|
|||
#define SOMFY_NO_WIND_TIMEOUT MINS_TO_MILLIS(12)
|
||||
#define SOMFY_NO_WIND_REMOTE_TIMEOUT SECS_TO_MILLIS(30)
|
||||
|
||||
|
||||
struct appver_t {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
uint8_t build;
|
||||
};
|
||||
enum class radio_proto : byte {
|
||||
enum class radio_proto : byte { // Ordinal byte 0-255
|
||||
RTS = 0x00,
|
||||
RTW = 0x01,
|
||||
RTV = 0x02
|
||||
RTV = 0x02,
|
||||
GPIO = 0x08
|
||||
};
|
||||
enum class somfy_commands : byte {
|
||||
Unknown0 = 0x0,
|
||||
|
|
@ -183,6 +185,8 @@ class SomfyRemote {
|
|||
uint32_t m_remoteAddress = 0;
|
||||
public:
|
||||
radio_proto proto = radio_proto::RTS;
|
||||
uint8_t gpioUp = 0;
|
||||
uint8_t gpioDown = 0;
|
||||
somfy_frame_t lastFrame;
|
||||
bool flipCommands = false;
|
||||
uint16_t lastRollingCode = 0;
|
||||
|
|
@ -204,6 +208,7 @@ class SomfyRemote {
|
|||
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);
|
||||
virtual uint16_t p_lastRollingCode(uint16_t code);
|
||||
somfy_commands transformCommand(somfy_commands cmd);
|
||||
};
|
||||
class SomfyLinkedRemote : public SomfyRemote {
|
||||
|
|
@ -231,6 +236,7 @@ class SomfyShade : public SomfyRemote {
|
|||
bool settingTiltPos = false;
|
||||
uint32_t awaitMy = 0;
|
||||
public:
|
||||
int8_t gpioDir = 0;
|
||||
int8_t sortOrder = 0;
|
||||
bool flipPosition = false;
|
||||
shade_types shadeType = shade_types::roller;
|
||||
|
|
@ -249,8 +255,9 @@ class SomfyShade : public SomfyRemote {
|
|||
float myTiltPos = -1.0f;
|
||||
SomfyLinkedRemote linkedRemotes[SOMFY_MAX_LINKED_REMOTES];
|
||||
bool paired = false;
|
||||
int8_t validateJSON(JsonObject &obj);
|
||||
bool toJSONRef(JsonObject &obj);
|
||||
bool fromJSON(JsonObject &obj);
|
||||
int8_t fromJSON(JsonObject &obj);
|
||||
bool toJSON(JsonObject &obj) override;
|
||||
char name[21] = "";
|
||||
void setShadeId(uint8_t id) { shadeId = id; }
|
||||
|
|
@ -289,8 +296,27 @@ class SomfyShade : public SomfyRemote {
|
|||
void commitShadePosition();
|
||||
void commitTiltPosition();
|
||||
void commitMyPosition();
|
||||
void setGPIOs();
|
||||
void clear();
|
||||
int8_t transformPosition(float fpos);
|
||||
|
||||
// State Setters
|
||||
int8_t p_direction(int8_t dir);
|
||||
int8_t p_tiltDirection(int8_t dir);
|
||||
float p_target(float target);
|
||||
float p_tiltTarget(float target);
|
||||
float p_myPos(float pos);
|
||||
float p_myTiltPos(float pos);
|
||||
bool p_flag(somfy_flags_t flag, bool val);
|
||||
bool p_sunFlag(bool val);
|
||||
bool p_sunny(bool val);
|
||||
bool p_windy(bool val);
|
||||
uint16_t p_lastRollingCode(uint16_t code);
|
||||
bool publish(const char *topic, uint8_t val, bool retain = false);
|
||||
bool publish(const char *topic, int8_t val, bool retain = false);
|
||||
bool publish(const char *topic, uint32_t val, bool retain = false);
|
||||
bool publish(const char *topic, uint16_t val, bool retain = false);
|
||||
bool publish(const char *topic, bool val, bool retain = false);
|
||||
};
|
||||
class SomfyGroup : public SomfyRemote {
|
||||
protected:
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
16
Web.cpp
16
Web.cpp
|
|
@ -593,7 +593,8 @@ void Web::handleShade(WebServer &server) {
|
|||
if (obj.containsKey("shadeId")) {
|
||||
SomfyShade* shade = somfy.getShadeById(obj["shadeId"]);
|
||||
if (shade) {
|
||||
shade->fromJSON(obj);
|
||||
uint8_t err = shade->fromJSON(obj);
|
||||
if(err == 0) {
|
||||
shade->save();
|
||||
DynamicJsonDocument sdoc(2048);
|
||||
JsonObject sobj = sdoc.to<JsonObject>();
|
||||
|
|
@ -601,6 +602,11 @@ void Web::handleShade(WebServer &server) {
|
|||
serializeJson(sdoc, g_content);
|
||||
server.send(200, _encoding_json, g_content);
|
||||
}
|
||||
else {
|
||||
snprintf(g_content, sizeof(g_content), "{\"status\":\"DATA\",\"desc\":\"Data Error.\", \"code\":%d}", err);
|
||||
server.send(500, _encoding_json, g_content);
|
||||
}
|
||||
}
|
||||
else server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Shade Id not found.\"}"));
|
||||
}
|
||||
else server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No shade id was supplied.\"}"));
|
||||
|
|
@ -1192,7 +1198,8 @@ void Web::begin() {
|
|||
if (obj.containsKey("shadeId")) {
|
||||
SomfyShade* shade = somfy.getShadeById(obj["shadeId"]);
|
||||
if (shade) {
|
||||
shade->fromJSON(obj);
|
||||
int8_t err = shade->fromJSON(obj);
|
||||
if(err == 0) {
|
||||
shade->save();
|
||||
DynamicJsonDocument sdoc(512);
|
||||
JsonObject sobj = sdoc.to<JsonObject>();
|
||||
|
|
@ -1200,6 +1207,11 @@ void Web::begin() {
|
|||
serializeJson(sdoc, g_content);
|
||||
server.send(200, _encoding_json, g_content);
|
||||
}
|
||||
else {
|
||||
snprintf(g_content, sizeof(g_content), "{\"status\":\"DATA\",\"desc\":\"Data Error.\", \"code\":%d}", err);
|
||||
server.send(500, _encoding_json, g_content);
|
||||
}
|
||||
}
|
||||
else server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"Shade Id not found.\"}"));
|
||||
}
|
||||
else server.send(500, _encoding_json, F("{\"status\":\"ERROR\",\"desc\":\"No shade id was supplied.\"}"));
|
||||
|
|
|
|||
|
|
@ -289,20 +289,33 @@
|
|||
<div style="display:inline-block;float:right;position:relative;"><span id="spanShadeId">*</span>/<span id="spanMaxShades">5</span></div>
|
||||
<div class="field-group" style="padding:0px;">
|
||||
<div class="field-group" style="margin-top:-18px;display:inline-block;width:77px;">
|
||||
<select id="selShadeProto" name="proto" data-bind="proto" data-datatype="int" style="width:100%;">
|
||||
<select id="selShadeProto" name="proto" data-bind="proto" data-datatype="int" style="width:100%;" onchange="somfy.onShadeProtoChanged(this);">
|
||||
<option value="0">RTS</option>
|
||||
<option value="1">RTW</option>
|
||||
<option value="2">RTV</option>
|
||||
<option value="8">GPIO</option>
|
||||
</select>
|
||||
<label for="selShadeProto">Protocol</label>
|
||||
</div>
|
||||
<div class="field-group" style="margin-top:-18px;display:inline-block;width:77px;">
|
||||
<div id="divShadeBitLength" class="field-group" style="margin-top:-18px;width:77px;">
|
||||
<select id="selShadeBitLength" name="bitLength" data-bind="bitLength" data-datatype="int" style="width:100%;" onchange="somfy.onShadeBitLengthChanged(this);">
|
||||
<option value="56">56-BIT</option>
|
||||
<option value="80">80-BIT</option>
|
||||
</select>
|
||||
<label for="selShadeBitLength">Bit Length</label>
|
||||
</div>
|
||||
<div id="divGPIOControl" class=" field-group">
|
||||
<div class="field-group" style="width:70px;display:inline-block;">
|
||||
<select id="selShadeGPIOUp" data-bind="gpioUp" data-datatype="int" style="width:70px;">
|
||||
</select>
|
||||
<label for="selShadeGPIOUp">UP</label>
|
||||
</div>
|
||||
<div class="field-group" style="width:70px;display:inline-block;">
|
||||
<select id="selShadeGPIODown" data-bind="gpioDown" data-datatype="int" style="width:70px;">
|
||||
</select>
|
||||
<label for="selShadeGPIODown">Down</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="field-group" style="width:127px;display:inline-block;margin-top:-10px;float:left;">
|
||||
|
|
@ -322,13 +335,13 @@
|
|||
</select>
|
||||
<label for="selShadeType">Type</label>
|
||||
</div>
|
||||
<div class="field-group" style="margin-top:-15px;">
|
||||
<div id="divShadeAddress" class="field-group" style="margin-top:-15px;">
|
||||
<input id="fldShadeAddress" name="shadeAddress" data-bind="remoteAddress" data-datatype="int" type="number" length=5 placeholder="Address" style="width:100%;text-align:right;">
|
||||
<label for="fldShadeAddress">Remote Address</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="divSomfyButtons" class="shadectl-buttons" style="float:right;margin-top:10px;position:relative">
|
||||
<div id="divSomfyButtons" class="shadectl-buttons" style="float:right;margin-top:-18px;position:relative">
|
||||
<div style="display:inline-block;margin-right:7px;position:relative;font-size:48px;"><i id="icoShade" class="somfy-shade-icon icss-window-shade" data-shadeid="0" style="--shade-position:0%;vertical-align:middle;"><span class="icss-panel-left"></span><span class="icss-panel-right"></span></i><i class="icss-window-tilt" data-tiltposition="0" style="display:none;"></i></div>
|
||||
<div class="button-outline" data-cmd="up" onclick="somfy.sendCommand(parseInt(document.getElementById('spanShadeId').innerText, 10), 'up');"><i class="icss-somfy-up"></i></div>
|
||||
<div class="button-outline" data-cmd="my" onclick="somfy.sendCommand(parseInt(document.getElementById('spanShadeId').innerText, 10), 'my');" style="font-size: 2em; padding: 10px;"><span>my</span></div>
|
||||
|
|
|
|||
156
data/index.js
156
data/index.js
|
|
@ -1,3 +1,8 @@
|
|||
var errors = [
|
||||
{ code: -10, desc: "Pin setting in use for Transceiver" },
|
||||
{ code: -11, desc: "Pin setting in use for Ethernet Adapter" },
|
||||
{ code: -12, desc: "Pin setting in use on another motor" }
|
||||
]
|
||||
document.oncontextmenu = (event) => {
|
||||
if (event.target && event.target.tagName.toLowerCase() === 'input' && (event.target.type.toLowerCase() === 'text' || event.target.type.toLowerCase() === 'password'))
|
||||
return;
|
||||
|
|
@ -874,6 +879,7 @@ class UIBinder {
|
|||
return div;
|
||||
}
|
||||
serviceError(el, err) {
|
||||
let title = 'Service Error'
|
||||
if (arguments.length === 1) {
|
||||
err = el;
|
||||
el = document.getElementById('divContainer');
|
||||
|
|
@ -896,10 +902,17 @@ class UIBinder {
|
|||
}
|
||||
}
|
||||
else if (typeof err !== 'undefined') {
|
||||
if (typeof err.desc === 'string') msg = typeof err.desc !== 'undefined' ? err.desc : err.message;
|
||||
if (typeof err.desc === 'string') {
|
||||
msg = typeof err.desc !== 'undefined' ? err.desc : err.message;
|
||||
if (typeof err.code === 'number') {
|
||||
let e = errors.find(x => x.code === err.code) || { code: err.code, desc: 'Unspecified error' };
|
||||
msg = e.desc;
|
||||
title = err.desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(err);
|
||||
let div = this.errorMessage(`${err.htmlError || 500}:Service Error`);
|
||||
let div = this.errorMessage(`${err.htmlError || 500}:${title}`);
|
||||
let sub = div.querySelector('.sub-message');
|
||||
sub.innerHTML = `<div><label>Service:</label>${err.service}</div><div style="font-size:22px;">${msg}</div>`;
|
||||
return div;
|
||||
|
|
@ -1846,6 +1859,8 @@ class Somfy {
|
|||
ui.toElement(document.getElementById('divTransceiverSettings'), {
|
||||
transceiver: { config: { proto: 0, SCKPin: 18, CSNPin: 5, MOSIPin: 23, MISOPin: 19, TXPin: 12, RXPin: 13, frequency: 433.42, rxBandwidth: 97.96, type:56, deviation: 11.43, txPower: 10, enabled: false } }
|
||||
});
|
||||
this.loadPins('out', document.getElementById('selShadeGPIOUp'));
|
||||
this.loadPins('out', document.getElementById('selShadeGPIODown'));
|
||||
this.initialized = true;
|
||||
}
|
||||
async loadSomfy() {
|
||||
|
|
@ -2231,27 +2246,78 @@ class Somfy {
|
|||
setListDraggable(list, itemclass, onChanged) {
|
||||
let items = list.querySelectorAll(itemclass);
|
||||
let changed = false;
|
||||
[].forEach.call(items, (item) => {
|
||||
item.addEventListener('dragstart', function(e) {
|
||||
console.log({ evt: 'dragStart', e: e, this: this });
|
||||
let timerStart = null;
|
||||
let dragDiv = null;
|
||||
let fnDragStart = function(e) {
|
||||
//console.log({ evt: 'dragStart', e: e, this: this });
|
||||
if (typeof e.dataTransfer !== 'undefined') {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/html', this.innerHTML);
|
||||
e.stopPropagation();
|
||||
this.style.opacity = '0.4';
|
||||
this.classList.add('dragging');
|
||||
});
|
||||
item.addEventListener('dragenter', function (e) {
|
||||
}
|
||||
else {
|
||||
timerStart = setTimeout(() => {
|
||||
this.style.opacity = '0.4';
|
||||
dragDiv = document.createElement('div');
|
||||
dragDiv.innerHTML = this.innerHTML;
|
||||
dragDiv.style.position = 'absolute';
|
||||
dragDiv.classList.add('somfyShade');
|
||||
dragDiv.style.left = `${this.offsetLeft}px`;
|
||||
dragDiv.style.width = `${this.clientWidth}px`;
|
||||
dragDiv.style.top = `${this.offsetTop}px`;
|
||||
dragDiv.style.border = 'dotted 1px silver';
|
||||
//dragDiv.style.background = 'gainsboro';
|
||||
list.appendChild(dragDiv);
|
||||
this.classList.add('dragging');
|
||||
timerStart = null;
|
||||
}, 1000);
|
||||
}
|
||||
e.stopPropagation();
|
||||
};
|
||||
let fnDragEnter = function (e) {
|
||||
//console.log({ evt: 'dragEnter', e: e, this: this });
|
||||
this.classList.add('over');
|
||||
});
|
||||
item.addEventListener('dragover', function(e) {
|
||||
};
|
||||
let fnDragOver = function (e) {
|
||||
//console.log({ evt: 'dragOver', e: e, this: this });
|
||||
if (timerStart) {
|
||||
clearTimeout(timerStart);
|
||||
timerStart = null;
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
if (typeof e.dataTransfer !== 'undefined') e.dataTransfer.dropEffect = 'move';
|
||||
else if (dragDiv) {
|
||||
let rc = list.getBoundingClientRect();
|
||||
let pageY = e.targetTouches[0].pageY;
|
||||
let y = pageY - rc.top;
|
||||
if (y < 0) y = 0;
|
||||
else if (y > rc.height) y = rc.height;
|
||||
dragDiv.style.top = `${y}px`;
|
||||
// Now lets calculate which element we are over.
|
||||
let ndx = -1;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let irc = items[i].getBoundingClientRect();
|
||||
if (pageY <= irc.bottom - (irc.height / 2)) {
|
||||
ndx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let over = items[ndx];
|
||||
if (ndx < 0) [].forEach.call(items, (item) => { item.classList.remove('over') });
|
||||
else if (!over.classList.contains['over']) {
|
||||
[].forEach.call(items, (item) => { item.classList.remove('over') });
|
||||
over.classList.add('over');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
item.addEventListener('dragleave', function(e) {
|
||||
};
|
||||
let fnDragLeave = function (e) {
|
||||
console.log({ evt: 'dragLeave', e: e, this: this });
|
||||
this.classList.remove('over');
|
||||
});
|
||||
item.addEventListener('drop', function(e) {
|
||||
};
|
||||
let fnDrop = function(e) {
|
||||
// Shift around the items.
|
||||
console.log({ evt: 'drop', e: e, this: this });
|
||||
let elDrag = list.querySelector('.dragging');
|
||||
|
|
@ -2261,26 +2327,50 @@ class Somfy {
|
|||
if (this === items[i]) end = i;
|
||||
if (elDrag === items[i]) curr = i;
|
||||
}
|
||||
console.log({ drag: elDrag, curr: curr, end: end, before: curr < end });
|
||||
if (curr !== end) {
|
||||
this.before(elDrag);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
item.addEventListener('dragend', function (e) {
|
||||
|
||||
};
|
||||
let fnDragEnd = function(e) {
|
||||
console.log({ evt: 'dragEnd', e: e, this: this });
|
||||
let elOver = list.querySelector('.over');
|
||||
[].forEach.call(items, (item) => { item.classList.remove('over') });
|
||||
this.style.opacity = '1';
|
||||
//overCounter = 0;
|
||||
this.classList.remove('dragging');
|
||||
if (timerStart) {
|
||||
clearTimeout(timerStart);
|
||||
timerStart = null;
|
||||
}
|
||||
if (dragDiv) {
|
||||
dragDiv.remove();
|
||||
dragDiv = null;
|
||||
if (elOver && typeof elOver !== 'undefined') fnDrop.call(elOver, e);
|
||||
}
|
||||
if (changed && typeof onChanged === 'function') {
|
||||
onChanged(list);
|
||||
}
|
||||
//console.log(e);
|
||||
});
|
||||
this.classList.remove('dragging');
|
||||
};
|
||||
[].forEach.call(items, (item) => {
|
||||
if (firmware.isMobile()) {
|
||||
item.addEventListener('touchstart', fnDragStart);
|
||||
//item.addEventListener('touchenter', fnDragEnter);
|
||||
item.addEventListener('touchmove', fnDragOver);
|
||||
item.addEventListener('touchleave', fnDragLeave);
|
||||
item.addEventListener('drop', fnDrop);
|
||||
item.addEventListener('touchend', fnDragEnd);
|
||||
|
||||
}
|
||||
else {
|
||||
item.addEventListener('dragstart', fnDragStart);
|
||||
item.addEventListener('dragenter', fnDragEnter);
|
||||
item.addEventListener('dragover', fnDragOver);
|
||||
item.addEventListener('dragleave', fnDragLeave);
|
||||
item.addEventListener('drop', fnDrop);
|
||||
item.addEventListener('dragend', fnDragEnd);
|
||||
}
|
||||
});
|
||||
}
|
||||
setGroupsList(groups) {
|
||||
|
|
@ -2573,7 +2663,7 @@ class Somfy {
|
|||
divs[i].setAttribute('data-tilttarget', state.tiltTarget);
|
||||
}
|
||||
let span = divs[i].querySelector('#spanMyPos');
|
||||
if (span) span.innerHTML = typeof state.mypos !== 'undefined' && state.mypos >= 0 ? `${state.mypos}%` : '---';
|
||||
if (span) span.innerHTML = typeof state.myPos !== 'undefined' && state.myPos >= 0 ? `${state.myPos}%` : '---';
|
||||
span = divs[i].querySelector('#spanMyTiltPos');
|
||||
if (span) span.innerHTML = typeof state.myTiltPos !== 'undefined' && state.myTiltPos >= 0 ? `${state.myTiltPos}%` : '---';
|
||||
}
|
||||
|
|
@ -2820,6 +2910,9 @@ class Somfy {
|
|||
document.getElementById('somfyShade').setAttribute('data-bitlength', el.value);
|
||||
//document.getElementById('divStepSettings').style.display = parseInt(el.value, 10) === 80 ? '' : 'none';
|
||||
}
|
||||
onShadeProtoChanged(el) {
|
||||
document.getElementById('somfyShade').setAttribute('data-proto', el.value);
|
||||
}
|
||||
openEditShade(shadeId) {
|
||||
if (typeof shadeId === 'undefined') {
|
||||
getJSONSync('/getNextShade', (err, shade) => {
|
||||
|
|
@ -2833,7 +2926,6 @@ class Somfy {
|
|||
document.getElementById('selShadeBitLength').value = 56;
|
||||
document.getElementById('cbFlipCommands').value = false;
|
||||
document.getElementById('cbFlipPosition').value = false;
|
||||
|
||||
if (err) {
|
||||
ui.serviceError(err);
|
||||
}
|
||||
|
|
@ -2921,6 +3013,7 @@ class Somfy {
|
|||
ico.style.setProperty('--tilt-position', `${shade.flipPosition ? 100 - shade.tiltPosition : shade.tiltPosition}%`);
|
||||
ico.setAttribute('data-shadeid', shade.shadeId);
|
||||
somfy.onShadeBitLengthChanged(document.getElementById('selShadeBitLength'));
|
||||
somfy.onShadeProtoChanged(document.getElementById('selShadeProto'));
|
||||
document.getElementById('btnSetRollingCode').style.display = 'inline-block';
|
||||
if (shade.paired) {
|
||||
document.getElementById('btnUnpairShade').style.display = 'inline-block';
|
||||
|
|
@ -3017,11 +3110,20 @@ class Somfy {
|
|||
ui.errorMessage(document.getElementById('divSomfySettings'), 'Down Time must be a value between 0 and 4,294,967,295 milliseconds. This is the travel time to go from full open to full closed.');
|
||||
valid = false;
|
||||
}
|
||||
if (obj.proto === 8) {
|
||||
if (obj.gpioUp === obj.gpioDown) {
|
||||
ui.errorMessage(document.getElementById('divSomfySettings'), 'For GPIO controlled motors the up and down GPIO selections must be unique.');
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
if (isNaN(shadeId) || shadeId >= 255) {
|
||||
// We are adding.
|
||||
putJSONSync('/addShade', obj, (err, shade) => {
|
||||
if (err) ui.serviceError(err);
|
||||
if (err) {
|
||||
ui.serviceError(err);
|
||||
console.log(err);
|
||||
}
|
||||
else {
|
||||
console.log(shade);
|
||||
document.getElementById('spanShadeId').innerText = shade.shadeId;
|
||||
|
|
|
|||
|
|
@ -135,6 +135,25 @@
|
|||
.shadectl-buttons:not([data-shadetype="5"]):not([data-shadetype="9"]) > .button-outline[data-cmd="toggle"] {
|
||||
display: none;
|
||||
}
|
||||
#somfyShade #divGPIOControl {
|
||||
display: none;
|
||||
}
|
||||
#somfyShade #divShadeBitLength {
|
||||
display:inline-block;
|
||||
}
|
||||
#somfyShade[data-proto="8"] #divGPIOControl {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
margin-top: -18px;
|
||||
}
|
||||
#somfyShade[data-proto="8"] #divShadeBitLength {
|
||||
display: none;
|
||||
}
|
||||
#divGPIOControl {
|
||||
text-align:center;
|
||||
margin-left:7px;
|
||||
}
|
||||
#somfyShade[data-proto="8"] #divStepSettings,
|
||||
#somfyShade[data-bitlength="56"] #divStepSettings,
|
||||
#somfyShade[data-shadetype="5"] #divStepSettings,
|
||||
#somfyShade[data-shadetype="6"] #divStepSettings,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue