iobroker.openwrt
Advanced tools
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
+78
-20
@@ -39,2 +39,5 @@ <html> | ||
| var getCommandList = []; | ||
| var getTypeList = []; | ||
| // This will be called by the admin adapter when the settings page loads | ||
@@ -77,6 +80,4 @@ function load(settings, onChange) { | ||
| }); | ||
| })); | ||
| })); | ||
| $('#inp_password').on('keydown', (function () { | ||
@@ -94,2 +95,5 @@ $('#fTestAuth').removeClass('disabled'); | ||
| var id = $key.attr('id'); | ||
| if (id === 'inp_password') { | ||
| settings[id] = decrypt(secret, settings[id]); | ||
| } | ||
| if ($key.attr('type') === 'checkbox') { | ||
@@ -108,3 +112,8 @@ // do not call onChange direct, because onChange could expect some arguments | ||
| }); | ||
| getCommandList = settings.list_commands || []; | ||
| getTypeList = settings.list_types || []; | ||
| onChange(false); | ||
| values2table("list_commands", getCommandList, onChange); | ||
| values2table("list_types", getTypeList, onChange); | ||
| // reinitialize all the Materialize labels on the page if you are dynamically adding inputs: | ||
@@ -134,7 +143,8 @@ if (M) M.updateTextFields(); | ||
| default: | ||
| obj[$this.attr('id')] = | ||
| $this.data('crypt') && $this.val() ? encrypt(secret, $this.val()) : $this.val(); | ||
| obj[$this.attr('id')] = $this.data('crypt') && $this.val() ? encrypt(secret, $this.val()) : $this.val(); | ||
| break; | ||
| } | ||
| }); | ||
| obj.list_commands = table2values("list_commands"); | ||
| obj.list_types = table2values("list_types"); | ||
| callback(obj); | ||
@@ -144,2 +154,12 @@ } | ||
| <style> | ||
| /* Title of each section */ | ||
| .title { font-weight: bold; } | ||
| /* Info text of each section */ | ||
| .info { margin-left: 1em; } | ||
| /* Table header */ | ||
| .table-values th { height: 2em; background-color:#2196F3; font-size:90%; } | ||
| /* Table: Add button */ | ||
| .table-button-add { margin: 0.3em 0 1em 0; } | ||
| </style> | ||
| </head> | ||
@@ -152,3 +172,3 @@ | ||
| <div class="row"> | ||
| <div class="col s12 m4 l2"> | ||
| <div class="col s12 m6 l4"> | ||
| <img src="openwrt.png" class="logo"> | ||
@@ -164,6 +184,6 @@ </div> | ||
| <div class="row"> | ||
| <div class="input-field col s12 m6 l2"> | ||
| <div class="input-field col s12 m6 l4"> | ||
| <input class="value" type="text" id="inp_url" /> | ||
| <label for="inp_url" class="translate">inp_url_short</label> | ||
| <i><span class="translate">inp_url_long</span></i> | ||
| <label for="inp_url" class="translate">lab_url_short</label> | ||
| <i><span class="translate">lab_url_long</span></i> | ||
| </div> | ||
@@ -177,11 +197,11 @@ | ||
| <div class="row"> | ||
| <div class="input-field col s4 m2 l1"> | ||
| <div class="input-field col s12 m6 l2"> | ||
| <input class="value" type="text" id="inp_username" /> | ||
| <label for="inp_username" class="translate">inp_username_short</label> | ||
| <i><span class="translate">inp_username_long</span></i> | ||
| <label for="inp_username" class="translate">lab_username_short</label> | ||
| <i><span class="translate">lab_username_long</span></i> | ||
| </div> | ||
| <div class="input-field col s4 m2 l1"> | ||
| <div class="input-field col s12 m6 l2"> | ||
| <input class="value" data-crypt="1" type="password" id="inp_password" /> | ||
| <label for="inp_password" class="translate">inp_password_short</label> | ||
| <i><span class="translate">inp_password_long</span></i> | ||
| <label for="inp_password" class="translate">lab_password_short</label> | ||
| <i><span class="translate">lab_password_long</span></i> | ||
| </div> | ||
@@ -194,13 +214,51 @@ <div class="col s6"> | ||
| <div class="row"> | ||
| <div class="input-field col s12 m6 l2"> | ||
| <div class="input-field col s12 m6 l4"> | ||
| <input class="value" type="number" id="inp_refresh" /> | ||
| <label for="inp_refresh" class="translate">inp_refresh_short</label> | ||
| <i><span class="translate">inp_refresh_long</span></i> | ||
| <label for="inp_refresh" class="translate">lab_refresh_short</label> | ||
| <i><span class="translate">lab_refresh_long</span></i> | ||
| </div> | ||
| </div> | ||
| <div class="row"> | ||
| <div id="tab-list_commands" class="col s12 page"> | ||
| <p class="translate title">lab_settings</p> | ||
| <p class="translate info">text_settings</p> | ||
| <div class="col s12 m6 l4" id="list_commands"> | ||
| <a class="btn-floating waves-effect waves-light blue table-button-add"><i class="material-icons">add</i></a> | ||
| <span class="translate info" style="margin-right: 50px;">lab_BtnAddCMD</span> | ||
| <div class="table-values-div"> | ||
| <table class="table-values"> | ||
| <thead> | ||
| <tr> | ||
| <th class="header translate" data-name="alias">list_commands-alias</th> | ||
| <th class="header translate" data-name="cmd">list_commands-cmd</th> | ||
| <th class="header translate" data-buttons="delete">list_commands-del</th> | ||
| </tr> | ||
| </thead> | ||
| </table> | ||
| </div> | ||
| </div> | ||
| <div class="col s12 m6 l4" id="list_types"> | ||
| <a class="btn-floating waves-effect waves-light blue table-button-add"><i class="material-icons">add</i></a> | ||
| <span class="translate info" style="margin-right: 50px;">lab_BtnAddType</span> | ||
| <div class="table-values-div"> | ||
| <table class="table-values"> | ||
| <thead> | ||
| <tr> | ||
| <th class="header translate" data-name="stateid">list_types-stateid</th> | ||
| <th class="header translate" style="width: 150px" data-name="type" data-options="Text;Number;Boolean" data-type="select" style="width: 150px">list_types-type</th> | ||
| <th class="header translate" data-buttons="delete">list_types-del</th> | ||
| </tr> | ||
| </thead> | ||
| </table> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </body> | ||
| </html> | ||
| </html> |
+237
-21
@@ -19,48 +19,264 @@ /*global systemDictionary:true */ | ||
| "en": "General", | ||
| "de": "Allgemein" | ||
| "de": "Allgemein", | ||
| "ru": "Общий", | ||
| "pt": "Em geral", | ||
| "nl": "Algemeen", | ||
| "fr": "Général", | ||
| "it": "Generale", | ||
| "es": "General", | ||
| "pl": "Ogólny", | ||
| "zh-cn": "一般的" | ||
| }, | ||
| "text_general": { | ||
| "en": "OpenWRT RPC API Configuration", | ||
| "de": "OpenWRT RPC API Konfiguration" | ||
| "de": "OpenWRT RPC API-Konfiguration", | ||
| "ru": "Конфигурация OpenWRT RPC API", | ||
| "pt": "Configuração da API OpenWRT RPC", | ||
| "nl": "OpenWRT RPC API-configuratie", | ||
| "fr": "Configuration de l'API OpenWRT RPC", | ||
| "it": "Configurazione API RPC OpenWRT", | ||
| "es": "Configuración de la API de OpenWRT RPC", | ||
| "pl": "Konfiguracja interfejsu API OpenWRT RPC", | ||
| "zh-cn": "OpenWRT RPC API 配置" | ||
| }, | ||
| "inp_url_short": { | ||
| "lab_url_short": { | ||
| "en": "URL", | ||
| "de": "URL" | ||
| "de": "URL", | ||
| "ru": "URL", | ||
| "pt": "URL", | ||
| "nl": "URL", | ||
| "fr": "URL", | ||
| "it": "URL", | ||
| "es": "URL", | ||
| "pl": "URL", | ||
| "zh-cn": "网址" | ||
| }, | ||
| "inp_url_long": { | ||
| "lab_url_long": { | ||
| "en": "URL to RPC | e.g. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "de": "URL zu RPC-Dienst | z.B. http://192.168.1.1/cgi-bin/luci/rpc/" | ||
| "de": "URL zu RPC | z.B. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "ru": "URL-адрес RPC | например http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "pt": "URL para RPC | por exemplo. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "nl": "URL naar RPC | bijv. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "fr": "URL vers RPC | par exemple. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "it": "URL per RPC | per esempio. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "es": "URL a RPC | p.ej. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "pl": "URL do RPC | np. http://192.168.1.1/cgi-bin/luci/rpc/", | ||
| "zh-cn": "RPC 的 URL |例如http://192.168.1.1/cgi-bin/luci/rpc/" | ||
| }, | ||
| "btn_checkURL": { | ||
| "en": "Check URL", | ||
| "de": "URL prüfen" | ||
| "de": "URL prüfen", | ||
| "ru": "Проверить URL", | ||
| "pt": "Verifique o URL", | ||
| "nl": "Controleer URL", | ||
| "fr": "Vérifier l'URL", | ||
| "it": "Controlla URL", | ||
| "es": "Verificar URL", | ||
| "pl": "Sprawdź adres URL", | ||
| "zh-cn": "检查网址" | ||
| }, | ||
| "inp_username_short": { | ||
| "lab_username_short": { | ||
| "en": "Username", | ||
| "de": "Benutzername" | ||
| "de": "Nutzername", | ||
| "ru": "Имя пользователя", | ||
| "pt": "Nome do usuário", | ||
| "nl": "gebruikersnaam", | ||
| "fr": "Nom d'utilisateur", | ||
| "it": "Nome utente", | ||
| "es": "Nombre de usuario", | ||
| "pl": "Nazwa użytkownika", | ||
| "zh-cn": "用户名" | ||
| }, | ||
| "inp_username_long": { | ||
| "lab_username_long": { | ||
| "en": "OpenWRT username", | ||
| "de": "OpenWRT Benutzername" | ||
| "de": "OpenWRT-Benutzername", | ||
| "ru": "Имя пользователя OpenWRT", | ||
| "pt": "Nome de usuário OpenWRT", | ||
| "nl": "OpenWRT-gebruikersnaam", | ||
| "fr": "Nom d'utilisateur OpenWRT", | ||
| "it": "Nome utente OpenWRT", | ||
| "es": "Nombre de usuario de OpenWRT", | ||
| "pl": "Nazwa użytkownika OpenWRT", | ||
| "zh-cn": "OpenWRT 用户名" | ||
| }, | ||
| "inp_password_short": { | ||
| "lab_password_short": { | ||
| "en": "OpenWRT password", | ||
| "de": "OpenWRT Passwort" | ||
| "de": "OpenWRT-Passwort", | ||
| "ru": "Пароль OpenWRT", | ||
| "pt": "Senha OpenWRT", | ||
| "nl": "OpenWRT-wachtwoord", | ||
| "fr": "Mot de passe OpenWRT", | ||
| "it": "Password OpenWRT", | ||
| "es": "Contraseña OpenWRT", | ||
| "pl": "Hasło OpenWRT", | ||
| "zh-cn": "OpenWRT 密码" | ||
| }, | ||
| "inp_password_long": { | ||
| "lab_password_long": { | ||
| "en": "OpenWRT password", | ||
| "de": "OpenWRT Passwort" | ||
| "de": "OpenWRT-Passwort", | ||
| "ru": "Пароль OpenWRT", | ||
| "pt": "Senha OpenWRT", | ||
| "nl": "OpenWRT-wachtwoord", | ||
| "fr": "Mot de passe OpenWRT", | ||
| "it": "Password OpenWRT", | ||
| "es": "Contraseña OpenWRT", | ||
| "pl": "Hasło OpenWRT", | ||
| "zh-cn": "OpenWRT 密码" | ||
| }, | ||
| "btn_checkAuth": { | ||
| "en": "Check Auth", | ||
| "de": "Auth prüfen" | ||
| "de": "Authentifizierung prüfen", | ||
| "ru": "Проверить аутентификацию", | ||
| "pt": "Verificar autenticação", | ||
| "nl": "Controleer Auth", | ||
| "fr": "Vérifier l'autorisation", | ||
| "it": "Verifica autenticazione", | ||
| "es": "Verificar autenticación", | ||
| "pl": "Sprawdź uwierzytelnianie", | ||
| "zh-cn": "检查身份验证" | ||
| }, | ||
| "inp_refresh_short": { | ||
| "lab_refresh_short": { | ||
| "en": "Refresh interval", | ||
| "de": "Aktualisierungsintervall" | ||
| "de": "Aktualisierungsintervall", | ||
| "ru": "Интервал обновления", | ||
| "pt": "Intervalo de atualização", | ||
| "nl": "Vernieuwingsinterval", | ||
| "fr": "Intervalle de rafraîchissement", | ||
| "it": "Intervallo di aggiornamento", | ||
| "es": "Intervalo de actualización", | ||
| "pl": "Częstotliwość odświeżania", | ||
| "zh-cn": "刷新间隔" | ||
| }, | ||
| "inp_refresh_long": { | ||
| "lab_refresh_long": { | ||
| "en": "Refresh interval (minutes)", | ||
| "de": "Aktualisierungsintervall (Minuten)" | ||
| "de": "Aktualisierungsintervall (Minuten)", | ||
| "ru": "Интервал обновления (минуты)", | ||
| "pt": "Intervalo de atualização (minutos)", | ||
| "nl": "Verversingsinterval (minuten)", | ||
| "fr": "Intervalle de rafraîchissement (minutes)", | ||
| "it": "Intervallo di aggiornamento (minuti)", | ||
| "es": "Intervalo de actualización (minutos)", | ||
| "pl": "Interwał odświeżania (minuty)", | ||
| "zh-cn": "刷新间隔(分钟)" | ||
| }, | ||
| "lab_settings": { | ||
| "en": "Datatransfer - Commands&DataTypes", | ||
| "de": "Datenübertragung - Befehle und Datentypen", | ||
| "ru": "Передача данных - Команды и типы данных", | ||
| "pt": "Datatransfer - Comandos e DataTypes", | ||
| "nl": "Gegevensoverdracht - Commando's en gegevenstypen", | ||
| "fr": "Transfert de données - Commandes et types de données", | ||
| "it": "Trasferimento dati - Comandi e tipi di dati", | ||
| "es": "Transferencia de datos: comandos y tipos de datos", | ||
| "pl": "Transfer danych — polecenia i typy danych", | ||
| "zh-cn": "数据传输 - 命令和数据类型" | ||
| }, | ||
| "text_settings": { | ||
| "en": "You probably just need the left table with the Command-List<br>The table on the right should be used if a DataType is determined wrong for a created ioBroker-States [under Tab Objects] (type: Text, Boolean or Number)", | ||
| "de": "Du wirst in der Regel nur die linke Tabelle mit den Kommandos benötigen.<br>Die rechts Tabelle die nur zum korrieren der automatisch erkannten DatenTypen für ioBroker-States [im Objects-Tab] (Type: Text, Boolean oder Number)", | ||
| "ru": "Вам, наверное, просто нужен левый стол с Command-List<br>The table on the right должен быть использован, если DataType определен не так для созданных ioBroker-States [under Tab Objects] (type: Text, Boolean или Number)", | ||
| "pt": "Você provavelmente só precisa da tabela esquerda com o comando-List<br> A tabela à direita deve ser usada se um DataType é determinado errado para um ioBroker-States criado [sob objetos de guia] (tipo: texto, booleano ou número)", | ||
| "nl": "Je hebt waarschijnlijk de linkertafel nodig met de Command-List, de tafel aan de rechterkant zou moeten worden gebruikt als een DataType verkeerd vastgesteld is voor een gecreëerde ioBroker-States [onderwerp", | ||
| "fr": "Vous avez probablement juste besoin de la table de gauche avec le Command-List profanéLe tableau de droite devrait être utilisé si un DataType est déterminé à tort pour un ioBroker-States créé [sous les objets Tab] (type: Texte, Boolean ou Nombre)", | ||
| "it": "Probabilmente avete solo bisogno della tabella sinistra con il Comando-List <br> La tabella a destra dovrebbe essere utilizzata se un DataType è determinato sbagliato per uno ioBroker-States creato [sotto Oggetti della scheda] (tipo: Testo, Boolean o Numero)", | ||
| "es": "Usted probablemente sólo necesita la tabla izquierda con el Command-List obtenidosbr confianzaLa tabla sobre la derecha debe ser utilizada si un DataType está determinado mal para un ioBroker-States creado [bajo objetos de la pestaña] (tipo: Texto, Booleano o Número)", | ||
| "pl": "Prawdopodobnie potrzebujesz lewej tablicy z napisem Command-List<br> Tabela na prawej stronie powinna być używana, jeśli daneType jest zdeterminowana dla stworzonego ioBroker-States under Objects (typ: Text, Boolean lub Number)", | ||
| "zh-cn": "你可能只需要与指挥部-List <br>左面桌面,如果数据Type被确定为创建的OioBroker-States[根据Tab物体](原状、Bolean或编号)便应该使用该权利表。" | ||
| }, | ||
| "lab_BtnAddCMD": { | ||
| "en": "Add ubus Command", | ||
| "de": "ubus-Befehl hinzufügen", | ||
| "ru": "Добавить команду ubus", | ||
| "pt": "Adicionar comando ubus", | ||
| "nl": "Ubus-opdracht toevoegen", | ||
| "fr": "Ajouter une commande ubus", | ||
| "it": "Aggiungi comando ubus", | ||
| "es": "Agregar comando ubus", | ||
| "pl": "Dodaj polecenie ubus", | ||
| "zh-cn": "添加 ubus 命令" | ||
| }, | ||
| "list_commands-alias": { | ||
| "en": "Alias", | ||
| "de": "Alias", | ||
| "ru": "Алиас", | ||
| "pt": "Alias", | ||
| "nl": "Alias", | ||
| "fr": "Alias", | ||
| "it": "Alias", | ||
| "es": "Alias", | ||
| "pl": "Alias", | ||
| "zh-cn": "Aliasasas" | ||
| }, | ||
| "list_commands-cmd": { | ||
| "en": "ubus Command", | ||
| "de": "ubus-Befehl", | ||
| "ru": "команда ubus", | ||
| "pt": "Comando ubus", | ||
| "nl": "ubus Commando", | ||
| "fr": "Commande Ubus", | ||
| "it": "comando ubus", | ||
| "es": "comando ubus", | ||
| "pl": "ubus Polecenie", | ||
| "zh-cn": "ubus 命令" | ||
| }, | ||
| "list_commands-del": { | ||
| "en": "Delete", | ||
| "de": "Löschen", | ||
| "ru": "Удалить", | ||
| "pt": "Excluir", | ||
| "nl": "Verwijderen", | ||
| "fr": "Effacer", | ||
| "it": "Elimina", | ||
| "es": "Borrar", | ||
| "pl": "Kasować", | ||
| "zh-cn": "删除" | ||
| }, | ||
| "lab_BtnAddType": { | ||
| "en": "Add type definition", | ||
| "de": "Typdefinition hinzufügen", | ||
| "ru": "Добавить определение типа", | ||
| "pt": "Adicionar definição de tipo", | ||
| "nl": "Typedefinitie toevoegen", | ||
| "fr": "Ajouter une définition de type", | ||
| "it": "Aggiungi la definizione del tipo", | ||
| "es": "Agregar definición de tipo", | ||
| "pl": "Dodaj definicję typu", | ||
| "zh-cn": "添加类型定义" | ||
| }, | ||
| "list_types-stateid": { | ||
| "en": "State ID (see Objects)", | ||
| "de": "State-ID (siehe Objekte)", | ||
| "ru": "ID состояния (см. Объекты)", | ||
| "pt": "ID de estado (ver objetos)", | ||
| "nl": "Status-ID (zie Objecten)", | ||
| "fr": "ID d'état (voir Objets)", | ||
| "it": "ID stato (vedi Oggetti)", | ||
| "es": "ID de estado (ver Objetos)", | ||
| "pl": "Identyfikator stanu (patrz Obiekty)", | ||
| "zh-cn": "状态 ID(请参阅对象)" | ||
| }, | ||
| "list_types-type": { | ||
| "en": "Datatype", | ||
| "de": "Datentyp (soll)", | ||
| "ru": "Тип данных", | ||
| "pt": "Tipo de dados", | ||
| "nl": "Data type", | ||
| "fr": "Type de données", | ||
| "it": "Tipo di dati", | ||
| "es": "Tipo de datos", | ||
| "pl": "Typ danych", | ||
| "zh-cn": "数据类型" | ||
| }, | ||
| "list_types-del": { | ||
| "en": "Delete", | ||
| "de": "Löschen", | ||
| "ru": "Удалить", | ||
| "pt": "Excluir", | ||
| "nl": "Verwijderen", | ||
| "fr": "Effacer", | ||
| "it": "Elimina", | ||
| "es": "Borrar", | ||
| "pl": "Kasować", | ||
| "zh-cn": "删除" | ||
| } | ||
| }; | ||
| }; |
+135
-104
| { | ||
| "common": { | ||
| "name": "openwrt", | ||
| "version": "0.0.1", | ||
| "news": { | ||
| "0.0.1": { | ||
| "en": "initial release", | ||
| "de": "Erstveröffentlichung", | ||
| "ru": "Начальная версия", | ||
| "pt": "lançamento inicial", | ||
| "nl": "Eerste uitgave", | ||
| "fr": "Première version", | ||
| "it": "Versione iniziale", | ||
| "es": "Versión inicial", | ||
| "pl": "Pierwsze wydanie", | ||
| "zh-cn": "首次出版" | ||
| } | ||
| }, | ||
| "title": "OpenWRT", | ||
| "titleLang": { | ||
| "en": "OpenWrt", | ||
| "de": "OpenWrt", | ||
| "ru": "OpenWrt", | ||
| "pt": "OpenWrt", | ||
| "nl": "OpenWrt", | ||
| "fr": "OpenWrt", | ||
| "it": "OpenWrt", | ||
| "es": "OpenWrt", | ||
| "pl": "OpenWrt", | ||
| "zh-cn": "OpenWrt" | ||
| }, | ||
| "desc": { | ||
| "en": "Interact with the openwrt RPC API", | ||
| "de": "Interagiere mit der openwrt RPC API", | ||
| "ru": "Взаимодействовать с openwrt RPC API", | ||
| "pt": "Interaja com a API RPC openwrt", | ||
| "nl": "Interactie met de openwrt RPC API", | ||
| "fr": "Interagir avec l'API openwrt RPC", | ||
| "it": "Interagisci con l'API RPC openwrt", | ||
| "es": "Interactúa con la API openwrt RPC", | ||
| "pl": "Interakcja z openwrt RPC API", | ||
| "zh-cn": "与openwrt RPC API交互" | ||
| }, | ||
| "authors": [ | ||
| "Schnup89 <tobias_tsafi@gmx.de>" | ||
| ], | ||
| "keywords": [ | ||
| "openwrt", | ||
| "network", | ||
| "api", | ||
| "router" | ||
| ], | ||
| "license": "MIT", | ||
| "platform": "Javascript/Node.js", | ||
| "messagebox": true, | ||
| "message": true, | ||
| "subscribe": "messagebox", | ||
| "main": "main.js", | ||
| "icon": "openwrt.png", | ||
| "enabled": true, | ||
| "extIcon": "https://raw.githubusercontent.com/Schnup89/ioBroker.openwrt/master/admin/openwrt.png", | ||
| "readme": "https://github.com/Schnup89/ioBroker.openwrt/blob/master/README.md", | ||
| "loglevel": "info", | ||
| "mode": "daemon", | ||
| "type": "infrastructure", | ||
| "compact": true, | ||
| "connectionType": "local", | ||
| "dataSource": "poll", | ||
| "materialize": true, | ||
| "supportCustoms": true, | ||
| "dependencies": [ | ||
| { | ||
| "js-controller": ">=1.4.2" | ||
| } | ||
| ] | ||
| "common": { | ||
| "name": "openwrt", | ||
| "version": "0.0.3", | ||
| "news": { | ||
| "0.0.1": { | ||
| "en": "initial release", | ||
| "de": "Erstveröffentlichung", | ||
| "ru": "Начальная версия", | ||
| "pt": "lançamento inicial", | ||
| "nl": "Eerste uitgave", | ||
| "fr": "Première version", | ||
| "it": "Versione iniziale", | ||
| "es": "Versión inicial", | ||
| "pl": "Pierwsze wydanie", | ||
| "zh-cn": "首次出版" | ||
| }, | ||
| "0.0.2": { | ||
| "en": "Added Last-Update key to states", | ||
| "de": "Letzter Update-Schlüssel zu Staaten hinzugefügt", | ||
| "ru": "Добавлен ключ последнего обновления к состояниям", | ||
| "pt": "Adicionada a chave da última atualização aos estados", | ||
| "nl": "Last-Update-sleutel toegevoegd aan staten", | ||
| "fr": "Ajout de la clé de dernière mise à jour aux états", | ||
| "it": "Aggiunto tasto Ultimo aggiornamento agli stati", | ||
| "es": "Se agregó la clave de última actualización a los estados", | ||
| "pl": "Dodano klucz ostatniej aktualizacji do stanów", | ||
| "zh-cn": "为状态添加了 Last-Update 键" | ||
| }, | ||
| "0.0.3": { | ||
| "en": "Added Alias and isAvailable", | ||
| "de": "Alias und isAvailable hinzugefügt", | ||
| "ru": "Добавлено Alias и доступно", | ||
| "pt": "Adicionado Alias e éDisponível", | ||
| "nl": "Toegevoegd Alias en is beschikbaar", | ||
| "fr": "Ajouté Alias et estDisponible", | ||
| "it": "Aggiunto Alias ed è disponibile", | ||
| "es": "Alias adicionales y está disponible", | ||
| "pl": "Added Alias and Is Available (ang.)", | ||
| "zh-cn": "增 编" | ||
| } | ||
| }, | ||
| "native": { | ||
| "sToken": "", | ||
| "inp_url": "http://openwrt/cgi-bin/luci/rpc/", | ||
| "inp_username": "admin", | ||
| "inp_password": "", | ||
| "inp_refresh": 1 | ||
| "titleLang": { | ||
| "en": "OpenWrt", | ||
| "de": "OpenWrt", | ||
| "ru": "OpenWrt", | ||
| "pt": "OpenWrt", | ||
| "nl": "OpenWrt", | ||
| "fr": "OpenWrt", | ||
| "it": "OpenWrt", | ||
| "es": "OpenWrt", | ||
| "pl": "OpenWrt", | ||
| "zh-cn": "OpenWrt" | ||
| }, | ||
| "objects": [], | ||
| "instanceObjects": [ | ||
| { | ||
| "_id": "info", | ||
| "type": "channel", | ||
| "common": { | ||
| "name": "Information" | ||
| }, | ||
| "native": {} | ||
| }, | ||
| { | ||
| "_id": "info.connection", | ||
| "type": "state", | ||
| "common": { | ||
| "role": "indicator.connected", | ||
| "name": "Device or service connected", | ||
| "type": "boolean", | ||
| "read": true, | ||
| "write": false, | ||
| "def": false | ||
| }, | ||
| "native": {} | ||
| } | ||
| ] | ||
| "desc": { | ||
| "en": "Interact with the openwrt RPC API", | ||
| "de": "Interagiere mit der openwrt RPC API", | ||
| "ru": "Взаимодействовать с openwrt RPC API", | ||
| "pt": "Interaja com a API RPC openwrt", | ||
| "nl": "Interactie met de openwrt RPC API", | ||
| "fr": "Interagir avec l'API openwrt RPC", | ||
| "it": "Interagisci con l'API RPC openwrt", | ||
| "es": "Interactúa con la API openwrt RPC", | ||
| "pl": "Interakcja z openwrt RPC API", | ||
| "zh-cn": "与openwrt RPC API交互" | ||
| }, | ||
| "authors": [ | ||
| "Schnup89 <tobias_tsafi@gmx.de>" | ||
| ], | ||
| "keywords": [ | ||
| "openwrt", | ||
| "network", | ||
| "api", | ||
| "router" | ||
| ], | ||
| "license": "MIT", | ||
| "platform": "Javascript/Node.js", | ||
| "messagebox": true, | ||
| "message": true, | ||
| "subscribe": "messagebox", | ||
| "main": "main.js", | ||
| "icon": "openwrt.png", | ||
| "enabled": true, | ||
| "extIcon": "https://raw.githubusercontent.com/Schnup89/ioBroker.openwrt/master/admin/openwrt.png", | ||
| "readme": "https://github.com/Schnup89/ioBroker.openwrt/blob/master/README.md", | ||
| "loglevel": "info", | ||
| "mode": "daemon", | ||
| "type": "infrastructure", | ||
| "compact": true, | ||
| "connectionType": "local", | ||
| "dataSource": "poll", | ||
| "materialize": true, | ||
| "supportCustoms": false, | ||
| "dependencies": [ | ||
| { | ||
| "js-controller": ">=3.3.22" | ||
| } | ||
| ], | ||
| "installedFrom": "Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e" | ||
| }, | ||
| "native": { | ||
| "sToken": "", | ||
| "inp_url": "http://openwrt/cgi-bin/luci/rpc/", | ||
| "inp_username": "root", | ||
| "inp_password": "", | ||
| "inp_refresh": 1, | ||
| "list_commands": [ | ||
| { | ||
| "alias": "wan_status", | ||
| "cmd": "ubus call network.interface.wan status" | ||
| } | ||
| ], | ||
| "list_types": [] | ||
| }, | ||
| "objects": [], | ||
| "instanceObjects": [ | ||
| { | ||
| "_id": "info", | ||
| "type": "channel", | ||
| "common": { | ||
| "name": "Information" | ||
| }, | ||
| "native": {} | ||
| }, | ||
| { | ||
| "_id": "info.connection", | ||
| "type": "state", | ||
| "common": { | ||
| "role": "indicator.connected", | ||
| "name": "Device or service connected", | ||
| "type": "boolean", | ||
| "read": true, | ||
| "write": false, | ||
| "def": false | ||
| }, | ||
| "native": {} | ||
| } | ||
| ] | ||
| } |
+1
-1
| MIT License | ||
| Copyright (c) 2020 Schnup89 <tobias_tsafi@gmx.de> | ||
| Copyright (c) 2022 Schnup89 <tobias_tsafi@gmx.de> | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
+263
-161
@@ -11,2 +11,3 @@ "use strict"; | ||
| const request = require("request"); | ||
| const type = require("get-type"); | ||
@@ -20,2 +21,13 @@ // eslint-disable-next-line no-unused-vars | ||
| Array.prototype.remove = function() { | ||
| var what, a = arguments, L = a.length, ax; | ||
| while (L && this.length) { | ||
| what = a[--L]; | ||
| while ((ax = this.indexOf(what)) !== -1) { | ||
| this.splice(ax, 1); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| class Openwrt extends utils.Adapter { | ||
@@ -33,3 +45,3 @@ | ||
| this.on("ready", this.onReady.bind(this)); | ||
| this.on("objectChange", this.onObjectChange.bind(this)); | ||
| //this.on("objectChange", this.onObjectChange.bind(this)); | ||
| this.on("stateChange", this.onStateChange.bind(this)); | ||
@@ -62,3 +74,3 @@ this.on("message", this.onMessage.bind(this)); | ||
| this.log.info("##### LOAD CONFIG #####"); | ||
| this.log.debug("##### LOAD CONFIG #####"); | ||
@@ -90,6 +102,18 @@ //Check refresh interval field, if its's not set, we set it | ||
| } | ||
| this.log.info("Decrypted the encrypted password!"); | ||
| this.log.debug("Decrypted the encrypted password!"); | ||
| //Check for empty Commands or Alias, if found, preCheck = false | ||
| if (this.config.list_commands.length > 0) { | ||
| for (let nEntry = 0; nEntry < this.config.list_commands.length; nEntry++) { | ||
| if (!this.config.list_commands[nEntry].alias || !this.config.list_commands[nEntry].alias) { | ||
| this.log.error("## Alias or Command-Entry empty, only Path-Check available"); | ||
| bPreCheckErr = true; //Dont run | ||
| } | ||
| } | ||
| }else{ | ||
| this.log.error("## No Commands defined, only Path-Check available"); | ||
| bPreCheckErr = true; //Dont run | ||
| } | ||
| this.log.info("##### RUN ADAPTER ##### "); | ||
| this.log.debug("##### RUN ADAPTER ##### "); | ||
| if (!bPreCheckErr) { | ||
@@ -100,8 +124,42 @@ //Get first Time Token | ||
| this.fHTTPGetValues(); | ||
| }else{ | ||
| this.log.info("##### PRE CHECK ERRORS, MAIN FUNCTIONS DISABLED! Check Settings"); | ||
| } else { | ||
| this.log.error("##### PRE CHECK ERRORS, MAIN FUNCTIONS DISABLED! Check Settings"); | ||
| } | ||
| //Object2SendCMD | ||
| this.setObjectNotExists("sendCommand", { | ||
| type: "state", | ||
| common: { name: "sendCommand", type: "string", role: "text", write: true}, | ||
| native: {} | ||
| }, (id, error) => {this.setState("sendCommand", "", true);}); | ||
| //Object2WriteResult | ||
| this.setObjectNotExists("sendCommandLastResult", { | ||
| type: "state", | ||
| common: { name: "sendCommand", type: "string", role: "text", write: false}, | ||
| native: {} | ||
| }, (id, error) => {this.setState("sendCommandLastResult", "", true);}); | ||
| this.getDevices((err,devices) => { | ||
| try { | ||
| const device_list = this.config.list_commands.map(entry => {return entry.alias}); | ||
| device_list.forEach(device => { | ||
| this.setObjectNotExists(device, { | ||
| type: "device", | ||
| common: { name: device}, | ||
| native: {} | ||
| }); | ||
| }); | ||
| devices.forEach(device => { | ||
| const device_name = device._id.replace(this.namespace+".",""); | ||
| if (!device_list.includes(device_name)) { | ||
| this.delObject(device_name, {recursive: true}) | ||
| } | ||
| }) | ||
| }catch (e) { | ||
| this.log.warn("Check that Alias and UBUS-Command are both filled. Error: "+e); | ||
| } | ||
| }); | ||
| this.subscribeStates("*"); | ||
| } | ||
@@ -115,2 +173,7 @@ | ||
| try { | ||
| if (tmr_GetValues) { | ||
| clearInterval(tmr_GetValues); | ||
| clearTimeout(tmr_GetValues); | ||
| tmr_GetValues = null; | ||
| } | ||
| this.log.info("cleaned everything up..."); | ||
@@ -124,7 +187,8 @@ callback(); | ||
| /** | ||
| * Is called if a subscribed object changes | ||
| * @param {string} id | ||
| * @param {ioBroker.Object | null | undefined} obj | ||
| */ | ||
| onObjectChange(id, obj) { | ||
| // * Is called if a subscribed object changes | ||
| // * @param {string} id | ||
| // * @param {ioBroker.Object | null | undefined} obj | ||
| */ | ||
| /*onObjectChange(id, obj) { | ||
| if (obj) { | ||
@@ -137,16 +201,21 @@ // The object was changed | ||
| } | ||
| } | ||
| }*/ | ||
| /** | ||
| * Is called if a subscribed state changes | ||
| * @param {string} id | ||
| * @param {ioBroker.State | null | undefined} state | ||
| */ | ||
| // * Is called if a subscribed state changes | ||
| // * @param {string} id | ||
| //* @param {ioBroker.State | null | undefined} state | ||
| */ | ||
| onStateChange(id, state) { | ||
| if (state) { | ||
| // The state was changed | ||
| this.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`); | ||
| if (id == this.namespace + ".sendCommand" && state.val) { //& value not "" empty | ||
| this.log.debug("SendCommand: " + state.val); | ||
| this.fHTTPSendCommand(state.val, true); | ||
| this.setState("sendCommand", ""); | ||
| } | ||
| } else { | ||
| // The state was deleted | ||
| this.log.info(`state ${id} deleted`); | ||
| this.log.debug(`state ${id} deleted`); | ||
| } | ||
@@ -187,15 +256,19 @@ } | ||
| this.log.info("Called fHTTPCheckURL"); | ||
| this.log.debug("Called fHTTPCheckURL"); | ||
| request(oReqOpt, (error, response, body) => { | ||
| if (error) { | ||
| this.log.warn("fHTTPCheckURL Unexpected Error: " + error); | ||
| resolve(false); | ||
| } else { | ||
| if (!body.includes("jsonrpc")) { | ||
| this.log.warn("fHTTPCheckURL 'jsonrpc' not found in response."); | ||
| try { | ||
| if (error) { | ||
| this.log.warn("fHTTPCheckURL Unexpected Error: " + error); | ||
| resolve(false); | ||
| } else { | ||
| this.log.info("fHTTPCheckURL success"); | ||
| resolve(true); | ||
| } else { | ||
| if (!body.includes("jsonrpc")) { | ||
| this.log.warn("fHTTPCheckURL 'jsonrpc' not found in response."); | ||
| resolve(false); | ||
| } else { | ||
| this.log.debug("fHTTPCheckURL success"); | ||
| resolve(true); | ||
| } | ||
| } | ||
| } catch (e) { | ||
| this.log.error("##### fHTTPCheckURL CatchError: " + e); | ||
| } | ||
@@ -219,18 +292,22 @@ }); | ||
| }; | ||
| this.log.info("Called fHTTPCheckAuth"); | ||
| this.log.debug("Called fHTTPCheckAuth"); | ||
| request(oReqOpt, (error, response, body) => { | ||
| if (this.fValidateHTTPResult(error,response,"CheckAuth")) { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| this.log.info("fHTTPCheckAuth success"); | ||
| resolve(true); | ||
| }else{ | ||
| this.log.info("fHTTPCheckAuth ResultError: " + body); | ||
| try { | ||
| if (this.fValidateHTTPResult(error,response,"CheckAuth")) { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| this.log.debug("fHTTPCheckAuth success"); | ||
| resolve(true); | ||
| }else{ | ||
| this.log.error("fHTTPCheckAuth ResultError: " + body); | ||
| resolve(false); | ||
| } | ||
| } else { | ||
| //Log Message printed in fValidateHTTPResult function | ||
| resolve(false); | ||
| } | ||
| } else { | ||
| //Log Message printed in fValidateHTTPResult function | ||
| resolve(false); | ||
| resolve(true); | ||
| } catch (e) { | ||
| this.log.error("##### fHTTPCheckAuth CatchError: " + e); | ||
| } | ||
| resolve(true); | ||
| }); | ||
@@ -247,3 +324,3 @@ }); | ||
| if (!(response.statusCode == 200)) { | ||
| this.log.info("##### fHTTP" + sFuncName + " HTTPCode: " + response.statusCode); | ||
| this.log.debug("##### fHTTP" + sFuncName + " HTTPCode: " + response.statusCode); | ||
| if (response.statusCode == 403) { | ||
@@ -255,5 +332,5 @@ await this.fHTTPGetToken(); | ||
| } | ||
| return true; //NO Error | ||
| } | ||
@@ -265,3 +342,3 @@ fHTTPGetToken() { //NOT ASYNC | ||
| "method": "login", | ||
| "params": ["root",sPass] | ||
| "params": [this.config.inp_username,sPass] | ||
| }; | ||
@@ -275,12 +352,22 @@ const oReqOpt = { | ||
| this.log.info("Called fHTTGetToken"); | ||
| this.log.debug("Called fHTTGetToken"); | ||
| request(oReqOpt, (error, response, body) => { | ||
| if (this.fValidateHTTPResult(error,response,"GetToken")) { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| this.log.info("Saved new Token: " + oBody.result); | ||
| this.config.sToken = oBody.result; | ||
| }else{ | ||
| this.log.info("##### fHTTPGetToken ResultError: " + body); | ||
| try { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| this.log.debug("Saved new Token: " + oBody.result); | ||
| this.config.sToken = oBody.result; | ||
| this.setState("info.connection",true,true); | ||
| }else{ | ||
| this.log.debug("##### fHTTPGetToken ResultError: " + body); | ||
| this.setState("info.connection",false,true); | ||
| } | ||
| } catch (e) { | ||
| this.log.debug("##### fHTTPGetToken CatchError: " + e); | ||
| this.setState("info.connection",false,true); | ||
| } | ||
| } else { | ||
| //Error Message is printed in validate function | ||
| this.setState("info.connection",false,true); | ||
| } | ||
@@ -294,30 +381,21 @@ resolve(true); | ||
| //Set Timer for next Update | ||
| tmr_GetValues = setTimeout(() =>this.fHTTPGetValues(),this.config.inp_refresh * 1000); | ||
| tmr_GetValues = setTimeout(() =>this.fHTTPGetValues(),this.config.inp_refresh * 60000); | ||
| //GetUptime | ||
| this.fHTTPGetSysinfo(); | ||
| //GetHostname | ||
| this.fHTTPGetSysBoard(); | ||
| //GetInterfaces | ||
| this.fHTTPGetInterfaces(); | ||
| for (let nEntry = 0; nEntry < this.config.list_commands.length; nEntry++) { | ||
| this.fHTTPGetUbusCMD(this.config.list_commands[nEntry].cmd,this.config.list_commands[nEntry].alias); | ||
| } | ||
| } | ||
| //##################### DATA FUNCTION | ||
| fSetValue2State(sValue, oValues){ | ||
| this.setObjectNotExists(oValues.name, { | ||
| type: "state", | ||
| common: oValues, | ||
| native: {} | ||
| }); | ||
| this.setState(oValues.name, sValue); | ||
| // eslint-disable-next-line no-unused-vars | ||
| fOverrideExists(sKey) { | ||
| const sType = ""; | ||
| const sRole = ""; | ||
| //ToDo, check if Override exists, change const to let and overrite it! | ||
| return { name: "", type: sType, role: sRole, read: true, write: false }; | ||
| } | ||
| fHTTPGetSysinfo() { //System-Information | ||
| fHTTPSendCommand(sCMD, bFirstTry) { | ||
| const oReqBody = { | ||
| "method": "exec", | ||
| "params": [ "ubus call system info" ] | ||
| "params": [ sCMD ] | ||
| }; | ||
@@ -334,22 +412,21 @@ const oReqOpt = { | ||
| request(oReqOpt, async (error, response, body) => { | ||
| if (await this.fValidateHTTPResult(error,response,"GetSysinfo")) { | ||
| //bug... output \n\t\ seems broken, delete it | ||
| body = this.replaceAll(body,"\n\t",""); | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| const oSysInfo = JSON.parse(oBody.result); | ||
| if(typeof oSysInfo.uptime != "undefined") this.fSetValue2State(oSysInfo.uptime, { name: "sys.uptime", type: "number", role: "time", read: true, write: false }); | ||
| if(typeof oSysInfo.load != "undefined") { | ||
| this.fSetValue2State(oSysInfo.load[1], { name: "sys.load1M", type: "number", role: "value", read: true, write: false }); | ||
| this.fSetValue2State(oSysInfo.load[2], { name: "sys.load5M", type: "number", role: "value", read: true, write: false }); | ||
| this.fSetValue2State(oSysInfo.load[3], { name: "sys.load15M", type: "number", role: "value", read: true, write: false }); | ||
| } | ||
| if(typeof oSysInfo.memory.total != "undefined") this.fSetValue2State(oSysInfo.memory.total, { name: "sys.memory.total", type: "number", role: "value", read: true, write: false }); | ||
| if(typeof oSysInfo.memory.free != "undefined") this.fSetValue2State(oSysInfo.memory.free, { name: "sys.memory.free", type: "number", role: "value", read: true, write: false }); | ||
| if(typeof oSysInfo.memory.shared != "undefined") this.fSetValue2State(oSysInfo.memory.shared, { name: "sys.memory.shared", type: "number", role: "value", read: true, write: false }); | ||
| if(typeof oSysInfo.memory.buffered != "undefined") this.fSetValue2State(oSysInfo.memory.buffered, { name: "sys.memory.buffered", type: "number", role: "value", read: true, write: false }); | ||
| if(typeof oSysInfo.swap.total != "undefined") this.fSetValue2State(oSysInfo.swap.total, { name: "sys.swap.total", type: "number", role: "value", read: true, write: false }); | ||
| if(typeof oSysInfo.swap.free != "undefined") this.fSetValue2State(oSysInfo.swap.free, { name: "sys.swap.free", type: "number", role: "value", read: true, write: false }); | ||
| //this.fSetValue2State(oBody.result, oSetObj); | ||
| if (await this.fValidateHTTPResult(error,response,"SendCommand, " + sCMD)) { | ||
| try { | ||
| //bug... output \n\t\ seems broken, delete it | ||
| body = this.replaceAll(body,"\n\t",""); | ||
| let sBody = JSON.stringify(JSON.parse(body)); | ||
| sBody = sBody.replace(/\\t/g,""); | ||
| sBody = sBody.replace(/\\n/g,""); | ||
| sBody = sBody.replace(/\\r/g,""); | ||
| this.setState("sendCommandLastResult",sBody); | ||
| } catch (e) { | ||
| this.log.error("##### SendCommand, " + sCMD + " + CatchError: " + e); | ||
| this.setState("sendCommandLastResult","{ \"error\": \"" + e + "\" }"); | ||
| } | ||
| } else { | ||
| if (bFirstTry) { | ||
| this.fHTTPSendCommand(sCMD, false); //If Token was not valid, this ensures it gets renew while fvalidehttpresult | ||
| } else { | ||
| this.setState("sendCommandLastResult",JSON.stringify(response)); | ||
| } | ||
| } | ||
@@ -359,42 +436,79 @@ }); | ||
| fHTTPGetSysBoard() { //System-Information | ||
| const oReqBody = { | ||
| "method": "exec", | ||
| "params": [ "ubus call system board" ] | ||
| }; | ||
| const oReqOpt = { | ||
| "method": "POST", | ||
| "url": this.config.inp_url + "sys?auth="+this.config.sToken, | ||
| "headers": { | ||
| "Content-Type": ["application/json", "text/plain"] | ||
| }, | ||
| "body": JSON.stringify(oReqBody) | ||
| }; | ||
| request(oReqOpt, async (error, response, body) => { | ||
| if (await this.fValidateHTTPResult(error,response,"GetSysBoard")) { | ||
| //bug... output \n\t\ seems broken, delete it | ||
| body = this.replaceAll(body,"\n\t",""); | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| const oSysInfo = JSON.parse(oBody.result); | ||
| if(typeof oSysInfo.kernel != "undefined") this.fSetValue2State(oSysInfo.kernel, { name: "sys.kernel", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.hostname != "undefined") this.fSetValue2State(oSysInfo.hostname, { name: "sys.hostname", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.system != "undefined") this.fSetValue2State(oSysInfo.system, { name: "sys.system", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.model != "undefined") this.fSetValue2State(oSysInfo.model, { name: "sys.model", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.board_name != "undefined") this.fSetValue2State(oSysInfo.board_name, { name: "sys.board_name", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.release.distribution != "undefined") this.fSetValue2State(oSysInfo.release.distribution, { name: "sys.release.distribution", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.release.version != "undefined") this.fSetValue2State(oSysInfo.release.version, { name: "sys.release.version", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.release.revision != "undefined") this.fSetValue2State(oSysInfo.release.revision, { name: "sys.release.revision", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.release.target != "undefined") this.fSetValue2State(oSysInfo.release.target, { name: "sys.release.target", type: "text", role: "text", read: true, write: false }); | ||
| if(typeof oSysInfo.release.description != "undefined") this.fSetValue2State(oSysInfo.release.description, { name: "sys.release.description", type: "text", role: "text", read: true, write: false }); | ||
| } | ||
| //##################### DATA FUNCTION | ||
| fSetValue2State(oValue, oKey, sFolder, oTree, channelnames){ | ||
| // eslint-disable-next-line prefer-const | ||
| let oCommon = this.fOverrideExists(oKey); | ||
| oCommon.name = oKey; | ||
| //this.log.info(oKey + ": " + type.get(oValue)); | ||
| if (oCommon.type == "") { //NOT Overwritten | ||
| switch(type.get(oValue)) { | ||
| case "string": | ||
| oCommon.type = "string"; | ||
| oCommon.role = "string"; | ||
| oCommon.write = false; | ||
| break; | ||
| case "number": | ||
| oCommon.type = "number"; | ||
| oCommon.role = "value"; | ||
| oCommon.write = false; | ||
| break; | ||
| case "boolean": | ||
| oCommon.type = "boolean"; | ||
| oCommon.role = "inidicator"; | ||
| oCommon.write = false; | ||
| break; | ||
| case "array": | ||
| if (Object.entries(oTree[oKey]).length) { | ||
| this.setObjectNotExists(sFolder + "." + oKey, { | ||
| type: "channel", | ||
| native: {} | ||
| }); | ||
| channelnames.remove(this.namespace + "." + sFolder + "." + oKey); | ||
| this.fSetValue2State(true,"isAvailable",sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| this.fSetValue2State(this.formatDate(new Date(), "TT.MM.JJJJ hh:mm:ss"),"lastUpdate",sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| for (const [key, value] of Object.entries(oTree[oKey])) { | ||
| oValue = oValue + ", "+ value; | ||
| this.fSetValue2State(value,key,sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| } | ||
| oValue.slice(-1); | ||
| } | ||
| return; //No need to set this Parent Object | ||
| case "object": | ||
| if (Object.entries(oTree[oKey]).length) { | ||
| this.setObjectNotExists(sFolder + "." + oKey, { | ||
| type: "channel", | ||
| native: {} | ||
| }); | ||
| channelnames.remove(this.namespace + "." + sFolder + "." + oKey); | ||
| this.fSetValue2State(true,"isAvailable",sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| this.fSetValue2State(this.formatDate(new Date(), "TT.MM.JJJJ hh:mm:ss"),"lastUpdate",sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| for (const [key, value] of Object.entries(oTree[oKey])) { | ||
| oValue = oValue + ", "+ value; | ||
| this.fSetValue2State(value,key,sFolder+"."+oKey,oTree[oKey], channelnames); | ||
| } | ||
| oValue.slice(-1); | ||
| } | ||
| return; //No need to set this Parent Object | ||
| default: | ||
| this.log.warn("Unhandled DataType: " + type.get(oValue) + " for " + oKey); | ||
| return; // Do Nothing | ||
| } | ||
| }); | ||
| } | ||
| this.setObjectNotExists(sFolder + "." + oCommon.name, { | ||
| type: "state", | ||
| common: oCommon, | ||
| native: {} | ||
| }, (id, error) => {this.setState(sFolder + "." + oCommon.name, oValue, true);} | ||
| ); | ||
| } | ||
| /* | ||
| fHTTPGetHostname() { //Hostname | ||
| fHTTPGetUbusCMD(sCMD,sAlias) { //ubus Communication | ||
| const oReqBody = { | ||
| "method": "hostname" | ||
| "method": "exec", | ||
| "params": [ sCMD ] | ||
| }; | ||
@@ -411,38 +525,26 @@ const oReqOpt = { | ||
| request(oReqOpt, async (error, response, body) => { | ||
| if (await this.fValidateHTTPResult(error,response,"GetHostname")) { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| const oSetObj = { name: "sys.hostname", type: "text", role: "text", read: true, write: false }; | ||
| this.fSetValue2State(oBody.result, oSetObj); | ||
| if (await this.fValidateHTTPResult(error,response,"GetUbusCMD, " + sCMD)) { | ||
| try { | ||
| //bug... output \n\t\ seems broken, delete it | ||
| body = this.replaceAll(body,"\n\t",""); | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| const oTree = JSON.parse(oBody.result); | ||
| let sFolder = this.replaceAll(sAlias," ","_"); //Format CMD to be OK as ObjectName | ||
| sFolder = this.replaceAll(sFolder ,/\./,"-"); //Format CMD to be OK as ObjectName | ||
| this.getChannelsOf(sFolder.split(".")[0],(err,channels) => { | ||
| const channelnames = channels.map(channel => {return channel._id}) | ||
| for (const [key, value] of Object.entries(oTree)) { | ||
| this.fSetValue2State(value,key,sFolder, oTree, channelnames); | ||
| } | ||
| channelnames.forEach(channel => { | ||
| this.fSetValue2State(false,"isAvailable",channel,oTree, channelnames); | ||
| }) | ||
| }); | ||
| } | ||
| } catch (e) { | ||
| this.log.error("##### GetUbusCMD, " + sCMD + " + CatchError: " + e); | ||
| } | ||
| } | ||
| }); | ||
| }*/ | ||
| fHTTPGetInterfaces() { //Get Interfaces | ||
| const oReqBody = { | ||
| "method": "net.devices" | ||
| }; | ||
| const oReqOpt = { | ||
| "method": "POST", | ||
| "url": this.config.inp_url + "sys?auth="+this.config.sToken, | ||
| "headers": { | ||
| "Content-Type": ["application/json", "text/plain"] | ||
| }, | ||
| "body": JSON.stringify(oReqBody) | ||
| }; | ||
| request(oReqOpt, async (error, response, body) => { | ||
| if (await this.fValidateHTTPResult(error,response,"GetInterfaces")) { | ||
| const oBody = JSON.parse(body); | ||
| if (!oBody.error && oBody.result) { | ||
| oBody.result.forEach(oDev => { | ||
| //eth1.1 would result crappy, we replace . with / | ||
| oDev = oDev.replace(".","/"); | ||
| const oSetObj = { name: "net.devices." + oDev + ".exists", type: "boolean", role: "indicator", read: true, write: false }; | ||
| this.fSetValue2State(true, oSetObj); | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
@@ -449,0 +551,0 @@ } |
+51
-26
| { | ||
| "name": "iobroker.openwrt", | ||
| "version": "0.0.1", | ||
| "description": "Interact with the openwrt RPC API", | ||
| "_from": "github:Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "_id": "iobroker.openwrt@0.0.3", | ||
| "_inBundle": false, | ||
| "_integrity": "", | ||
| "_location": "/iobroker.openwrt", | ||
| "_phantomChildren": {}, | ||
| "_requested": { | ||
| "type": "git", | ||
| "raw": "Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "rawSpec": "Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "saveSpec": "github:Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "fetchSpec": null, | ||
| "gitCommittish": "40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e" | ||
| }, | ||
| "_requiredBy": [ | ||
| "#USER", | ||
| "/" | ||
| ], | ||
| "_resolved": "github:Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "_spec": "Schnup89/ioBroker.openwrt#40b7f9d8a784f6082bf1f10cc965c8f8ed2e128e", | ||
| "_where": "/opt/iobroker", | ||
| "author": { | ||
@@ -9,17 +27,12 @@ "name": "Schnup89", | ||
| }, | ||
| "homepage": "https://github.com/Schnup89/ioBroker.openwrt", | ||
| "license": "MIT", | ||
| "keywords": [ | ||
| "openwrt", | ||
| "network", | ||
| "api", | ||
| "router" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/Schnup89/ioBroker.openwrt" | ||
| "bugs": { | ||
| "url": "https://github.com/Schnup89/ioBroker.openwrt/issues" | ||
| }, | ||
| "bundleDependencies": false, | ||
| "dependencies": { | ||
| "@iobroker/adapter-core": "^2.3.0" | ||
| "@iobroker/adapter-core": "^2.3.0", | ||
| "get-type": "^1.1.0" | ||
| }, | ||
| "deprecated": false, | ||
| "description": "Interact with the openwrt RPC API", | ||
| "devDependencies": { | ||
@@ -35,25 +48,37 @@ "@iobroker/testing": "^2.2.0", | ||
| "@types/sinon-chai": "^3.2.4", | ||
| "axios": "^0.19.2", | ||
| "axios": "^0.21.2", | ||
| "chai": "^4.2.0", | ||
| "chai-as-promised": "^7.1.1", | ||
| "eslint": "^6.8.0", | ||
| "get-type": "^1.1.0", | ||
| "gulp": "^4.0.2", | ||
| "mocha": "^7.1.1", | ||
| "proxyquire": "^2.1.3", | ||
| "sinon-chai": "^3.5.0", | ||
| "sinon": "^8.1.1" | ||
| "request": "^2.88.2", | ||
| "sinon": "^8.1.1", | ||
| "sinon-chai": "^3.5.0" | ||
| }, | ||
| "homepage": "https://github.com/Schnup89/ioBroker.openwrt", | ||
| "keywords": [ | ||
| "openwrt", | ||
| "network", | ||
| "api", | ||
| "router" | ||
| ], | ||
| "license": "MIT", | ||
| "main": "main.js", | ||
| "name": "iobroker.openwrt", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/Schnup89/ioBroker.openwrt.git" | ||
| }, | ||
| "scripts": { | ||
| "lint": "eslint", | ||
| "test": "npm run test:js && npm run test:package", | ||
| "test:integration": "mocha test/integration --exit", | ||
| "test:js": "mocha --opts test/mocha.custom.opts", | ||
| "test:package": "mocha test/package --exit", | ||
| "test:unit": "mocha test/unit --exit", | ||
| "test:integration": "mocha test/integration --exit", | ||
| "test": "npm run test:js && npm run test:package", | ||
| "lint": "eslint" | ||
| "test:unit": "mocha test/unit --exit" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/Schnup89/ioBroker.openwrt/issues" | ||
| }, | ||
| "readmeFilename": "README.md" | ||
| "version": "0.0.3" | ||
| } |
+64
-55
@@ -1,4 +0,5 @@ | ||
|  | ||
| # ioBroker.openwrt | ||
| <img src="admin/openwrt.png" width="64"> | ||
| # ioBroker.openwrt V0.0.3 seems broken, do not update | ||
| [](https://www.npmjs.com/package/iobroker.openwrt) | ||
@@ -8,3 +9,2 @@ [](https://www.npmjs.com/package/iobroker.openwrt) | ||
|  | ||
| [](https://david-dm.org/Schnup89/iobroker.openwrt) | ||
| [](https://snyk.io/test/github/Schnup89/ioBroker.openwrt) | ||
@@ -16,74 +16,83 @@ | ||
| ## openwrt adapter for ioBroker | ||
| Interact with the openwrt RPC API | ||
| This Adapter interacts with the OpenWrt RPC API of a OpenWrt-Device (Router, Switch, AccessPoint, RaspberryPI, etc.). | ||
| ## Developer manual | ||
| This section is intended for the developer. It can be deleted later | ||
| **Reading data from ubus to ioBroker-Objects:** | ||
| At the moment only the "ubus call" results are fetched. With that commands you should get the most data out of the router. | ||
| The json-results are parsed and written to the objects database, <a href="https://openwrt.org/docs/techref/ubus">see here [ubus]</a> | ||
| ### Getting started | ||
| **Setting data with ubus from ioBroker to OpenWrt:** | ||
| You can send Commands to the router over the API with the State-Object "sendCommand". | ||
| Put in the command you want to send to the router, the result will be written as JSON-Object to the "sendCommandLastResult" Object and the "sendCommand"-Object will be cleared. | ||
| You are almost done, only a few steps left: | ||
| 1. Create a new repository on GitHub with the name `ioBroker.openwrt` | ||
| 1. Push all files to the GitHub repo. The creator has already set up the local repository for you: | ||
| ```bash | ||
| git push origin master | ||
| ``` | ||
| 1. Head over to [main.js](main.js) and start programming! | ||
| ### Best Practices | ||
| We've collected some [best practices](https://github.com/ioBroker/ioBroker.repositories#development-and-coding-best-practices) regarding ioBroker development and coding in general. If you're new to ioBroker or Node.js, you should | ||
| check them out. If you're already experienced, you should also take a look at them - you might learn something new :) | ||
| ### ToDo / new Features | ||
| - ToDo: Initial Testing | ||
| - ToDo: Dynamic Objects, see https://forum.iobroker.net/topic/32465/dynamischer-objektbaum (german) | ||
| - Feature: Interface Handling (get Informations automaticly) | ||
| ### Scripts in `package.json` | ||
| Several npm scripts are predefined for your convenience. You can run them using `npm run <scriptname>` | ||
| | Script name | Description | | ||
| |-------------|----------------------------------------------------------| | ||
| | `test:js` | Executes the tests you defined in `*.test.js` files. | | ||
| | `test:package` | Ensures your `package.json` and `io-package.json` are valid. | | ||
| | `test` | Performs a minimal test run on package files and your tests. | | ||
| | `lint` | Runs `ESLint` to check your code for formatting errors and potential bugs. | | ||
| ### Writing tests | ||
| When done right, testing code is invaluable, because it gives you the | ||
| confidence to change your code while knowing exactly if and when | ||
| something breaks. A good read on the topic of test-driven development | ||
| is https://hackernoon.com/introduction-to-test-driven-development-tdd-61a13bc92d92. | ||
| Although writing tests before the code might seem strange at first, but it has very | ||
| clear upsides. | ||
| ## Setup and Check API on Target-Device | ||
| ### Setup | ||
| To enable the API, install the following package and restart `uhttpd`: | ||
| The template provides you with basic tests for the adapter startup and package files. | ||
| It is recommended that you add your own tests into the mix. | ||
| ```bash | ||
| opkg install luci-mod-rpc | ||
| /etc/init.d/uhttpd restart | ||
| ``` | ||
| ### Publishing the adapter | ||
| To get your adapter released in ioBroker, please refer to the documentation | ||
| of [ioBroker.repositories](https://github.com/ioBroker/ioBroker.repositories#requirements-for-adapter-to-get-added-to-the-latest-repository). | ||
| Source: [HowTo at the official OpenWrt-Github-Repo](https://github.com/openwrt/luci/wiki/JsonRpcHowTo) | ||
| ### Test the adapter manually on a local ioBroker installation | ||
| In order to install the adapter locally without publishing, the following steps are recommended: | ||
| 1. Create a tarball from your dev directory: | ||
| ```bash | ||
| npm pack | ||
| ``` | ||
| 1. Upload the resulting file to your ioBroker host | ||
| 1. Install it locally (The paths are different on Windows): | ||
| ```bash | ||
| cd /opt/iobroker | ||
| npm i /path/to/tarball.tgz | ||
| ``` | ||
| ### Check | ||
| To check that the API ist working fine, just navigate to this url with your webbrowser: | ||
| ```bash | ||
| http://[TargetDeviceIPorHostname]/cgi-bin/luci/rpc/auth | ||
| ``` | ||
| For later updates, the above procedure is not necessary. Just do the following: | ||
| 1. Overwrite the changed files in the adapter directory (`/opt/iobroker/node_modules/iobroker.openwrt`) | ||
| 1. Execute `iobroker upload openwrt` on the ioBroker host | ||
| If you get something like this, the API is successfully installed: | ||
| ```bash | ||
| {"id":null,"error":{"message":"Parse error.","code":-32700},"jsonrpc":"2.0"} | ||
| ``` | ||
| > Side-Note: The URL-Check on the "admin"-Page checks for "jsonrpc" text in response | ||
| ## Usage | ||
| - Type the URL, Username and Password (same as the SSH/Webinterface) in the admin page | ||
| - If everything works fine, you will see the new Objects: | ||
| <img src="github-ressources/example_objects.png" width=300> | ||
| - Get more Data with specific ubus call-commands, [check this out](https://github.com/Schnup89/ioBroker.openwrt/wiki/ubus-commands) | ||
| ## Troubleshooting | ||
| If there is something wrong, you can check the communication at the admin-panel. | ||
| First the URL should be "OK", test it with the "Check URL"-Button. | ||
| Second the Authentication with user/pass can be tested with the "Check Auth"-Button. | ||
| If there are some error's the button will get red, look at the ioBroker-Logs for more informations . | ||
| ## Changelog | ||
| ### 0.0.3 | ||
| * (Schnup89) Merged PR15, Thanks to "TyrionWarMage", New Parameter "Alias" and "isAvailable" | ||
| ### 0.0.2 | ||
| * (Schnup89) Merged PR13, Thanks to "TyrionWarMage", Parameter "Last Updated" is now set to the states | ||
| ### 0.0.1 | ||
| * (Schnup89) initial release | ||
| ## License | ||
| MIT License | ||
| Copyright (c) 2020 Schnup89 <tobias_tsafi@gmx.de> | ||
| Copyright (c) 2022 Schnup89 <tobias_tsafi@gmx.de> | ||
@@ -106,2 +115,2 @@ Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. | ||
| SOFTWARE. |
| <script type="text/x-iobroker" data-template-name="openwrt"> | ||
| <div class="row"> | ||
| <div class="col s2"> | ||
| <input type="checkbox" data-field="enabled" data-default="false"/> | ||
| <!-- this field is mandatory, just to find out if to include this settings or not</span--> | ||
| <span class="translate">enabled</span> | ||
| </div> | ||
| <div class="col s4"> | ||
| <input type="text" data-field="interval" size="30"> | ||
| <span class="translate">period of time</span> | ||
| </div> | ||
| <div class="col s4"> | ||
| <input type="text" data-field="state" size="30"> | ||
| <span class="translate">new state</span> | ||
| </div> | ||
| <div class="col s2"> | ||
| <input type="checkbox" data-field="setAck" data-default="false"> | ||
| <span class="translate">ack</span> | ||
| </div> | ||
| </div> | ||
| </script> | ||
| <script type="text/javascript"> | ||
| $.get("adapter/openwrt/words.js", function(script) { | ||
| let translation = script.substring(script.indexOf('{'), script.length); | ||
| translation = translation.substring(0, translation.lastIndexOf(';')); | ||
| $.extend(systemDictionary, JSON.parse(translation)); | ||
| }); | ||
| // There are two ways how to predefine default settings: | ||
| // - with attribute "data-default" (content independent) | ||
| // - with function in global variable "defaults". Function name is equal with adapter name. | ||
| // as input function receives object with all information concerning it | ||
| if (typeof defaults !== 'undefined') { | ||
| defaults["openwrt"] = function (obj, instanceObj) { | ||
| return { | ||
| enabled: false, | ||
| interval: '5m', | ||
| state: false, | ||
| setAck: false | ||
| }; | ||
| } | ||
| } | ||
| </script> |
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
142650
29.38%16
6.67%906
53.82%114
9.62%2
100%20
11.11%+ Added
+ Added
+ Added
+ Added