In Anlehnung an die Views Skript Status und Adapter Status mit den Material Design Widgets habe ich mir eine View mit den Geräten aus dem TR064-Adapter erstellt, siehe nachfolgender Screenshot.
Github: Link
Voraussetzung:
- Material Design Widgets v0.2.66
Funktionen:
- Anzeige des Netzwerkstatus euer Geräte aus dem TR064-Adapter (online, offline)
- Anzeige von Werten des Adapters (IP-Adresse, letzte An- und Abmeldung)
- Einträge, die mit einem Link hinterlegt wurden, können per Klick auf das Symbol in einem neuen Browser-Tab geöffnet werden
- Sortier und Filter Funktion
- Einstellungen, siehe im Skript Sektion Einstellungen, Funktion der Einstellungen ist dort als Kommentar beschrieben.
View zum Importieren (für Material Design Icons):
{
"settings": {
"style": {
"background_class": ""
},
"theme": "redmond",
"sizex": "",
"sizey": "",
"gridSize": "",
"useBackground": false,
"snapType": null
},
"widgets": {
"e00001": {
"tpl": "tplHtml",
"data": {
"g_fixed": false,
"g_visibility": false,
"g_css_font_text": false,
"g_css_background": true,
"g_css_shadow_padding": false,
"g_css_border": false,
"g_gestures": false,
"g_signals": false,
"g_last_change": false,
"visibility-cond": "==",
"visibility-val": 1,
"visibility-groups-action": "hide",
"refreshInterval": "0",
"signals-cond-0": "==",
"signals-val-0": true,
"signals-icon-0": "/vis/signals/lowbattery.png",
"signals-icon-size-0": 0,
"signals-blink-0": false,
"signals-horz-0": 0,
"signals-vert-0": 0,
"signals-hide-edit-0": false,
"signals-cond-1": "==",
"signals-val-1": true,
"signals-icon-1": "/vis/signals/lowbattery.png",
"signals-icon-size-1": 0,
"signals-blink-1": false,
"signals-horz-1": 0,
"signals-vert-1": 0,
"signals-hide-edit-1": false,
"signals-cond-2": "==",
"signals-val-2": true,
"signals-icon-2": "/vis/signals/lowbattery.png",
"signals-icon-size-2": 0,
"signals-blink-2": false,
"signals-horz-2": 0,
"signals-vert-2": 0,
"signals-hide-edit-2": false,
"lc-type": "last-change",
"lc-is-interval": true,
"lc-is-moment": false,
"lc-format": "",
"lc-position-vert": "top",
"lc-position-horz": "right",
"lc-offset-vert": 0,
"lc-offset-horz": 0,
"lc-font-size": "12px",
"lc-font-family": "",
"lc-font-style": "",
"lc-bkg-color": "",
"lc-color": "",
"lc-border-width": "0",
"lc-border-style": "",
"lc-border-color": "",
"lc-border-radius": 10,
"lc-zindex": 0
},
"style": {
"left": "0",
"top": "0",
"width": "100%",
"background-color": "#44739e",
"height": "50px",
"z-index": "0"
},
"widgetSet": "basic"
},
"e00002": {
"tpl": "tplVis-materialdesign-Select",
"data": {
"oid": "0_userdata.0.vis.NetzwerkStatus.sortMode",
"g_fixed": false,
"g_visibility": false,
"g_css_font_text": false,
"g_css_background": false,
"g_css_shadow_padding": false,
"g_css_border": false,
"g_gestures": false,
"g_signals": false,
"g_last_change": false,
"visibility-cond": "==",
"visibility-val": 1,
"visibility-groups-action": "hide",
"inputType": "text",
"inputLayout": "regular",
"showInputMessageAlways": "true",
"showInputCounter": false,
"clearIconShow": false,
"listDataMethod": "jsonStringObject",
"countSelectItems": "1",
"listPosition": "bottom",
"showSelectedIcon": "prepend-inner",
"showValue": false,
"signals-cond-0": "==",
"signals-val-0": true,
"signals-icon-0": "/vis/signals/lowbattery.png",
"signals-icon-size-0": 0,
"signals-blink-0": false,
"signals-horz-0": 0,
"signals-vert-0": 0,
"signals-hide-edit-0": false,
"signals-cond-1": "==",
"signals-val-1": true,
"signals-icon-1": "/vis/signals/lowbattery.png",
"signals-icon-size-1": 0,
"signals-blink-1": false,
"signals-horz-1": 0,
"signals-vert-1": 0,
"signals-hide-edit-1": false,
"signals-cond-2": "==",
"signals-val-2": true,
"signals-icon-2": "/vis/signals/lowbattery.png",
"signals-icon-size-2": 0,
"signals-blink-2": false,
"signals-horz-2": 0,
"signals-vert-2": 0,
"signals-hide-edit-2": false,
"lc-type": "last-change",
"lc-is-interval": true,
"lc-is-moment": false,
"lc-format": "",
"lc-position-vert": "top",
"lc-position-horz": "right",
"lc-offset-vert": 0,
"lc-offset-horz": 0,
"lc-font-size": "12px",
"lc-font-family": "",
"lc-font-style": "",
"lc-bkg-color": "",
"lc-color": "",
"lc-border-width": "0",
"lc-border-style": "",
"lc-border-color": "",
"lc-border-radius": 10,
"lc-zindex": 0,
"inputLabelText": "Sortieren nach",
"inputLabelColor": "#ffffff",
"inputLabelFontFamily": "RobotoCondensed-LightItalic",
"collapseIconColor": "#ffffff",
"collapseIconSize": "",
"jsonStringObject": "[\n\t{\n\t\t\"text\": \"Gerätename\",\n\t\t\"value\": \"name\",\n\t\t\"icon\": \"sort-alphabetical\"\n\t},\n\t{\n\t\t\"text\": \"IP Adresse\",\n\t\t\"value\": \"ipAddress\",\n\t\t\"icon\": \"ip\"\n\t}\n]",
"listPositionOffset": true,
"inputLayoutBackgroundColor": "transparent",
"inputLabelColorSelected": "#ffffff",
"inputTranslateX": "-15",
"clearIcon": "",
"inputLayoutBorderColorHover": "#ffffff",
"inputLayoutBorderColorSelected": "#ffffff",
"inputLayoutBorderColor": "#a1a1a1",
"listItemFontColor": "",
"inputTextColor": "#ffffff",
"inputTextFontFamily": "RobotoCondensed-LightItalic",
"prepandIcon": "",
"prepandIconColor": "",
"prepandIconSize": "",
"prepandInnerIcon": "",
"prepandInnerIconColor": "#ffffff",
"prepandInnerIconSize": "18",
"collapseIcon": "",
"inputTranslateY": "-12",
"listIconSelectedColor": "#44739e",
"listIconColor": "",
"appendOuterIcon": "",
"appendOuterIconSize": "2",
"listItemFont": "RobotoCondensed-Regular",
"listItemRippleEffectColor": "",
"inputLayoutBackgroundColorSelected": "",
"inputLayoutBackgroundColorHover": ""
},
"style": {
"left": "10px",
"top": "0px",
"z-index": "1",
"width": "calc(50% - 20px)",
"height": "40px"
},
"widgetSet": "materialdesign"
},
"e00003": {
"tpl": "tplVis-materialdesign-Select",
"data": {
"oid": "0_userdata.0.vis.NetzwerkStatus.filterMode",
"g_fixed": false,
"g_visibility": false,
"g_css_font_text": false,
"g_css_background": false,
"g_css_shadow_padding": false,
"g_css_border": false,
"g_gestures": false,
"g_signals": false,
"g_last_change": false,
"visibility-cond": "==",
"visibility-val": 1,
"visibility-groups-action": "hide",
"inputType": "text",
"inputLayout": "regular",
"showInputMessageAlways": "true",
"showInputCounter": false,
"clearIconShow": true,
"listDataMethod": "jsonStringObject",
"countSelectItems": "1",
"listPosition": "bottom",
"showSelectedIcon": "prepend-inner",
"showValue": false,
"signals-cond-0": "==",
"signals-val-0": true,
"signals-icon-0": "/vis/signals/lowbattery.png",
"signals-icon-size-0": 0,
"signals-blink-0": false,
"signals-horz-0": 0,
"signals-vert-0": 0,
"signals-hide-edit-0": false,
"signals-cond-1": "==",
"signals-val-1": true,
"signals-icon-1": "/vis/signals/lowbattery.png",
"signals-icon-size-1": 0,
"signals-blink-1": false,
"signals-horz-1": 0,
"signals-vert-1": 0,
"signals-hide-edit-1": false,
"signals-cond-2": "==",
"signals-val-2": true,
"signals-icon-2": "/vis/signals/lowbattery.png",
"signals-icon-size-2": 0,
"signals-blink-2": false,
"signals-horz-2": 0,
"signals-vert-2": 0,
"signals-hide-edit-2": false,
"lc-type": "last-change",
"lc-is-interval": true,
"lc-is-moment": false,
"lc-format": "",
"lc-position-vert": "top",
"lc-position-horz": "right",
"lc-offset-vert": 0,
"lc-offset-horz": 0,
"lc-font-size": "12px",
"lc-font-family": "",
"lc-font-style": "",
"lc-bkg-color": "",
"lc-color": "",
"lc-border-width": "0",
"lc-border-style": "",
"lc-border-color": "",
"lc-border-radius": 10,
"lc-zindex": 0,
"inputLabelText": "Filtern nach",
"inputLabelColor": "#ffffff",
"inputLabelFontFamily": "RobotoCondensed-LightItalic",
"collapseIconColor": "#ffffff",
"collapseIconSize": "",
"jsonStringObject": "[\n\t{\n\t\t\"text\": \"online\",\n\t\t\"value\": \"online\",\n\t\t\"icon\": \"network\"\n\t},\n\t{\n\t\t\"text\": \"offline\",\n\t\t\"value\": \"offline\",\n\t\t\"icon\": \"network-off-outline\"\n\t}\n]",
"listPositionOffset": true,
"inputLayoutBackgroundColor": "transparent",
"inputLabelColorSelected": "#ffffff",
"inputTranslateX": "-15",
"clearIcon": "",
"inputLayoutBorderColorHover": "#ffffff",
"inputLayoutBorderColorSelected": "#ffffff",
"inputLayoutBorderColor": "#a1a1a1",
"listItemFontColor": "",
"inputTextColor": "#ffffff",
"inputTextFontFamily": "RobotoCondensed-LightItalic",
"prepandIcon": "",
"prepandIconColor": "",
"prepandIconSize": "",
"prepandInnerIcon": "",
"prepandInnerIconColor": "#ffffff",
"prepandInnerIconSize": "18",
"collapseIcon": "",
"inputTranslateY": "-12",
"listIconSelectedColor": "#44739e",
"listIconColor": "",
"appendOuterIcon": "",
"appendOuterIconSize": "2",
"listItemFont": "RobotoCondensed-Regular",
"listItemRippleEffectColor": "",
"inputLayoutBackgroundColorSelected": "",
"inputLayoutBackgroundColorHover": "",
"clearIconColor": "#ffffff"
},
"style": {
"left": "calc(50% + 10px)",
"top": "0px",
"z-index": "1",
"width": "calc(50% - 20px)",
"height": "40px"
},
"widgetSet": "materialdesign"
},
"e00004": {
"tpl": "tplVis-materialdesign-Icon-List",
"data": {
"g_fixed": false,
"g_visibility": false,
"g_css_font_text": false,
"g_css_background": false,
"g_css_shadow_padding": false,
"g_css_border": false,
"g_gestures": false,
"g_signals": false,
"g_last_change": false,
"visibility-cond": "==",
"visibility-val": 1,
"visibility-groups-action": "hide",
"wrapItems": true,
"listItemDataMethod": "jsonStringObject",
"countListItems": "1",
"vibrateOnMobilDevices": "50",
"listLayout": "card",
"itemLayout": "horizontal",
"listType0": "text",
"showValueLabel0": "true",
"listType1": "text",
"showValueLabel1": "true",
"signals-cond-0": "==",
"signals-val-0": true,
"signals-icon-0": "/vis/signals/lowbattery.png",
"signals-icon-size-0": 0,
"signals-blink-0": false,
"signals-horz-0": 0,
"signals-vert-0": 0,
"signals-hide-edit-0": false,
"signals-cond-1": "==",
"signals-val-1": true,
"signals-icon-1": "/vis/signals/lowbattery.png",
"signals-icon-size-1": 0,
"signals-blink-1": false,
"signals-horz-1": 0,
"signals-vert-1": 0,
"signals-hide-edit-1": false,
"signals-cond-2": "==",
"signals-val-2": true,
"signals-icon-2": "/vis/signals/lowbattery.png",
"signals-icon-size-2": 0,
"signals-blink-2": false,
"signals-horz-2": 0,
"signals-vert-2": 0,
"signals-hide-edit-2": false,
"lc-type": "last-change",
"lc-is-interval": true,
"lc-is-moment": false,
"lc-format": "",
"lc-position-vert": "top",
"lc-position-horz": "right",
"lc-offset-vert": 0,
"lc-offset-horz": 0,
"lc-font-size": "12px",
"lc-font-family": "",
"lc-font-style": "",
"lc-bkg-color": "",
"lc-color": "",
"lc-border-width": "0",
"lc-border-style": "",
"lc-border-color": "",
"lc-border-radius": 10,
"lc-zindex": 0,
"maxItemsperRow": "8",
"json_string_oid": "0_userdata.0.vis.NetzwerkStatus.jsonList",
"labelFontSize": "22",
"subLabelFontSize": "14",
"labelFontFamily": "RobotoCondensed-Regular",
"horizontalIconContainerWidth": "70",
"buttonHeight": "",
"iconHeight": "35",
"iconItemMinWidth": "300",
"buttonLayout": "round",
"autoLockAfter": "10",
"lockIconTop": "5",
"lockIconLeft": "5",
"lockFilterGrayscale": "30",
"lockApplyOnlyOnImage": "true",
"subLabelFontFamily": "RobotoCondensed-BoldItalic",
"subLabelFontColor": "black",
"verticalIconContainerHeight": "70"
},
"style": {
"left": "",
"top": "50px",
"width": "100%",
"height": "calc(100% - 50px)",
"overflow-y": "auto"
},
"widgetSet": "materialdesign"
}
},
"name": "330_System_NetzwerkStatus",
"filterList": []
}
Skript (mit Material Design Icons):
/* Versionshistorie:
*
* 1.0.2:
* - neu: Anzeige der letzten An- und Abmeldung
* - neu: Verwendung eigener Bilder möglich
*
* 1.0.1:
* - neu: In dem Mapping der IP-Adressen kann jetzt eine URL vergeben werden ('http' oder direkt eine spezifische URL)
* - geändert: Styling der Details
* - entfernt: MAC-Adresse
*
* 1.0.0:
* - Initial Release
*/
const moment = require("moment");
// Skript Einstellungen *************************************************************************************************************************************************
let dpList = '0_userdata.0.vis.NetzwerkStatus.jsonList'; // Datenpunkt für IconList Widget (Typ: Zeichenkette (String))
let dpSortMode = '0_userdata.0.vis.NetzwerkStatus.sortMode'; // Datenpunkt für Sortieren (Typ: Zeichenkette (String))
let dpFilterMode = '0_userdata.0.vis.NetzwerkStatus.filterMode'; // Datenpunkt für Filter (Typ: Zeichenkette (String))
const checkInterval = 30; // Interval wie oft Status der Skripte aktualisiert werden soll (in Sekunden)
let sprache = 'de'; // Sprache für formatierung letzte Änderung
let formatierungLastChange = "ddd DD.MM - HH:mm"; // Formatierung letzte Änderung -> siehe momentjs library
let imagePath = '/vis.0/myImages/networkDevices/' // Pfad zu den verwendeten Bildern (bitte über den VIS Dateimanager hochladen)
// nach Variable imagePath suchen und die entsprechenden Zeilen aus- bzw. einkommentieren
// Das Bild (Dateiformat png) in der Mapping-Liste hinterlegen
let defaultImage = 'ip-network-outline'; // Standardbild, falls kein Bild angegeben wurde (Material Design Icons)
//let defaultImage = `${imagePath}default.png`; // Standardbild, falls kein Bild angegeben wurde (eigenes Bild)
let farbeGeraetOnline = 'green'; // Status Bar Farbe wenn Geräte online ist
let farbeGeraetOffline = 'FireBrick'; // Status Bar Farbe wenn Geräte offline ist
let sortResetAfter = 120; // Sortierung nach X Sekunden auf sortReset zurücksetzen (0=deaktiviert)
let sortReset = 'name' // Sortierung auf die zurückgesetzt werden soll
let filterResetAfter = 120; // Filter nach X Sekunden zurücksetzen (0=deaktiviert)
const deviceNames =
[{ ip: "192.168.178.20", alias: "NAS", image: "nas", link: "http://diskstation:5000" },
{ ip: "192.168.178.37", alias: "Gosund Küchenlicht", image: "toggle-switch-outline", link: "http" },
{ ip: "192.168.178.45", alias: "Homematic Raspi", image: "server", link: "http" },
{ ip: "192.168.178.32", alias: "OnePlus 3T", image: "cellphone" }
];
// **********************************************************************************************************************************************************************
// Fomate für moment Lib
moment.locale(sprache);
// auf Änderungen aktiver Skripts hören
let activeSelector = `[id=tr-064.*.devices.*.active]`;
let deviceActiveList = $(activeSelector);
if (deviceActiveList.length === 0) {
// Fehlermeldung ausgeben, wenn selector kein result liefert
console.error(`no result for selector '${activeSelector}'`)
} else {
// listener nur für Änderung bei alive
deviceActiveList.on(netzwerkStatus);
}
// auf Änderungen der Sortieung hören
on({ id: dpSortMode, change: 'any' }, netzwerkStatus);
on({ id: dpSortMode, change: 'any' }, resetSort);
// // auf Änderungen der Filter hören
on({ id: dpFilterMode, change: 'any' }, netzwerkStatus);
on({ id: dpFilterMode, change: 'any' }, resetFilter);
// Funktion adapterStatus alle x Sekunden ausführen
schedule('*/' + checkInterval + ' * * * * *', netzwerkStatus);
function netzwerkStatus() {
try {
let deviceList = [];
for (var i = 0; i <= deviceActiveList.length - 1; i++) {
let id = deviceActiveList[i].replace('.active', '');
let obj = getObject(id);
let pattern = /(?:\d{1,3}\.){3}\d{1,3}/i;
let ipAddress = obj.common.name.match(pattern)[0];
let image = defaultImage;
let deviceName = obj.common.name.replace(/ \((?:\d{1,3}\.){3}\d{1,3}\)/g, '');
let device = deviceNames.find(element => element.ip == ipAddress);
let listType = 'text';
let buttonLink = '';
if(device) {
deviceName = device.alias;
image = device.image;
//image = `${imagePath}${device.image}.png`;
if(device.link) {
listType = 'buttonLink';
if(device.link == 'http') {
buttonLink = `http://${ipAddress}`;
} else {
buttonLink = device.link;
}
}
}
let macAddress = obj.native.mac;
let imageColor = 'black';
let statusBarColor = farbeGeraetOffline;
let status = 2;
if (getState(deviceActiveList[i]).val) {
statusBarColor = farbeGeraetOnline;
status = 1;
}
if(listType === 'buttonLink') {
deviceName = `<span style="text-decoration: underline">${deviceName}</span>`
}
let lastSignIn = 'noch nicht angemeldet';
let lastSignOff = 'noch nicht abgemeldet';
// Letzte Anmeldung auslesen
if(existsState(id + '.lastActive')) {
lastSignIn = 'angemeldet seit: ' + moment((getState(id + '.lastActive').val)).format("DD.MM.YY HH:mm:ss");
}
// Letzte Abmeldung auslesen
if(existsState(id + '.lastInactive')) {
lastSignOff = 'abgemeldet seit: ' + moment((getState(id + '.lastInactive').val)).format("DD.MM.YY HH:mm:ss");
}
let subText = `<div style="color: black; font-family: RobotoCondensed-BoldItalic">${ipAddress}</div>
<div style="color: grey; font-family: RobotoCondensed-Regular">${lastSignIn}</div>
<div style="color: grey; font-family: RobotoCondensed-Regular">${lastSignOff}</div>`
deviceList.push({
text: deviceName,
subText: subText,
statusBarColor: statusBarColor,
image: image,
imageColor: imageColor,
listType: listType,
buttonLink: buttonLink,
showValueLabel: false,
name: deviceName,
ipAddress: ipAddress,
status: status
});
}
let sortMode = myHelper().getStateValueIfExist(dpSortMode, 'name');
if (sortMode === 'name' || sortMode === 'ipAddress') {
deviceList.sort(function (a, b) {
return a[sortMode].toLowerCase() == b[sortMode].toLowerCase() ? 0 : +(a[sortMode].toLowerCase() > b[sortMode].toLowerCase()) || -1;
});
} else if (sortMode === 'status') {
deviceList.sort(function (a, b) {
return a[sortMode] == b[sortMode] ? 0 : +(a[sortMode] < b[sortMode]) || -1;
});
} else {
// default: nach name sortieren
sortMode = 'name'
deviceList.sort(function (a, b) {
return a[sortMode].toLowerCase() == b[sortMode].toLowerCase() ? 0 : +(a[sortMode].toLowerCase() > b[sortMode].toLowerCase()) || -1;
});
}
let filterMode = myHelper().getStateValueIfExist(dpFilterMode, null);
if (filterMode && filterMode !== null && filterMode !== '') {
if (filterMode === 'offline') {
deviceList = deviceList.filter(function (item) {
return item.status === 2;
});
} else if (filterMode === 'online') {
deviceList = deviceList.filter(function (item) {
return item.status === 1;
});
}
}
let result = JSON.stringify(deviceList);
if (getState(dpList) !== result) {
setState(dpList, result, true);
}
} catch (err) {
console.error(`[netzwerkStatus] error: ${err.message}, stack: ${err.stack}`);
}
}
function resetSort() {
let sortMode = myHelper().getStateValueIfExist(dpSortMode, null);
if (sortResetAfter > 0) {
setTimeout(function () {
if (sortMode !== null && sortMode === myHelper().getStateValueIfExist(dpSortMode, null)) {
setState(dpSortMode, sortReset);
}
}, sortResetAfter * 1000);
}
}
function resetFilter() {
let filterMode = myHelper().getStateValueIfExist(dpFilterMode, null);
if (filterResetAfter > 0) {
setTimeout(function () {
if (filterMode !== null && filterMode === myHelper().getStateValueIfExist(dpFilterMode, null)) {
setState(dpFilterMode, '');
}
}, filterResetAfter * 1000);
}
}
// Beim Staren des Skriptes Adapter Status abrufen
netzwerkStatus();
function myHelper() {
return {
getStateValueIfExist: function (id, nullValue = undefined, prepand = '', append = '') {
if (existsState(id)) {
return prepand + getState(id).val + append;
} else {
return nullValue;
}
},
getCommonPropertyIfExist: function (object, prop, nullValue = undefined, prepand = '', append = '') {
if (myHelper().checkCommonPropertyExist(object, prop)) {
return prepand + object.common[prop] + append;
} else {
return nullValue;
}
},
checkCommonPropertyExist: function (object, prop) {
if (object && object.common && object.common[prop]) {
return true;
} else {
return false;
}
}
}
}
Folgende NPM-Module müsst ihr in eurer Javascript-Instanz hinzufügen: moment, moment-timezone, moment-duration-format
Außerdem bitte die Einstellung "Erlaube das Kommando setObject" in eurer Javascript-Instanz aktivieren