// 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("" + versuch[i].hostname + " | " + versuch[i].essid + " | " + versuch[i].ip + " |
");
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("
Geamtanzahl angemeldeter Geräte:" + versuch.length + "
"));
dlog("ClientFile schreibt! " + iqontrol.toString() + writeClientTable.toString());
if (writeClientTable) setState(dpPrefix + "WLANUnifi.Wifi_Clients", "")); //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", ""));
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);