// September 2019 @liv-in-sky durch viel vorarbeit von @thewhobox (api verbindung) // Definition Login const unifi_username = "x"; const unifi_password = "xxxxxx"; const unifi_controller = "https://192.xxx.xxx.xxx:8443"; // DEFINITION der zu anzeigenden Netzwerke am besten bis auf id und smart alle gleich setzen: beispiel: const wifis = { "WLAN_Dragon1": { name: "WLAN_Dragon1", id: "yyyyyyyyyyyyyyyyyyyyy", desc: "WLAN_Dragon1", smart: "WLAN_Dragon1" } , "WLAN_DragonGuest": { name: "WLAN_DragonGuest", id: "yyyyyyyyyyyyyyyyyyyy", desc: "WLAN_DragonGuest", smart: "WLAN_DragonGuest" } } //Überwachte Geräte beim Abschalten - Beispiele überschreiben! const fastLane = { "Galaxy-S9": { name: "Galaxy-S9"} , "GalaxyTabS2": { name: "GalaxyTabS2"}, "ESP_C75826" : {name: "ESP_C75826"} } let wifiDPs = []; let fastLaneDPs = []; let fastLaneDPsAlt=[]; const request = require('request-promise-native').defaults({ rejectUnauthorized: false }); var fs = require('fs') const datei = "/opt/iobroker/iobroker-data/files/iqontrol/htmlvoucher.html"; const datei2 = "/opt/iobroker/iobroker-data/files/iqontrol/htmlclients.html"; let writeFile = true; let writeFileVar = 0; let writeClientTable = true; let writeAnwesenheit = true; let listeDatenpunkte = []; let listeDatenpunkteNew = []; let listeDatenpunkteAlt = []; // Datenpunkte Hauptpfad wählen - WICHTIG muss mit der javascript instanz, inder das script läuft zusammenpassen const dpPrefix = "javascript.2."; // Abfragezyklus definieren const abfragezyklus =20000; // es ist nicht zu empfehlen unter 20000 (20 sekunden) zu gehen //HIER Einstellungen : EIN-AUSSCHALTEN Vouchers, iqontrol-Datei erstellen, anwesenheitskontrolle-clientpflege let iqontrol = true; let anwesenheit = true; // beim setzen von true auf false die verzeichnisstruktur unter iobroker-objects "von hand" löschen let vouchers = true; // Hier Definition iqontrol-Style für Popup const format = "Voucher"; const format2 = "Clients
"; //-----------------AB HIER NICHTS MEHR ÄNDERN------------------------ let cookies = []; let loggedIn = false; let debug = false; if ( !anwesenheit) fs.writeFileSync(datei2,("variable anwesenheit und/oder iqontrol ist nicht im unifiscript aktiviert - auf true setzen")); if ( !vouchers) fs.writeFileSync(datei,("variable vouchers und/oder iqontrol ist nicht im unifiscript aktiviert - auf true setzen")); //fastlane reset for(var fastLane_member in fastLane) { fastLaneDPsAlt.push(0); } //Erstelle Datenpunkte für die WLANs automatisch for(let wifi_name in wifis) { wifiDPs.push(dpPrefix + "WLANUnifi." + wifis[wifi_name].name); createState(dpPrefix + "WLANUnifi."+ wifi_name, { name: wifis[wifi_name].desc, role: 'state', read: true, write: true, type: "boolean", smartName: { de: wifis[wifi_name].smart, smartType: "SWITCH" } });} if (true) { createState(dpPrefix + "WLANUnifi.Wifi_Clients", { name: 'Unifi Wifi Clients Table', role: 'string', read: true, write: true, });} if (vouchers) { createState(dpPrefix + "WLANUnifi.Wifi_Vouchers", { name: 'Unifi Wifi Vouchers_Table', role: 'string', read: true, write: true, }); for (var i = 1; i < 21; i++) { var x=i.toString(); if (i<10) x="0"+x; createState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+x, { name: 'Unifi Voucher_Code'+x, role: 'string', read: true, write: true, }); createState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+x+".code"+x, { name: 'Unifi Voucher_Code_code'+x, role: 'string', read: true, write: true, }); createState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+x+".erstellt", { name: 'Unifi Voucher_Code_erstellt'+x, role: 'string', read: true, write: true, }); createState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+x+".dauer", { name: 'Unifi Voucher_Code_duration'+x, role: 'string', read: true, write: true, }); createState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+x+".abgelaufen", { name: 'Unifi Voucher_Code_expires'+x, role: 'string', read: true, write: true, }); }} createState(dpPrefix + "WLANUnifi.Wifi_Clients_Anzahl", { name: 'Wifi_Clients_Anzahl', desc: 'Wifi_Clients_Anzahl', type: 'number', unit: '', min: '0', max: '100', role: '',read: true, write: true }); if (vouchers) createState(dpPrefix + "WLANUnifi.Wifi_Vouchers_Anzahl", { name: 'Wifi_Vouchers_Anzahl', desc: 'Wifi_Vouchers_Anzahl', type: 'number', unit: '', min: '0', max: '100', role: '',read: true, write: true }); function dlog(message) { if(debug) console.log(message); } //-----------------------------------------LOGIN--------------------------------------------------------------- async function login() { return new Promise(async (resolve, reject) => { let resp = await request.post({ resolveWithFullResponse: true, url: unifi_controller + "/api/login", body: JSON.stringify({ username: unifi_username, password: unifi_password }), headers: { 'Content-Type': 'application/json' } }).catch((e) => { dlog("login: reject"), reject(e) }); if(resp != null) { dlog("login: login war erfolgreich! " + ((resp.headers && resp.headers.hasOwnProperty("set-cookie")) ? "Mit Cookies":"Ohne Cookies")); if(resp.headers && resp.headers.hasOwnProperty("set-cookie")) { let set_cookies = resp.headers["set-cookie"]; for(i = 0; i < set_cookies.length; i++) { let cookie = set_cookies[i]; cookie = cookie.split(";")[0]; cookies.push(cookie); } } else { dlog("login: no cookies to set!") } loggedIn = true; resolve(); } else { dlog("login: rejected") reject("resp = null"); } }); } async function dlogout() { return new Promise(async (resolve, reject) => { let resp = await request.get({ url: unifi_controller + "/dlogout", headers: { Cookie: cookies.join("; ") } }).catch((e) => reject(e)); if(resp != null) { dlog("Du bist nun ausgedloggt."); dlog(resp); resolve(); } else { reject("resp = null"); } }); } //-----------------------------------------STATUS WIFI --------------------------------------------------------- //Updatet status vom Wifi //wifi: wifi object aus der konstanten wifis async function getStatus(wifi) { dlog("BIN IN STATUS"); return new Promise(async (resolve, reject) => { dlog("nur mal so"); if (!loggedIn) await login().catch((e) => reject(e)); let resp = await request.get({ url: unifi_controller + "/api/s/default/rest/wlanconf/" + wifi.id, headers: { Cookie: cookies.join("; ") } }).catch((e) => { dlog("getStatus reject " + e); reject(e) }); dlog("got response " + JSON.stringify(resp)); resp = JSON.parse(resp); let wlanOn = resp.data[0].enabled; dlog("WLAN " + wifi.name + " ist: " + (wlanOn ? "an" : "aus")); if (resp != null && resp.meta && resp.meta.rc == "ok") { dlog("Status erfolgreich geholt!"); dlog(resp); let wlanOn = resp.data[0].enabled; dlog("WLAN ist: " + (wlanOn ? "an" : "aus")); setStateDelayed(dpPrefix + "WLANUnifi." + wifi.name, wlanOn, 200); resolve(wlanOn); } else { dlog("nicht ok...") reject(JSON.stringify(resp)); }dlog("BIN aus STATUS raus"); }); } //-----------------------------------------GETCLIENTS--------------------------------------------------------------- async function getClients() { dlog("BIN IN CLIENTS"); return new Promise(async (resolve, reject) => { dlog("nur mal so"); if(!loggedIn) await login().catch((e) => reject(e)); let resp = await request.get({ url: unifi_controller + "/api/s/default/stat/sta/", headers: { Cookie: cookies.join("; ") } }).catch((e) => { dlog("getStatus reject " + e); reject(e) }); dlog("got response " + JSON.stringify(resp)); dlog(typeof resp); dlog("--------------------- " + resp); //resp = JSON.parse(resp); //Sortierung Daten und Verwandlung Json var unfiltered = []; unfiltered = JSON.parse(resp).data; dlog(unfiltered[2].hostname + unfiltered[2].mac); let versuch = []; for(var index in unfiltered) { let device = unfiltered[index]; if(device.hostname !== undefined && device.essid !== undefined) versuch.push(device); } versuch.sort(function (alpha, beta) { if (alpha.hostname.toLowerCase() < beta.hostname.toLowerCase()) return -1; if (alpha.hostname.toLowerCase() > beta.hostname.toLowerCase()) return 1; return 0; }); dlog(versuch[2].hostname); dlog(versuch.length.toString()); var anzahlClients = versuch.length; setStateDelayed(dpPrefix + "WLANUnifi.Wifi_Clients_Anzahl",anzahlClients,100); var clientListe = ""; getExistingClients(); //erstelle aktuelles array fastLaneDPs = []; listeDatenpunkteNew=[]; for (var i = 0; i < versuch.length; i++) { listeDatenpunkteNew[i] = versuch[i].hostname;} dlog (listeDatenpunkteNew[3]); // gibt es unterschiedliche Daten - bezug listeDatenpunkte anwesenheit? dlog("ClientTable "+listeDatenpunkteNew.length + " - " + listeDatenpunkteAlt.length); if (listeDatenpunkteNew.length == listeDatenpunkteAlt.length) {writeClientTable = false;} else {writeClientTable=true;listeDatenpunkteAlt=[];listeDatenpunkteAlt=listeDatenpunkteNew.concat();} dlog("ClientTable "+writeClientTable.toString()); dlog("ClientTable "+listeDatenpunkteNew.length + " - " + listeDatenpunkteAlt.length); // gibt es unterschiedliche Daten - bezug listeDatenpunkte anwesenheit? if (anwesenheit && listeDatenpunkteNew.length==listeDatenpunkte.length) {writeAnwesenheit = false;} else {writeAnwesenheit=true} dlog("writeAnwesenheit "+writeAnwesenheit.toString()); dlog("writeAnwesenheit "+listeDatenpunkteNew.length + " - " + listeDatenpunkte.length); getFastLaneClients(versuch); // erstelle htmlclientliste wenn listenDaten verändert if ( writeClientTable ) { for (var i = 0; i < versuch.length; i++) { dlog(versuch[i].hostname + " --- " + versuch[i].essid + " --- " + versuch[i].ip); clientListe = clientListe.concat(""); dlog(clientListe); var ipWandler= versuch[i].ip; if (anwesenheit && writeAnwesenheit) { createState(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuch[i].hostname, { name: ipWandler, role: 'boolean', read: true, write: true, }); } if (anwesenheit && listeDatenpunkteNew.indexOf(versuch[i].hostname)>-1) { //ist hostname in neuer liste und verzeichnisstruktur -> true (anwesend) dlog("gefunden"+versuch[i].hostname); setStateDelayed(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuch[i].hostname, true, 500);} }} if (anwesenheit) { for (var b = 0; b < listeDatenpunkte.length-1; b++) { // ist hostname in verzeichnis struktur und nicht in neuer liste -> false (abwesend) if (listeDatenpunkteNew.indexOf(listeDatenpunkte[b])==-1) { dlog("nicht gefunden"+listeDatenpunkte[b]); setStateDelayed(dpPrefix + "WLANUnifi.Wifi_Client_States."+listeDatenpunkte[b], false, 500);}}} if (iqontrol && anwesenheit && writeClientTable) fs.writeFileSync(datei2, format2+clientListe.concat("
"+versuch[i].hostname+" "+versuch[i].essid+"    "+versuch[i].ip+"

Geamtanzahl angemeldeter Geräte:"+versuch.length+"

")); dlog("ClientFile schreibt! "+iqontrol.toString()+writeClientTable.toString()); if (writeClientTable) setState(dpPrefix + "WLANUnifi.Wifi_Clients", ""+clientListe.concat("
")); //schreibe client table dlog("bin raus aus clients"); }); } //-----------------------------------------EXISTING CLIENTS--------------------------------------------------------------- async function getExistingClients() { dlog("BIN IN EXISTING CLIENTS"); listeDatenpunkte = []; var cacheSelectorState = $("state[state.id=" + dpPrefix + "WLANUnifi.Wifi_Client_States.*]"); cacheSelectorState.each(function (id, c) { if (!id.includes("undefined")) { listeDatenpunkte[c] = id.replace(dpPrefix + "WLANUnifi.Wifi_Client_States.", "");} }); dlog("bin raus a existing clients"); } //-----------------------------------------FAASTLANE--------------------------------------------------------------- async function getFastLaneClients(versuchx) { dlog("BIN IN FASTLANE"); if (anwesenheit){ var laenge = versuchx.length; for (var z = 0; z < laenge; z++) { for(var fastLane_member in fastLane) { if (fastLane[fastLane_member].name==versuchx[z].hostname){ fastLaneDPs.push(versuchx[z]._last_seen_by_uap); if (parseFloat((new Date().getTime())) - (versuchx[z]._last_seen_by_uap*1000) > abfragezyklus+15000 ) { if (getState(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuchx[z].hostname).val) setState(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuchx[z].hostname, false); dlog("abgesetzt" +versuchx[z].hostname+fastLane[fastLane_member].name ); } if (parseFloat((new Date().getTime())) - (versuchx[z]._last_seen_by_uap*1000) < abfragezyklus+15000 ) { if (!getState(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuchx[z].hostname).val) setState(dpPrefix + "WLANUnifi.Wifi_Client_States."+versuchx[z].hostname, true); dlog("gesetzt" +versuchx[z].hostname+fastLane[fastLane_member].name); } } } } } dlog(fastLaneDPs.length.toString()); dlog("bin raus aus fastlane"); } //-----------------------------------------GET--VOUCHERS--------------------------------------------------------------- async function getVouchers() { dlog("BIN IN VOUCHERS"); return new Promise(async (resolve, reject) => { dlog("nur mal so"); if(!loggedIn) await login().catch((e) => reject(e)); let resp = await request.get({ url: unifi_controller + "/api/s/default/stat/voucher", headers: { Cookie: cookies.join("; ") } }).catch((e) => { dlog("getStatus reject " + e); reject(e) }); dlog("got response " + JSON.stringify(resp)); dlog(typeof resp); dlog("--------------------- " + resp); resp = JSON.parse(resp); dlog(resp.meta); dlog(resp.meta.rc); dlog(resp.data[1].code); dlog(resp.data.length); dlog(JSON.stringify(resp).length.toString()); var laengeMessage=JSON.stringify(resp).length; if (laengeMessage==writeFileVar) {writeFile = false;} else {writeFile=true} writeFileVar=JSON.stringify(resp).length; if (writeFile) { var clientListe = "DAUER STATUS-ABGELAUFEN    CODE  ERSTELLT "; for (var i = 1; i < 21; i++) { var x=i.toString(); if ( i < 10) { var yyy="0"+x;} else {yyy=x}; setStateDelayed(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yyy, "", 100);} for (var i = 0; i < resp.data.length; i++) { var zeit= resp.data[i].create_time*1000 let zeit1 = formatDate(getDateObject(zeit), "TT.MM.JJJJ SS:mm").toString(); clientListe = clientListe.concat(""+resp.data[i].duration+" "+resp.data[i].status_expires+"    "+resp.data[i].code+"  " +zeit1 + ""); var y=i+1; var yy=y.toString(); if (y<10 ) yy="0"+yy; if (i<20 ) { dlog(zeit1); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".code"+yy, resp.data[i].code ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".erstellt", zeit1 ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".dauer", resp.data[i].duration ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".abgelaufen", resp.data[i].status_expires ); }} //Datenpunkteäalt löschen var w = resp.data.length; for (i = w; i < 20; i++) { var y=i+1; var yy=y.toString(); if (y<10 ) yy="0"+yy; setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".code"+yy, " na " ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".erstellt", " na " ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".dauer", " na " ); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE"+yy+".abgelaufen", " na " ); } } if (iqontrol && writeFile) {fs.writeFileSync(datei, format + clientListe.concat("

Geamtanzahl Vouchers:"+resp.data.length+"

"));} if (writeFile) setState(dpPrefix + "WLANUnifi.Wifi_Vouchers", ""+clientListe.concat("
")); if (writeFile) setState(dpPrefix + "WLANUnifi.Wifi_Vouchers_Anzahl", resp.data.length); dlog("bin raus a existing vouchers"); }); } //-----------------------------------------SET WIFIS - WIFI EIN-AUSSCHALTEN---------------------------------------------- //Wifi an-/ausschalten //enabled: true = anschalten; false = ausschalten //wifi: wifi object aus der konstanten wifis async function setWifi(enabled, wifi) { return new Promise(async (resolve, reject) => { dlog("setWifi: start set Wifi_haupt"); if (!loggedIn) { dlog("need to login"); await login().catch((e) => reject(e)); } dlog("setWifi: now setting Wifi_haupt"); let resp = request.post({ url: unifi_controller + "/api/s/default/upd/wlanconf/" + wifi.id, body: JSON.stringify({ enabled }), headers: { 'Content-Type': 'application/json', Cookie: cookies.join("; ") } }).catch((e) => { dlog("setWifi: rejected: " + e); reject(e) }); dlog("setWifi: got response") if (resp != null) { dlog("setWifi: Wifi wurde erfolgreich " + (enabled ? "eingeschaltet" : "ausgeschaltet")); dlog(resp); setState(dpPrefix + "WLANUnifi." + wifi.name, enabled, enabled); resolve(); } else { dlog("setWifi: rejetced") dlog("resp: " + JSON.stringify(resp)); reject("msg: " + JSON.parse(resp.body).meta.msg); } }); } //-----------------------------------------------SCHALTER------------------------------------------------ on({id: wifiDPs, ack: false, change: "ne"}, function (obj) { var value = obj.state.val; var dp2 = obj.name setWifi(value, wifis[dp2]); dlog(wifis[dp2]) }); //-----------------------------------------------MAIN LOOP------------------------------------------------ setInterval(async () => { for(let wifi_name in wifis) { await getStatus(wifis[wifi_name]);} if (vouchers) getVouchers(); await getClients(); }, abfragezyklus); // wird oben definiert // Beispiel für //setWifi(true, wifis.WLAN_DragonGuest);