-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
JoKneeMo
authored and
JoKneeMo
committed
Aug 1, 2022
1 parent
b406fb9
commit 3ad5ac3
Showing
4 changed files
with
979 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# AdGuard Home DNS Manager (Unofficial) # | ||
|
||
This package is not supported nor endorsed by AdGuard! | ||
|
||
This package will allow you to manage the global services of an AdGuard Home DNS server and it's configured clients. | ||
A main application allows creation of multiple servers within Hubitat, and the clients are created as child devices of each server. | ||
|
||
|
||
## Application ## | ||
|
||
- [AdGuardHome_App.groovy](https://github.com/JoKneeMo/hubitat/adguardhome/blob/master/app/AdGuardHome_App.groovy) - Not required but makes managing multiple servers easier | ||
|
||
## Main Driver ## | ||
|
||
- [adGuardHome_Server.groovy](https://github.com/JoKneeMo/hubitat/adguardhome/blob/master/drivers/AdGuardHome_Server.groovy) - Required, this is the server device and handles the authentication and communication for each server. | ||
|
||
## Client Drivers ## | ||
|
||
- [adGuardHome_Client.groovy](https://github.com/JoKneeMo/hubitat/adguardhome/blob/master/drivers/AdGuardHome_Client.groovy) - Not required, this is the client device and is only needed if you want to manage individual client settings. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
/** | ||
* AdGuard Home DNS Server Manager for Hubitat | ||
* Author: JoKneeMo <https://github.com/JoKneeMo> | ||
* Copyright: JoKneeMo <https://github.com/JoKneeMo> | ||
* License: GPL-3.0-only | ||
* Version: 0.1.0 | ||
*/ | ||
|
||
import groovyx.net.http.ContentType | ||
import groovy.transform.Field | ||
|
||
definition( | ||
name: "AdGuard Home Manager", | ||
namespace: "adguard-home", | ||
author: "JoKneeMo", | ||
description: "Manages AdGuard Home servers and allows client control", | ||
category: "Dashboard", | ||
iconUrl: "", | ||
iconX2Url: "", | ||
singleInstance: true | ||
){} | ||
|
||
preferences { | ||
page(name: "mainPage") | ||
page(name: "newServer") | ||
page(name: "addServer") | ||
page(name: "configureServer") | ||
page(name: "createServerChildren") | ||
page(name: "deleteServer") | ||
page(name: "changeName") | ||
} | ||
|
||
def mainPage() { | ||
dynamicPage(name: "mainPage", title: "<h2>Manage Your AdGuard Home DNS Servers</h2>", nextPage: null, uninstall: true, install: true) { | ||
section("<h3>Managed Servers</h3>") { | ||
getChildDevices().sort({ a, b -> a["deviceNetworkId"] <=> b["deviceNetworkId"] }).each { | ||
href "configureServer", title: "$it.label", description: "", params: [did: it.deviceNetworkId] | ||
} | ||
href "newServer", title: "New DNS Server", description: "" | ||
} | ||
} | ||
} | ||
|
||
def newServer() { | ||
dynamicPage(name: "newServer", title: "<h2>New AdGuard Home DNS Server</h2>", nextPage: "mainPage", uninstall: false) { | ||
section { | ||
paragraph("Complete the fields below, then press the \"Add Server\" button.\n") | ||
|
||
input name: "serverName", type: "text", title: "New Server Name", required: true, defaultValue: "AdGuard Home DNS Server" | ||
input name: "serverIP", type: "text", title: "Server IP Address", required: true, defaultValue: "192.168.1.2" | ||
input name: "username", type: "text", title: "Username", required: true | ||
input name: "password", type: "password", title: "Password", required: true | ||
input name: "tlsEnable", type: "bool", title: "TLS Connection", defaultValue: false | ||
input name: "logDebug", type: "bool", title: "Enable debug logging", defaultValue: true | ||
|
||
href "addServer", title: "Add Server", description: "Complete the info above and click here to add it" | ||
} | ||
} | ||
} | ||
|
||
def addServer() { | ||
def formattedDNI = AGH_API_DNI + "||" + UUID.randomUUID().toString() | ||
def driver = DEVICE_TYPES[AGH_API_DNI].driver | ||
|
||
try { | ||
d = createDevice(driver, formattedDNI, serverName.toString()) | ||
|
||
d.updateSetting("serverIP", [value: serverIP.toString(), type: "text"]) | ||
d.updateSetting("username", [value: username.toString(), type: "text"]) | ||
d.updateSetting("password", [value: password.toString(), type: "password"]) | ||
d.updateSetting("tlsEnable",[value: tlsEnable.toString(), type: "bool"]) | ||
d.updateSetting("logDebug", [value: logDebug.toString(), type: "bool"]) | ||
|
||
d.initialize() | ||
d.refresh() | ||
|
||
logInfo "${DEVICE_TYPES[AGH_API_DNI].name} with ID ${formattedDNI} created..." | ||
|
||
dynamicPage(name: "addServer", title: "<h2>Add Server Summary</h2>", nextPage: "mainPage") { | ||
section { | ||
paragraph("The device has been created. Press \"Next\" to continue") | ||
} | ||
} | ||
} | ||
catch(e) { | ||
dynamicPage(name: "addServer", title: "<h2>Add Server Summary</h2>", nextPage: "mainPage") { | ||
section { | ||
paragraph("Error: ${(e as String).split(": ")[1]}.") | ||
paragraph("The device could not be created. Press \"Next\" to continue") | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
def configureServer(params) { | ||
if (params?.did || params?.params?.did) { | ||
if (params.did) { | ||
state.currentDeviceId = params.did | ||
state.currentDisplayName = getChildDevice(params.did)?.displayName | ||
} | ||
else { | ||
state.currentDeviceId = params.params.did | ||
state.currentDisplayName = getChildDevice(params.params.did)?.displayName | ||
} | ||
} | ||
if (getChildDevice(state.currentDeviceId) != null) getChildDevice(state.currentDeviceId).configure() | ||
dynamicPage(name: "configureServer", title: "<h2>Configure Existing AdGuard Home DNS Servers</h2>", nextPage: "mainPage") { | ||
if (state.currentDeviceId.startsWith(AGH_API_DNI)) { | ||
section { | ||
paragraph("This is the virtual device that holds the connection for your DNS Server.") | ||
paragraph("The devices attached to the server are listed in the \"Child Devices\" section below.\n" | ||
+ "If no devices are listed, you can create them by pressing the \"Create Child Devices\" button.\n" | ||
+ "If there is a child device that you don't want, simply delete it after you finish creating all devices.") | ||
} | ||
} | ||
|
||
section("<h3>Rename DNS Server Device</h3>"){ | ||
app.updateSetting("${state.currentDeviceId}_label", getChildDevice(state.currentDeviceId).label) | ||
input "${state.currentDeviceId}_label", "text", title: "Device Name", description: "", required: false | ||
href "changeName", title: "Change Device Name", description: "Edit the name above and click here to change it" | ||
} | ||
|
||
section("<h3>DNS Server Details</h3>") { | ||
paragraph("<strong>Connection Status: </strong>" + getChildDevice(state.currentDeviceId).currentState("commStatus").value + "\n" | ||
+ "<strong>IP Address: </strong>" + getChildDevice(state.currentDeviceId).getSetting("serverIP").value + "\n" | ||
+ "<strong>Username: </strong>" + getChildDevice(state.currentDeviceId).getSetting("username").value + "\n" | ||
+ "<strong>Debug Logging: </strong>" + getChildDevice(state.currentDeviceId).getSetting("logDebug").value + "\n" | ||
+ "<strong>Last Activity At: </strong>" + getChildDevice(state.currentDeviceId).getLastActivity().toString() | ||
) | ||
} | ||
|
||
section("<h3>Child Devices</h3>"){ | ||
if (getServerChildren(state.currentDeviceId) != null) { | ||
paragraph("<ul>\n" + | ||
getServerChildren(state.currentDeviceId).sort({ a, b -> a["deviceNetworkId"] <=> b["deviceNetworkId"] }).collect { | ||
def url = "${getLocalApiServerUrl().replace("/apps/api", "")}/device/edit/${it.id}" | ||
"<li><a href=\"${url}\" target=\"_blank\">${it.label}</a></li>" | ||
}.join("\n") + | ||
"</ul>" | ||
) | ||
href "createServerChildren", title: "Refresh Child Devices", description: "" | ||
} | ||
else { | ||
paragraph("DNS Server has no children") | ||
href "createServerChildren", title: "Create Child Devices", description: "" | ||
} | ||
|
||
} | ||
|
||
section("<h3>Delete Server Device</h3>"){ | ||
paragraph('<b style="color: red;">WARNING!! ADVERTENCIA!! ACHTUNG!! AVERTISSEMENT!!</b>') | ||
paragraph("There is not a confirmation for these delete buttons!") | ||
href "deleteServer", title: "Delete $state.currentDisplayName", description: "" | ||
} | ||
} | ||
} | ||
|
||
def deleteServer() { | ||
try { | ||
unsubscribe() | ||
deleteChildDevice(state.currentDeviceId) | ||
dynamicPage(name: "deleteServer", title: "<h2>AdGuard Home DNS Server Deletion Result</h2>", nextPage: "mainPage") { | ||
section { | ||
paragraph("The device has been deleted. Press \"Next\" to continue.") | ||
} | ||
} | ||
} | ||
catch (e) { | ||
dynamicPage(name: "deleteServer", title: "<h2>AdGuard Home DNS Server Deletion Result</h2>", nextPage: "mainPage") { | ||
section { | ||
paragraph("Error: ${(e as String).split(": ")[1]}.") | ||
} | ||
} | ||
} | ||
} | ||
|
||
def changeName() { | ||
def thisDevice = getChildDevice(state.currentDeviceId) | ||
thisDevice.label = settings["${state.currentDeviceId}_label"] | ||
|
||
dynamicPage(name: "changeName", title: "<h2>AdGuard Home DNS Server Change Name Result</h2>", nextPage: "mainPage") { | ||
section { | ||
paragraph("The device has been renamed. Press \"Next\" to continue") | ||
} | ||
} | ||
} | ||
|
||
def createServerChildren() { | ||
def thisDevice = getChildDevice(state.currentDeviceId) | ||
def connectionStatus = thisDevice.currentState("commStatus").value | ||
|
||
if ("${connectionStatus}" == "good") { | ||
try { | ||
thisDevice.createChildDevices() | ||
dynamicPage(name: "createServerChildren", title: "<h2>Create Child Devices</h2>", nextPage: "configureServer") { | ||
section { | ||
paragraph("The child devices have been created. Press \"Next\" to continue") | ||
} | ||
} | ||
} | ||
catch (e) { | ||
dynamicPage(name: "createServerChildren", title: "<h2>Failed to Create Child Devices</h2>", nextPage: "configureServer") { | ||
section { | ||
paragraph("The child devices could not be created.") | ||
paragraph("Error: ${(e as String).split(": ")[1]}.") | ||
} | ||
} | ||
} | ||
|
||
} | ||
else { | ||
dynamicPage(name: "createServerChildren", title: "<h2>DNS Server is not connected</h2>", nextPage: "configureServer") { | ||
section { | ||
paragraph("The server is not connected. Correct the connection between Hubitat and the AdGuard Home DNS server, then try again.") | ||
} | ||
} | ||
} | ||
} | ||
|
||
// General app functions | ||
|
||
def String getFormattedDNI(id) { | ||
return "AGH-${id}" | ||
} | ||
|
||
def getServerChildren(server) { | ||
def thisDevice = getChildDevice(server) | ||
def children = thisDevice.getChildDevices() | ||
|
||
return children | ||
} | ||
|
||
def createDevice(driver, id, label) { | ||
return addChildDevice("JoKneeMo", driver, id, null, ["label": label]) | ||
} | ||
|
||
//logging help methods | ||
private logInfo(msg) { | ||
if (descriptionTextEnable) log.info msg | ||
} | ||
|
||
def logDebug(msg) { | ||
if (logDebug) log.debug msg | ||
} | ||
|
||
def logTrace(msg) { | ||
if (traceLogEnable) log.trace msg | ||
} | ||
|
||
|
||
// Constants | ||
@Field static def AGH_API_DNI = "AGH_API_DNI" | ||
@Field static def GET = "httpGet" | ||
@Field static def POST = "httpPost" | ||
|
||
@Field static def DEVICE_TYPES = [ | ||
"AGH_API_DNI": [name: "AdGuard Home DNS Server", driver: "AdGuard Home DNS Server"], | ||
"client": [name: "AdGuard Home DNS Client", driver: "AdGuard Home DNS Client"] | ||
] |
Oops, something went wrong.