[Re-Release | Pi-Hole On/Off Toggle Driver ]

Preamble: Since the original topic with @cuboy29 's great port was closed, the polling has broken with the latest Pi-Hole updates, and a bunch of modifications have happened since then, I'm re-starting a thread for this great Pi-Hole integration for others to contribute to and discuss.

PI-HOLE ON/OFF TOGGLE DRIVER

What is this?

A custom Driver for HE that allows you to quickly disable pi-hole ad blocking from the HE dashboard, other devices, or you can even use RM to setup rules of when to enable/disable ads/porn blocking.

Features

  • Polls the Pi-Hole status every 15 minutes
  • Allows you to define in minutes how long the Pi-Hole blocking stays off including setting to indefinite.

Many thanks to @cuboy29 for the original port, @harriscd for contributions, and @walksonair for reporting the broken polling due to the Pi-Hole API updates.

Please feel free to make suggestions or direct pull requests if you'd like to see it improve.

Example uses

  • Quickly toggle your Pi-Hole blocking directly from your favorite dashboard
  • Setup a rule (RM, Simple Lighting, etc.) to automatically turn on or off your Pi-Hole blocking?
  • See your Pi-Hole status directly from your HE dashboard or reading directly from the device.
  • Turn on/off blocking for your kids and their devices based on a set of smarthome rules.

Code:

Screenshot

10 Likes

This is great! Where would one get the API token?

Edit: Found it under “Settings” -> “API / Web Interface” -> “Show API token”

1 Like

I wonder if there is some way it could be made accessible to Homekit…? @gopher.ny

Good point. For anyone (future) struggling with finding their API Token, here's a screenshot of what @Sebastien is talking about:

1 Like

Thanks for getting this updated! You're what make Hubitat so great!

1 Like

There isn't one in the current, certification-in-progress version.

1 Like

Instead of Pi-Hole, I use the pfSense add-in pfBlockerNG. Is there any chance this could be expanded to also control pfBlockerNG? Or might there already exist a separate integration that talks to pfBlockerNG?

This is using the PiHole API, so my guess is that would require a completely separate driver.

Unless perhaps that pfsense add-on is a clone of Pi-hole and uses the same, or similar, API code.

2 Likes

how can i use this if i don't have a password set? it won't allow me to leave the API token blank

EDIT: disregard. i updated the driver code to not make the API token required and it connects

EDIT 2: trying to turn the switch off and it doesn't do anything. anyone else having this happen?

Odd, few questions;

  1. Is the same true for turning on? (e.g. if you manually turn the pihole off via the web interface then try using this for on?
  2. When you try on/off can you post the logs here?
  3. Does your RaspberryPi / PiHole happen to be behind a different port that isn't 80 to access the Web Dashboard?
  4. If you manually in your browser go to http:///admin/api.php?status and http:///admin/api.php?summaryRaw what do you get?

Ah interesting. I'll add that as a configurable option going forward, make the API Token not required. Thanks for pointing this out.

I just did a quick search and it doesn't look like pfBlockerNG exposes any API calls to quickly enable/disable. If you find out it does, it would be easy to repurpose this to do the same.

1 Like
  1. yes, the turning on does nothing as well. i did manually turn off in pi-hole and it did reflect as off in HE

[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:46:07.792 am [error](http://{HE IP}/device/edit/1329)java.lang.NullPointerException: Cannot get property 'FTLnotrunning' on null object on line 109 (method parse)
[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:46:07.787 am [debug](http://{HE IP}/device/edit/1329)Received 'null'
[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:46:07.782 am [debug](http://{HE IP}/device/edit/1329)Parsing 'hubitat.device.HubResponse@1335f09'
[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:45:56.854 am [error](http://{HE IP}/device/edit/1329)java.lang.NullPointerException: Cannot get property 'FTLnotrunning' on null object on line 109 (method parse)
[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:45:56.849 am [debug](http://{HE IP}/device/edit/1329)Received 'null'
[dev:1329](http://{HE IP}/logs#dev1329)2023-01-11 11:45:56.843 am [debug](http://{HE IP}/device/edit/1329)Parsing 'hubitat.device.HubResponse@1ec0cc1'

  1. Not behind a different port, it's the default

{"domains_being_blocked":751393,"dns_queries_today":78849,"ads_blocked_today":30875,"ads_percentage_today":39.157124,"unique_domains":9221,"queries_forwarded":28262,"queries_cached":19557,"clients_ever_seen":58,"unique_clients":40,"dns_queries_all_types":78849,"reply_UNKNOWN":1938,"reply_NODATA":1447,"reply_NXDOMAIN":2756,"reply_CNAME":17038,"reply_IP":54830,"reply_DOMAIN":825,"reply_RRNAME":0,"reply_SERVFAIL":2,"reply_REFUSED":0,"reply_NOTIMP":0,"reply_OTHER":0,"reply_DNSSEC":0,"reply_NONE":0,"reply_BLOB":13,"dns_queries_all_replies":78849,"privacy_level":0,"status":"disabled","gravity_last_updated":{"file_exists":true,"absolute":1673169024,"relative":{"days":3,"hours":8,"minutes":34}}}

That tells me that your_ip/api.php?status isn't returning anything to this app unlike your browser where you get {"status":"enabled"}.

Could your vlan be blocking traffic between your HE and rPi or maybe the IP in the settings is wrong, or you need to add the auth key back?

I do have my firewall set up for access from my HE to Pi-Hole. I do see the "combined" details on HE with my Queries, Blocked, and Clients, so not sure why it's not properly pulling the status. I'll have to take a look more when I get out of work

Any chance that a toggle could be added to enable/disable logging?

1 Like

it's weird because when i do a refresh, it gets the information

dev:1329 2023-01-12 05:15:22.052 pm debugReceived '[reply_NOTIMP:0, reply_DOMAIN:838, reply_NXDOMAIN:4954, reply_RRNAME:0, reply_DNSSEC:0, gravity_last_updated:[file_exists:true, absolute:1673169024, relative:[hours:14, minutes:4, days:4]], queries_forwarded:28745, clients_ever_seen:58, reply_NONE:0, unique_domains:9416, privacy_level:0, reply_UNKNOWN:2170, reply_NODATA:1580, ads_blocked_today:27025, dns_queries_all_types:77408, dns_queries_all_replies:77408, dns_queries_today:77408, reply_OTHER:0, reply_SERVFAIL:2, reply_IP:49547, queries_cached:21377, reply_CNAME:18311, reply_REFUSED:0, domains_being_blocked:751393, ads_percentage_today:34.912411, unique_clients:37, reply_BLOB:6, status:enabled]'
dev:1329 2023-01-12 05:15:22.047 pm debugParsing 'hubitat.device.HubResponse@e69496'

it gets everything, but it's not able to control the status

Super weird, as a refresh is the exact thing as a "poll". The code literately calls poll.

That sounds to me like a rights issue. Are you sure you don't need an Auth Key? Or if not, can you check that you removed the auth key item from line 149
def path = getApiPath() + "?" + toggle + "&auth=" + apiToken

Yep. I'll add that to the list of things;
So far;

  1. Make API Key Optional
  2. Make Debug Toggle-able
2 Likes

that was it! i removed "+ apiToken" from lines 88 and 149 and it can now control it. i wonder what apiToken was providing since I had it blank.

to make this work for me, the updates i did:
33: input name: "apiToken", type: "text", title: "API token", required: false
88: def path = getApiPath() + "?summaryRaw" + "&auth="
149: def path = getApiPath() + "?" + toggle + "&auth="

EDIT:
just updated the code to see what apiToken was giving and it is "null". i wonder if having an if statement in the script to say "if apiToken = null THEN apiToken = "" " would suffice

EDIT 2:
played with it a bit more, made the following changes and it still works:

88:
def path = ""
if (apiToken == null) {
path = getApiPath() + "?summaryRaw" + "&auth="
} else{
path = getApiPath() + "?summaryRaw" + "&auth=" + apiToken
}

149 (now 154 after making the above change):
def path = ""
if (apiToken == null) {
path = getApiPath() + "?" + toggle + "&auth="
} else{
path = getApiPath() + "?" + toggle + "&auth=" + apiToken
}

not sure why it wouldn't let me leave the def path in the if statement, but it is what it is

1 Like

New update posted to GitHub with the following additions;

  • Added toggle for debugging &
  • API Token is now optional
  • Simplified the code (streamlined repeated code into one function, reducing the size and maintainability)