`;
html += '
BEWARE ... WARNING ... DANGER
';
html += '
';
html += '
Incorrect Ethernet settings can damage your ESP32. Please verify the settings below and ensure they match the manufacturer spec sheet.
';
html += '
If you are unsure do not press the Red button and press the Green button. If any of the settings are incorrect please use the Custom Board type and set them to the correct values.';
html += '
';
html += `
Board Type ${boardType.label} [${boardType.val}]
`;
html += `
PHY Chip Type ${phyType.label} [${phyType.val}]
`;
html += `
PHY Address ${obj.ethernet.phyAddress}
`;
html += `
Clock Mode ${clkMode.label} [${clkMode.val}]
`;
html += `
Power Pin ${obj.ethernet.PWRPin === -1 ? 'None' : obj.ethernet.PWRPin}
`;
html += `
MDC Pin ${obj.ethernet.MDCPin}
`;
html += `
MDIO Pin ${obj.ethernet.MDIOPin}
`;
html += '
'
html += `
`
html += `Save Ethernet Settings `
html += `Cancel `
html += `
';
}
document.getElementById('divShadeList').innerHTML = divCfg;
let shadeControls = document.getElementById('divShadeControls');
shadeControls.innerHTML = divCtl;
// Attach the timer for setting the My Position for the shade.
let btns = shadeControls.querySelectorAll('div.cmd-button');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('mouseup', (event) => {
console.log(this);
console.log(event);
console.log('mouseup');
let cmd = event.currentTarget.getAttribute('data-cmd');
let shadeId = parseInt(event.currentTarget.getAttribute('data-shadeid'), 10);
if (this.btnTimer) {
clearTimeout(this.btnTimer);
this.btnTimer = null;
if (new Date().getTime() - this.btnDown > 2000) event.preventDefault();
else this.sendCommand(shadeId, cmd);
}
else this.sendCommand(shadeId, cmd);
}, true);
btns[i].addEventListener('mousedown', (event) => {
if (this.btnTimer) {
clearTimeout(this.btnTimer);
this.btnTimer = null;
}
console.log(this);
console.log(event);
console.log('mousedown');
let elShade = event.currentTarget.closest('div.somfyShadeCtl');
let cmd = event.currentTarget.getAttribute('data-cmd');
let shadeId = parseInt(event.currentTarget.getAttribute('data-shadeid'), 10);
let el = event.currentTarget.closest('.somfyShadeCtl');
this.btnDown = new Date().getTime();
if (cmd === 'my') {
if (parseInt(el.getAttribute('data-direction'), 10) === 0) {
this.btnTimer = setTimeout(() => {
// Open up the set My Position dialog. We will allow the user to change the position to match
// the desired position.
this.openSetMyPosition(shadeId);
}, 2000);
}
}
else if (makeBool(elShade.getAttribute('data-tilt'))) {
this.btnTimer = setTimeout(() => {
this.sendTiltCommand(shadeId, cmd);
}, 2000);
}
}, true);
btns[i].addEventListener('touchstart', (event) => {
if (this.btnTimer) {
clearTimeout(this.btnTimer);
this.btnTimer = null;
}
console.log(this);
console.log(event);
console.log('touchstart');
let elShade = event.currentTarget.closest('div.somfyShadeCtl');
let cmd = event.currentTarget.getAttribute('data-cmd');
let shadeId = parseInt(event.currentTarget.getAttribute('data-shadeid'), 10);
let el = event.currentTarget.closest('.somfyShadeCtl');
this.btnDown = new Date().getTime();
if (parseInt(el.getAttribute('data-direction'), 10) === 0) {
if (cmd === 'my') {
this.btnTimer = setTimeout(() => {
// Open up the set My Position dialog. We will allow the user to change the position to match
// the desired position.
this.openSetMyPosition(shadeId);
}, 2000);
}
else {
if (makeBool(elShade.getAttribute('data-tilt'))) {
this.btnTimer = setTimeout(() => {
this.sendTiltCommand(shadeId, cmd);
}, 2000);
}
}
}
}, true);
}
};
closeShadePositioners() {
let ctls = document.querySelectorAll('.shade-positioner');
for (let i = 0; i < ctls.length; i++) {
console.log('Closing shade positioner');
ctls[i].remove();
}
}
openSetMyPosition(shadeId) {
if (typeof shadeId === 'undefined') {
return;
}
else {
let shade = document.querySelector(`div.somfyShadeCtl[data-shadeid="${shadeId}"]`);
if (shade) {
this.closeShadePositioners();
let currPos = parseInt(shade.getAttribute('data-position'), 10);
let myPos = parseInt(shade.getAttribute('data-mypos'), 10);
let elname = shade.querySelector(`.shadectl-name`);
let shadeName = elname.innerHTML;
let html = ``;
for (let i = 0; i < frame.pulses.length; i++) {
if (i !== 0) html += ',';
html += `${frame.pulses[i]}`;
}
row.innerHTML = html;
frames.prepend(row);
this.frames.push(frame);
};
JSONPretty(obj, indent = 2) {
if (Array.isArray(obj)) {
let output = '[';
for (let i = 0; i < obj.length; i++) {
if (i != 0) output += ',\n';
output += this.JSONPretty(obj[i], indent);
}
output += ']'
return output;
}
else {
let output = JSON.stringify(obj, function (k, v) {
if (Array.isArray(v)) return JSON.stringify(v);
return v;
}, indent).replace(/\\/g, '')
.replace(/\"\[/g, '[')
.replace(/\]\"/g, ']')
.replace(/\"\{/g, '{')
.replace(/\}\"/g, '}')
.replace(/\{\n\s+/g, '{');
return output;
}
}
framesToClipboard() {
if (typeof navigator.clipboard !== 'undefined')
navigator.clipboard.writeText(this.JSONPretty(this.frames, 2));
else {
let dummy = document.createElement('textarea');
document.body.appendChild(dummy);
dummy.value = this.JSONPretty(this.frames, 2);
dummy.focus();
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
}
}
openConfigTransceiver() {
document.getElementById('somfyMain').style.display = 'none';
document.getElementById('somfyTransceiver').style.display = '';
};
closeConfigTransceiver() {
document.getElementById('somfyTransceiver').style.display = 'none';
document.getElementById('somfyMain').style.display = '';
};
onShadeTypeChanged(el) {
let sel = document.getElementById('selShadeType');
let tilt = document.getElementById('cbHasTilt').checked;
let ico = document.getElementById('icoShade');
switch (parseInt(sel.value, 10)) {
case 1:
document.getElementById('divTiltSettings').style.display = '';
if (ico.classList.contains('icss-window-shade')) ico.classList.remove('icss-window-shade');
if (!ico.classList.contains('icss-window-blind')) ico.classList.add('icss-window-blind');
break;
default:
if (ico.classList.contains('icss-window-blind')) ico.classList.remove('icss-window-blind');
if (!ico.classList.contains('icss-window-shade')) ico.classList.add('icss-window-shade');
document.getElementById('divTiltSettings').style.display = 'none';
tilt = false;
break;
}
document.getElementById('fldTiltTime').parentElement.style.display = tilt ? 'inline-block' : 'none';
document.querySelector('#divSomfyButtons i.icss-window-tilt').style.display = tilt ? '' : 'none';
};
openEditShade(shadeId) {
console.log('Opening Edit Shade');
if (typeof shadeId === 'undefined') {
let overlay = waitMessage(document.getElementById('fsSomfySettings'));
getJSON('/getNextShade', (err, shade) => {
overlay.remove();
if (err) {
serviceError(document.getElementById('fsSomfySettings'), err);
}
else {
console.log(shade);
document.getElementById('btnPairShade').style.display = 'none';
document.getElementById('btnUnpairShade').style.display = 'none';
document.getElementById('btnLinkRemote').style.display = 'none';
document.getElementsByName('shadeUpTime')[0].value = 10000;
document.getElementsByName('shadeDownTime')[0].value = 10000;
document.getElementById('fldTiltTime').value = 7000;
document.getElementById('somfyMain').style.display = 'none';
document.getElementById('somfyShade').style.display = '';
document.getElementById('btnSaveShade').innerText = 'Add Shade';
document.getElementById('spanShadeId').innerText = '*';
document.getElementsByName('shadeName')[0].value = '';
document.getElementsByName('shadeAddress')[0].value = shade.remoteAddress;
document.getElementById('divLinkedRemoteList').innerHTML = '';
document.getElementById('btnSetRollingCode').style.display = 'none';
document.getElementById('selShadeBitLength').value = shade.bitLength || 56;
}
});
}
else {
// Load up an exist shade.
document.getElementById('btnSaveShade').style.display = 'none';
document.getElementById('btnPairShade').style.display = 'none';
document.getElementById('btnUnpairShade').style.display = 'none';
document.getElementById('btnLinkRemote').style.display = 'none';
document.getElementById('btnSaveShade').innerText = 'Save Shade';
document.getElementById('spanShadeId').innerText = shadeId;
let overlay = waitMessage(document.getElementById('fsSomfySettings'));
getJSON(`/shade?shadeId=${shadeId}`, (err, shade) => {
if (err) {
serviceError(document.getElementById('fsSomfySettings'), err);
}
else {
document.getElementById('somfyMain').style.display = 'none';
document.getElementById('somfyShade').style.display = '';
document.getElementById('btnSaveShade').style.display = 'inline-block';
document.getElementById('btnLinkRemote').style.display = '';
document.getElementById('selShadeType').value = shade.shadeType;
document.getElementsByName('shadeAddress')[0].value = shade.remoteAddress;
document.getElementsByName('shadeName')[0].value = shade.name;
document.getElementsByName('shadeUpTime')[0].value = shade.upTime;
document.getElementsByName('shadeDownTime')[0].value = shade.downTime;
document.getElementById('fldTiltTime').value = shade.tiltTime;
document.getElementById('cbHasTilt').checked = shade.hasTilt;
this.onShadeTypeChanged(document.getElementById('selShadeType'));
let ico = document.getElementById('icoShade');
switch (shade.shadeType) {
case 1:
ico.classList.remove('icss-window-shade');
ico.classList.add('icss-window-blind');
break;
}
let tilt = ico.parentElement.querySelector('i.icss-window-tilt');
tilt.style.display = shade.hasTilt ? '' : 'none';
tilt.setAttribute('data-tiltposition', shade.tiltPosition);
ico.style.setProperty('--shade-position', `${shade.position}%`);
ico.style.setProperty('--tilt-position', `${shade.tiltPosition}%`);
ico.setAttribute('data-shadeid', shade.shadeId);
document.getElementById('btnSetRollingCode').style.display = 'inline-block';
if (shade.paired) {
document.getElementById('btnUnpairShade').style.display = 'inline-block';
}
else {
document.getElementById('btnPairShade').style.display = 'inline-block';
}
this.setLinkedRemotesList(shade);
}
overlay.remove();
});
}
};
closeEditShade() {
let el = document.getElementById('somfyShade');
if (el) el.style.display = 'none';
document.getElementById('somfyMain').style.display = '';
//document.getElementById('somfyShade').style.display = 'none';
el = document.getElementById('divLinking');
if (el) el.remove();
el = document.getElementById('divPairing');
if (el) el.remove();
el = document.getElementById('frmSetRollingCode');
if (el) el.remove();
};
saveShade() {
let shadeId = parseInt(document.getElementById('spanShadeId').innerText, 10);
let obj = {
remoteAddress: parseInt(document.getElementsByName('shadeAddress')[0].value, 10),
name: document.getElementsByName('shadeName')[0].value,
upTime: parseInt(document.getElementsByName('shadeUpTime')[0].value, 10),
downTime: parseInt(document.getElementsByName('shadeDownTime')[0].value, 10),
shadeType: parseInt(document.getElementById('selShadeType').value, 10),
tiltTime: parseInt(document.getElementById('fldTiltTime').value, 10),
bitLength: parseInt(document.getElementById('selShadeBitLength').value, 10) || 56
};
if (obj.shadeType == 1) {
obj.hasTilt = document.getElementById('cbHasTilt').checked;
}
else obj.hasTilt = false;
let valid = true;
if (valid && (isNaN(obj.remoteAddress) || obj.remoteAddress < 1 || obj.remoteAddress > 16777215)) {
errorMessage(document.getElementById('fsSomfySettings'), 'The remote address must be a number between 1 and 16777215. This number must be unique for all shades.');
valid = false;
}
if (valid && (typeof obj.name !== 'string' || obj.name === '' || obj.name.length > 20)) {
errorMessage(document.getElementById('fsSomfySettings'), 'You must provide a name for the shade between 1 and 20 characters.');
valid = false;
}
if (valid && (isNaN(obj.upTime) || obj.upTime < 1 || obj.upTime > 4294967295)) {
errorMessage(document.getElementById('fsSomfySettings'), 'Up Time must be a value between 0 and 4,294,967,295 milliseconds. This is the travel time to go from full closed to full open.');
valid = false;
}
if (valid && (isNaN(obj.downTime) || obj.downTime < 1 || obj.downTime > 4294967295)) {
errorMessage(document.getElementById('fsSomfySettings'), '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 (valid) {
let overlay = waitMessage(document.getElementById('fsSomfySettings'));
if (isNaN(shadeId) || shadeId >= 255) {
// We are adding.
putJSON('/addShade', obj, (err, shade) => {
console.log(shade);
document.getElementById('spanShadeId').innerText = shade.shadeId;
document.getElementById('btnSaveShade').innerText = 'Save Shade';
overlay.remove();
document.getElementById('btnSaveShade').style.display = 'inline-block';
document.getElementById('btnLinkRemote').style.display = '';
if (shade.paired) {
document.getElementById('btnUnpairShade').style.display = 'inline-block';
}
else {
document.getElementById('btnPairShade').style.display = 'inline-block';
}
document.getElementById('btnSetRollingCode').style.display = 'inline-block';
});
}
else {
obj.shadeId = shadeId;
console.log(obj);
putJSON('/saveShade', obj, (err, shade) => {
console.log(shade);
// We are updating.
overlay.remove();
});
}
this.updateShadeList();
}
};
updateShadeList() {
let overlayCfg = waitMessage(document.getElementById('divShadeSection'));
let overlayControl = waitMessage(document.getElementById('divShadeControls'));
getJSON('/controller', (err, somfy) => {
overlayCfg.remove();
overlayControl.remove();
if (err) {
console.log(err);
serviceError(document.getElementById('fsSomfySettings'), err);
}
else {
console.log(somfy);
// Create the shades list.
this.setShadesList(somfy.shades);
}
});
};
deleteShade(shadeId) {
let valid = true;
if (isNaN(shadeId) || shadeId >= 255 || shadeId <= 0) {
errorMessage(document.getElementById('fsSomfySettings'), 'A valid shade id was not supplied.');
valid = false;
}
if (valid) {
promptMessage(document.getElementById('fsSomfySettings'), 'Are you sure you want to delete this shade?', () => {
clearErrors();
let overlay = waitMessage(document.getElementById('fsSomfySettings'));
putJSON('/deleteShade', { shadeId: shadeId }, (err, shade) => {
overlay.remove();
this.updateShadeList();
});
});
}
};
sendPairCommand(shadeId) {
putJSON('/pairShade', { shadeId: shadeId }, (err, shade) => {
if (err) {
console.log(err);
}
else {
console.log(shade);
document.getElementById('somfyMain').style.display = 'none';
document.getElementById('somfyShade').style.display = '';
document.getElementById('btnSaveShade').style.display = 'inline-block';
document.getElementById('btnLinkRemote').style.display = '';
document.getElementsByName('shadeAddress')[0].value = shade.remoteAddress;
document.getElementsByName('shadeName')[0].value = shade.name;
document.getElementsByName('shadeUpTime')[0].value = shade.upTime;
document.getElementsByName('shadeDownTime')[0].value = shade.downTime;
let ico = document.getElementById('icoShade');
ico.style.setProperty('--shade-position', `${shade.position}%`);
ico.setAttribute('data-shadeid', shade.shadeId);
if (shade.paired) {
document.getElementById('btnUnpairShade').style.display = 'inline-block';
document.getElementById('btnPairShade').style.display = 'none';
}
else {
document.getElementById('btnPairShade').style.display = 'inline-block';
document.getElementById('btnUnpairShade').style.display = 'none';
}
this.setLinkedRemotesList(shade);
document.getElementById('divPairing').remove();
}
});
};
sendUnpairCommand(shadeId) {
putJSON('/unpairShade', { shadeId: shadeId }, (err, shade) => {
if (err) {
console.log(err);
}
else {
console.log(shade);
document.getElementById('somfyMain').style.display = 'none';
document.getElementById('somfyShade').style.display = '';
document.getElementById('btnSaveShade').style.display = 'inline-block';
document.getElementById('btnLinkRemote').style.display = '';
document.getElementsByName('shadeAddress')[0].value = shade.remoteAddress;
document.getElementsByName('shadeName')[0].value = shade.name;
document.getElementsByName('shadeUpTime')[0].value = shade.upTime;
document.getElementsByName('shadeDownTime')[0].value = shade.downTime;
let ico = document.getElementById('icoShade');
ico.style.setProperty('--shade-position', `${shade.position}%`);
ico.setAttribute('data-shadeid', shade.shadeId);
if (shade.paired) {
document.getElementById('btnUnpairShade').style.display = 'inline-block';
document.getElementById('btnPairShade').style.display = 'none';
}
else {
document.getElementById('btnPairShade').style.display = 'inline-block';
document.getElementById('btnUnpairShade').style.display = 'none';
}
this.setLinkedRemotesList(shade);
document.getElementById('divPairing').remove();
}
});
};
setRollingCode(shadeId, rollingCode) {
let dlg = document.getElementById('frmSetRollingCode');
let overlay = waitMessage(dlg || document.getElementById('fsSomfySettings'));
putJSON('/setRollingCode', { shadeId: shadeId, rollingCode: rollingCode }, (err, shade) => {
overlay.remove();
if (err) {
serviceError(document.getElementById('fsSomfySettings'), err);
}
else {
if (dlg) dlg.remove();
}
});
}
openSetRollingCode(shadeId) {
let overlay = waitMessage(document.getElementById('fsSomfySettings'));
getJSON(`/shade?shadeId=${shadeId}`, (err, shade) => {
overlay.remove();
if (err) {
serviceError(document.getElementById('fsSomfySettings'), err);
}
else {
console.log(shade);
let div = document.createElement('div');
let html = `