// 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 = []; const request = require('request-promise-native').defaults({ jar: true, 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 writeFileVar = 0; // 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------------------------ //Delete if login still works //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")); //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" } }); } //Obsolett. IF kann entfernt werden. 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({ //Delete if login still works //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!"); //Delete if login still works // 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 logout() { return new Promise(async (resolve, reject) => { let resp = await request.get(unifi_controller + "/logout") .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(unifi_controller + "/api/s/default/rest/wlanconf/" + wifi.id) .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(unifi_controller + "/api/s/default/stat/sta/") .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 = ""; let writeClientTable = true; let writeAnwesenheit = true; //erstelle aktuelles array let listeDatenpunkte = getExistingClients(); let listeDatenpunkteNew = []; let listeDatenpunkteAlt = []; 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--------------------------------------------------------------- function getExistingClients() { dlog("BIN IN EXISTING CLIENTS"); let listOut = []; var cacheSelectorState = $("state[state.id=" + dpPrefix + "WLANUnifi.Wifi_Client_States.*]"); cacheSelectorState.each(function (id, c) { if (!id.includes("undefined")) { listOut[c] = id.replace(dpPrefix + "WLANUnifi.Wifi_Client_States.", ""); } }); dlog("bin raus a existing clients"); return listOut; } //-----------------------------------------FAASTLANE--------------------------------------------------------------- function getFastLaneClients(versuchx) { dlog("BIN IN FASTLANE"); let counter = 0; 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) { counter++; if (parseFloat((new Date().getTime())) - (versuchx[z]._last_seen_by_uap * 1000) > abfragezyklus) { 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) { 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(counter); 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(unifi_controller + "/api/s/default/stat/voucher") .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()); let writeFile = false; 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; if (y < 10) y = "0" + y.toString(); else y = y.toString(); if (i < 20) { dlog(zeit1); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".code" + y, resp.data[i].code); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".erstellt", zeit1); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".dauer", resp.data[i].duration); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".abgelaufen", resp.data[i].status_expires); } } //Datenpunktealt löschen for (var i = resp.data.length; i < 20; i++) { var y = i + 1; if (y < 10) y = "0" + y.toString(); else y = y.toString(); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".code" + y, " na "); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".erstellt", " na "); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".dauer", " na "); setState(dpPrefix + "WLANUnifi.Wifi_Vouchers-CODES.CODE" + y + ".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);