Pi-Hole switch

Oops, when posting the code a few lines were incorrectly indented. Please copy the blocks from my post again and the config should validate without any errors.

Thanks for sharing the code to integrate the pi-hole switch in Home Assistant. However, I wonder why the above is using the shell command and not the pi_hole.disable service, that comes with the home assistant Pi-Hole component?

As far as I can tell it isn’t possible to disable pi-hole indefinitely using that service as the duration option is required so you can only disable it for a period of time.

Hello,

first, many thanks for this great idea!

Note: If you’re running PiHole ion another client and you can access it via ssh, this is more easy:

  1. Login to your pihole by ssh,
  2. cd /etc/pihole
  3. less setupVars.conf
    then read your webpassword.

/Ralf

Is this planned in the future?

This above is a little clunky. I merged the status and script into a switch instead and added the ability to disable permanently in addition to timed disable.

I updated it to use these instead:

  1. Shell commands
  2. Binary Sensor
  3. Switch
  4. Input Selector

secrets.yaml (update <PIHOLE_IP> and <YOUR API KEY> with your own installation information)

pi_hole_status: curl -X GET 'http://<PIHOLE_IP>/admin/api.php?status'
pi_hole_enable: curl -X GET 'http://<PIHOLE_IP>/admin/api.php?enable&auth=<YOUR API KEY>'
pi_hole_disable: curl -X GET 'http://<PIHOLE_IP>/admin/api.php?disable&auth=<YOUR API KEY>'
pi_hole_disable_time: curl -X GET 'http://<PIHOLE_IP>/admin/api.php?disable={{ states.input_select.pihole_time.state }}&auth=<YOUR API KEY>'

configuration.yaml

shell_command:
  pihole_enable: !secret pi_hole_enable
  pihole_disable: !secret pi_hole_disable
  pihole_disable_time: !secret pi_hole_disable_time

binary_sensor:
   - platform: command_line
      name: Pi-hole Status
      command: !secret pi_hole_status
      device_class: connectivity
      value_template: >-
        {% if value_json.status == 'enabled' %}
           {{'ON'}}
        {% else %}
           {{'OFF'}}
        {% endif %}

switch:
   - platform: template
     switches:
        pihole_control:
            friendly_name: "Pi-hole"
            value_template: "{{ is_state('binary_sensor.pi_hole_status', 'on') }}"
            turn_on:
                - service: shell_command.pihole_enable
                - service: homeassistant.update_entity
                  data:
                      entity_id: binary_sensor.pi_hole_status
            turn_off:
                - service_template: >-
                   {% if states('input_select.pihole_time') | float > 0 %}
                       shell_command.pihole_disable_time
                   {% else %}
                       shell_command.pihole_disable
                   {% endif %}
                - service: input_select.select_option
                  data:
                      entity_id: input_select.pihole_time
                      option: 0
                - service: homeassistant.update_entity
                  data:
                      entity_id: binary_sensor.pi_hole_status
            icon_template: >-
               {% if is_state('binary_sensor.pi_hole_status', 'on') %}
                  mdi:server-network
               {% else %}
                  mdi:server-network-off
               {% endif %}

input_select:
  pihole_time:
    name: Disable Time (seconds)
    options:
      - 0
      - 10
      - 30
      - 60
      - 300
      - 600
      - 900
      - 1800
      - 3600
    initial: 0

image

10 Likes

Hey there! You guys are awesome here, seems like such a helpful community! I’m just getting started with Home Assistant and was stuck with some configs around a Pi-Hole switch.

Running Home Assistant 0.114.4 on a VM through virtualbox. Here are some other details I know people ask for when others require help.

System Health

arch x86_64
chassis vm
dev false
docker true
docker_version 19.03.11
hassio true
host_os HassOS 4.12
installation_type Home Assistant OS
os_name Linux
os_version 5.4.56
python_version 3.8.3
supervisor 235
timezone America/Toronto
version 0.114.4
virtualenv false

Lovelace

dashboards 1
mode storage
resources 0
views 5

If I have missed any required details, please just let me know. That said, I have setup the following configuration settings and am unsure what is causing the issue. I had the Pi-Hole setup on a VM, but recently switched it over to a raspberry pi 1. All was working before, the swtich allowed me to enable/disable the pihole, but after the change to the pi, no go. I have updated everything, used the same IP, changed the API keys, etc. I’m able to pull the data into HA, just not able to get the switch going.

Configuration.yaml

pi_hole:
host: 192.168.50.11
name: pihole
ssl: false
verify_ssl: false
api_key: !secret pihole

Sensor.yaml

Switch.yaml

  • platform: template
    switches:
    pihole_switch:
    friendly_name: Pihole Switch
    value_template: “{{ is_state(‘sensor.pihole_status’, ‘enabled’) }}”
    turn_on:
    - service: pi_hole.enable
    turn_off:
    - service: pi_hole.disable
    data:
    duration: “00:30”

I can’t find many details in the logs, but I think this is the error?

This is the error I see when I hit the switch – “must contain at least one of entity_id, area_id.”

Log Details (ERROR)

Logger: homeassistant.components.websocket_api.http.connection.139757886354720
Source: core.py:1262
Integration: Home Assistant WebSocket API
First occurred: 1:34:44 PM (1 occurrences)
Last logged: 1:34:44 PM

must contain at least one of entity_id, area_id.

Traceback (most recent call last): File “/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py”, line 272, in call return self._compiled([], data) File “/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py”, line 817, in validate_callable return schema(data) File “/usr/src/homeassistant/homeassistant/helpers/config_validation.py”, line 122, in validate raise vol.Invalid(“must contain at least one of {}.”.format(", ".join(keys))) voluptuous.error.Invalid: must contain at least one of entity_id, area_id. During handling of the above exception, another exception occurred: Traceback (most recent call last): File “/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py”, line 125, in handle_call_service await hass.services.async_call( File “/usr/src/homeassistant/homeassistant/core.py”, line 1308, in async_call task.result() File “/usr/src/homeassistant/homeassistant/core.py”, line 1343, in _execute_service await handler.func(service_call) File “/usr/src/homeassistant/homeassistant/helpers/entity_component.py”, line 208, in handle_service await self.hass.helpers.service.entity_service_call( File “/usr/src/homeassistant/homeassistant/helpers/service.py”, line 454, in entity_service_call future.result() # pop exception if have File “/usr/src/homeassistant/homeassistant/helpers/entity.py”, line 583, in async_request_call await coro File “/usr/src/homeassistant/homeassistant/helpers/service.py”, line 485, in _handle_entity_call await result File “/usr/src/homeassistant/homeassistant/components/template/switch.py”, line 220, in async_turn_off await self._off_script.async_run(context=self._context) File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 802, in async_run await asyncio.shield(run.async_run()) File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 183, in async_run await self._async_step(log_exceptions=False) File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 191, in _async_step await getattr( File “/usr/src/homeassistant/homeassistant/helpers/script.py”, line 380, in _async_call_service_step await service_task File “/usr/src/homeassistant/homeassistant/core.py”, line 1262, in async_call processed_data = handler.schema(service_data) File “/usr/local/lib/python3.8/site-packages/voluptuous/validators.py”, line 208, in call return self._exec((Schema(val) for val in self.validators), v) File “/usr/local/lib/python3.8/site-packages/voluptuous/validators.py”, line 287, in _exec raise e if self.msg is None else AllInvalid(self.msg, path=path) File “/usr/local/lib/python3.8/site-packages/voluptuous/validators.py”, line 283, in _exec v = func(v) File “/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py”, line 276, in call raise er.MultipleInvalid([e]) voluptuous.error.MultipleInvalid: must contain at least one of entity_id, area_id.

Any help would be greatly appreciated!

Cheers,

C

The error message is kind of telling you what you need: to add an entity_id to the service call.

But, it’s actually a bit more complicated. The service call pi_hole.enable has been removed in 0.114, and pi_hole.disable is changed. You can re-think your config completely, the Pi-hole integration was improved significantly in 0.114. Scroll down to Breaking Changes in the release notes, and read through the Pi-hole section: https://www.home-assistant.io/blog/2020/08/12/release-114/

Once you set up the integration (your first config section) you get both the status and the switch for free. (At least, that’s how I understand it.) But, automations and other non-built-in features will need tweaking. (That entity_id thing.)

Here’s the script (just updated and tested today) I use to disable my two Pi-holes (one on a Pi, one on an Synology):

handle_disable_pihole:
  alias: 'Disable Pi-hole Blocking'
  sequence:
    - service: pi_hole.disable
      data:
        entity_id: all
        duration: '00:01'

If you just have one Pi-hole, all should still work for the entity_id, but you could just use the actual switch ID, e.g., switch.pi_hole_rpi for my Pi-hole running on a Raspberry Pi 4.

Here’s the “parallel” script to enable both Pi-holes:

handle_enable_pihole:
  alias: 'Enable Pi-hole Blocking'
  sequence:
    - service: switch.turn_on
      entity_id: switch.pi_hole_rpi
    - service: switch.turn_on
      entity_id: switch.pi_hole_syn

Mildly irritating to have to list out all of my Pi-hole instances like this, when there used to be a perfectly good service, pi_hole.enable, that would have done the trick. Perhaps someday it’ll come back. But multiple Pi-holes is not that common, and more than two is probably very rare. So it’s not a big deal.

Hi Michael!

Thank you very much for this. I didn’t realize the changes in 0.114 (Looks like I should obviously keep up to date with the changes in the releases). This all makes more sense now I think. I’ve got it back up and working, but will have to play with it a bit. It seems when I toggle the pihole switch, it turns off and then back on in about 1 second. However, the pihole does go offline but comes back online. I’ll play around with the duration and such to see if I can fix it. Appreciate the help!!

Out of curiosity, why do you use 2 pi holes? Just separate networks or?

Cheers,

Chad

Great! Glad it was useful. Keeping up with the changes in Home Assistant, especially as things transition from YAML to the UI, is challenging. HA moves really fast, which is exciting, but also challenging. (I work for an enterprise software company where HA velocity would be terrifying.

I run two Pi-holes for redundancy. When your DNS goes out all kinds of things go wonky, and the problem has so many different symptoms, you don’t always quickly realize that’s the source of your problem. I’ve spent hours diagnosing weird network problems that came down to, oops, that DNS config or resource is old/dead. Wish I’d started there.

Pi-hole on a Raspberry Pi 4 has been rock solid, and basically instant response. So, I mostly don’t need the secondary. But it’s there, just in case. And since the Synology is going to be running 24/7 anyway, it’s an easy way to get a secondary local Pi-hole-based DNS server.

Cheers!

1 Like

This really doesn’t help the discussion much, but I do find the Pi-Hole integration useful.

I added a routine to Alexa so my family is can say “Alexa, shut your pie hole” when they are having trouble accessing websites.

I know it’s not the best, but it’s just easier that way…

Will give this a try.

Cool. Thanks! Just one thing: the one doesn’t get the status for free… only the switch.

Hi,

meanwhile according to official integration documentation a service for disabling Pi-Hole for a specified time is implemented:

Can someone guide me how to implement it using the “input_select” from Pi-Hole switch ?

I have:

  1. the “input_select” helper in configuration.yaml
  2. the following automation:
- id: '1605967593588'
  alias: Pi-Hole_disable temporary
  trigger:
  - platform: state
    entity_id: input_select.pihole_time
  action:
  - service: pi_hole.disable
    data:
      duration: states.input_select.pihole_time.state
#      duration: 30

The automation gets triggered when selecting an item from the input_selection BUT Pi-Hole won´t be disabled at all. Where´s the error?

Update: I managed to get it work by NOT using the service “pi_hole.disable” but instead using the “shell_command”.

What is the correct syntax for replacing “yourauth” by the “pi_hole_api_key” stored in secrets.yaml?

  pihole_enable: curl -X GET 'http://yourpiholeip/admin/api.php?enable&auth=yourauth'

Using

http://yourpiholeip/admin/api.php?enable&auth={!secret pi_hole_api_key}'

doesn´t work unfortunately :frowning:

Suddenly the sensor stopped working while the sensor configuration has not been touched:

sensor:
  platform: command_line
  name: PiHole Status
  command: curl -X GET 'http://yourpiholeip/admin/api.php?status'
  value_template: >
    {{ value_json.status }}

Error: “entity not available: sensor.pi_hole_status”

I only changed other sections below that sensor definition in the configuration.yaml.

Any ideas how to fix this?

@e-raser I am confused as to why you don’t just use the built in integration? The native integration offers a ton of sensors…

And yes these numbers are all accurate for one day in my network…

I do BUT the official integration unfortunately lacks two things:

  1. The switch does not accurately represent the actual Pi-hole status: when Pi-hole is being disabled (e. g. using the Pi.hole site itself) the switch does not reflect that or at least not in a proper time. For this the additional sensor is great.
  2. Very important to me: it does not provide an option to disable Pi-hole for a specified range of time (e. g. 1/5/15 minutes etc.).

Both requirements are (were) satisfied by adding parts of the manual integration.

Update: found the error, will fix it in the evening and I‘m pretty sure that sensor will be back and working.

But as we’re talking: would there be the possibility to have my two pain points/missing features being integrated in the official Pi-Hole integration? Who to talk to, where to send my feature requests?

I’d prefer that as all that additional manual stuff has the potential to break (as I can see now already).

You can solve this with an automation and an input_number. Use the input number to set how long you want it to be turned off and then in your automation turn the seitch off, add a delay taking the value from the input_number and then turn it on again after this delay.