Merge pull request #3291 from Aircoookie/onoff-nodes

Add ability to toggle devices from nodes view.
This commit is contained in:
Blaž Kristan 2023-07-14 12:41:15 +02:00 committed by GitHub
commit b1dfa1db61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2049 additions and 2001 deletions

View File

@ -9,9 +9,9 @@
#include <IPAddress.h> #include <IPAddress.h>
#define NODE_TYPE_ID_UNDEFINED 0 #define NODE_TYPE_ID_UNDEFINED 0
#define NODE_TYPE_ID_ESP8266 82 #define NODE_TYPE_ID_ESP8266 82 // should be 1
#define NODE_TYPE_ID_ESP32 32 #define NODE_TYPE_ID_ESP32 32 // should be 2
#define NODE_TYPE_ID_ESP32S2 33 #define NODE_TYPE_ID_ESP32S2 33 // etc
#define NODE_TYPE_ID_ESP32S3 34 #define NODE_TYPE_ID_ESP32S3 34
#define NODE_TYPE_ID_ESP32C3 35 #define NODE_TYPE_ID_ESP32C3 35
@ -23,7 +23,13 @@ struct NodeStruct
String nodeName; String nodeName;
IPAddress ip; IPAddress ip;
uint8_t age; uint8_t age;
uint8_t nodeType; union {
uint8_t nodeType; // a waste of space as we only have 5 types
struct {
uint8_t type : 7; // still a waste of space (4 bits would be enough and future-proof)
bool on : 1;
};
};
uint32_t build; uint32_t build;
NodeStruct() : age(0), nodeType(0), build(0) NodeStruct() : age(0), nodeType(0), build(0)

View File

@ -134,7 +134,7 @@ button {
.off { .off {
color: var(--c-6) !important; color: var(--c-6) !important;
cursor: default !important; /* cursor: default !important; */
} }
.top .icons, .bot .icons { .top .icons, .bot .icons {
@ -1010,7 +1010,7 @@ textarea {
width: 50px !important; width: 50px !important;
} }
.segname, .pname { .segname, .pname, .bname {
white-space: nowrap; white-space: nowrap;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
@ -1020,6 +1020,9 @@ textarea {
max-width: 170px; max-width: 170px;
position: relative; position: relative;
} }
.bname {
padding: 0 24px;
}
.segname .flr, .pname .flr { .segname .flr, .pname .flr {
transform: rotate(0deg); transform: rotate(0deg);

View File

@ -826,6 +826,7 @@ function populateSegments(s)
resetUtil(noNewSegs); resetUtil(noNewSegs);
if (gId('selall')) gId('selall').checked = true; if (gId('selall')) gId('selall').checked = true;
for (var i = 0; i <= lSeg; i++) { for (var i = 0; i <= lSeg; i++) {
if (!gId(`seg${i}`)) continue;
updateLen(i); updateLen(i);
updateTrail(gId(`seg${i}bri`)); updateTrail(gId(`seg${i}bri`));
gId(`segr${i}`).classList.add("hide"); gId(`segr${i}`).classList.add("hide");
@ -1004,10 +1005,15 @@ function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', e
function btype(b) function btype(b)
{ {
switch (b) { switch (b) {
case 2:
case 32: return "ESP32"; case 32: return "ESP32";
case 3:
case 33: return "ESP32-S2"; case 33: return "ESP32-S2";
case 4:
case 34: return "ESP32-S3"; case 34: return "ESP32-S3";
case 5:
case 35: return "ESP32-C3"; case 35: return "ESP32-C3";
case 1:
case 82: return "ESP8266"; case 82: return "ESP8266";
} }
return "?"; return "?";
@ -1028,8 +1034,9 @@ function populateNodes(i,n)
n.nodes.sort((a,b) => (a.name).localeCompare(b.name)); n.nodes.sort((a,b) => (a.name).localeCompare(b.name));
for (var o of n.nodes) { for (var o of n.nodes) {
if (o.name) { if (o.name) {
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');">${bname(o)}</button>`; let onoff = `<i class="icons e-icon flr ${o.type&0x80?'':'off'}" onclick="rmtTgl('${o.ip}',this);"">&#xe08f;</i>`;
urows += inforow(url,`${btype(o.type)}<br><i>${o.vid==0?"N/A":o.vid}</i>`); var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');"><div class="bname">${bname(o)}</div>${o.vid<2307130?'':onoff}</button>`;
urows += inforow(url,`${btype(o.type&0x7F)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
nnodes++; nnodes++;
} }
} }
@ -2045,14 +2052,14 @@ function tglSegn(s)
function selSegAll(o) function selSegAll(o)
{ {
var obj = {"seg":[]}; var obj = {"seg":[]};
for (let i=0; i<=lSeg; i++) obj.seg.push({"id":i,"sel":o.checked}); for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":o.checked});
requestJson(obj); requestJson(obj);
} }
function selSegEx(s) function selSegEx(s)
{ {
var obj = {"seg":[]}; var obj = {"seg":[]};
for (let i=0; i<=lSeg; i++) obj.seg.push({"id":i,"sel":(i==s)}); for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":(i==s)});
obj.mainseg = s; obj.mainseg = s;
requestJson(obj); requestJson(obj);
} }
@ -2070,7 +2077,7 @@ function selGrp(g)
event.stopPropagation(); event.stopPropagation();
var sel = gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`); var sel = gId(`segcont`).querySelectorAll(`div[data-set="${g}"]`);
var obj = {"seg":[]}; var obj = {"seg":[]};
for (let i=0; i<=lSeg; i++) obj.seg.push({"id":i,"sel":false}); for (let i=0; i<=lSeg; i++) if (gId(`seg${i}`)) obj.seg.push({"id":i,"sel":false});
if (sel) for (let s of sel||[]) { if (sel) for (let s of sel||[]) {
let i = parseInt(s.id.substring(3)); let i = parseInt(s.id.substring(3));
obj.seg[i] = {"id":i,"sel":true}; obj.seg[i] = {"id":i,"sel":true};
@ -2571,6 +2578,24 @@ function setBalance(b)
requestJson(obj); requestJson(obj);
} }
function rmtTgl(ip,i) {
event.preventDefault();
event.stopPropagation();
fetch(`http://${ip}/win&T=2`, {method: 'get'})
.then((r)=>{
return r.text();
})
.then((t)=>{
let c = (new window.DOMParser()).parseFromString(t, "text/xml");
// perhaps just i.classList.toggle("off"); would be enough
if (c.getElementsByTagName('ac')[0].textContent === "0") {
i.classList.add("off");
} else {
i.classList.remove("off");
}
});
}
var hc = 0; var hc = 0;
setInterval(()=>{ setInterval(()=>{
if (!isInfo) return; if (!isInfo) return;

File diff suppressed because it is too large Load Diff

View File

@ -104,6 +104,7 @@ void stateUpdated(byte callMode) {
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode); if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
if (bri != briOld && nodeBroadcastEnabled) sendSysInfoUDP(); // update on state
//set flag to update ws and mqtt //set flag to update ws and mqtt
interfaceUpdateCallMode = callMode; interfaceUpdateCallMode = callMode;

View File

@ -669,6 +669,7 @@ void sendSysInfoUDP()
#else #else
data[38] = NODE_TYPE_ID_UNDEFINED; data[38] = NODE_TYPE_ID_UNDEFINED;
#endif #endif
if (bri) data[38] |= 0x80U; // add on/off state
data[39] = ip[3]; // unit ID == last IP number data[39] = ip[3]; // unit ID == last IP number
uint32_t build = VERSION; uint32_t build = VERSION;

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2306270 #define VERSION 2307130
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG