Open halfordfan opened 4 months ago
Hey there @shenxn, mind taking a look at this issue as it has been labeled with an integration (pi_hole
) you are listed as a code owner for? Thanks!
(message by CodeOwnersMention)
pi_hole documentation pi_hole source (message by IssueLinks)
I am having the same issue. HA container version 2024.5.4
Also found that thepi_hole.disable
service does not update the ad disable switch. However it does disable ad blocking in Pi-Hole for the duration.
- service: pi_hole.disable
data:
duration: "00:01"
target:
device_id: <DEVICE_ID>
Hi @shenxn, I was able to fix this issue by adding an additional sleep between sending the command to Pi-hole and updating the status. This gives Pi-Hole time to execute the command before we ask for the status again. I am not sure if this is the correct way to fix this, but it seems to work. Below is the modification I have done in async_turn_on() and async_disable():
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the service."""
try:
await self.api.enable()
await asyncio.sleep(3)
await self.async_update()
except HoleError as err:
_LOGGER.error("Unable to enable Pi-hole: %s", err)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the service."""
await self.async_disable()
async def async_disable(self, duration: Any = None) -> None:
"""Disable the service for a given duration."""
duration_seconds = True # Disable infinitely by default
if duration is not None:
duration_seconds = duration.total_seconds()
_LOGGER.debug(
"Disabling Pi-hole '%s' (%s) for %d seconds",
self.name,
self.api.host,
duration_seconds,
)
try:
await self.api.disable(duration_seconds)
await asyncio.sleep(3)
await self.async_update()
except HoleError as err:
_LOGGER.error("Unable to disable Pi-hole: %s", err)
I'm also facing the same behavior. Whenever I use the Switch or Service, I find "Unable to disable Pi-hole: Can not load data from *hole" error messages in the logs.
Hi @shenxn, I was able to fix this issue by adding an additional sleep between sending the command to Pi-hole and updating the status. This gives Pi-Hole time to execute the command before we ask for the status again. I am not sure if this is the correct way to fix this, but it seems to work. Below is the modification I have done in async_turn_on() and async_disable():
async def async_turn_on(self, **kwargs: Any) -> None: """Turn on the service.""" try: await self.api.enable() await asyncio.sleep(3) await self.async_update() except HoleError as err: _LOGGER.error("Unable to enable Pi-hole: %s", err) async def async_turn_off(self, **kwargs: Any) -> None: """Turn off the service.""" await self.async_disable() async def async_disable(self, duration: Any = None) -> None: """Disable the service for a given duration.""" duration_seconds = True # Disable infinitely by default if duration is not None: duration_seconds = duration.total_seconds() _LOGGER.debug( "Disabling Pi-hole '%s' (%s) for %d seconds", self.name, self.api.host, duration_seconds, ) try: await self.api.disable(duration_seconds) await asyncio.sleep(3) await self.async_update() except HoleError as err: _LOGGER.error("Unable to disable Pi-hole: %s", err)
@Stardust0766 have you tried some edge cases such as disabling for 1 second, etc. to see what happens? Did you try lower values before arriving at 3 seconds and if so, did they work?
This fix was along the lines I was thinking of trying.
@halfordfan
Thanks for the info on point 1 and totally agree on point 2. I get why they are using await and async calls for UI responsiveness, but there's a need for some blocking in here somewhere. I don't know that I understand the code well enough to attempt that.
@halfordfan - I don't think that there should be some blocking. I would change the implemention in a way that after sending the command to Pi-hole, the integration polls the status in the background without updating the entities in homeassistant until it receives the expected state. This polling can then be implemented with a timeout, that is much longer than the current 3 s delay and would also work with Pi-hole systems with lower performance.
Also found that the
pi_hole.disable
service does not update the ad disable switch. However it does disable ad blocking in Pi-Hole for the duration.- service: pi_hole.disable data: duration: "00:01" target: device_id: <DEVICE_ID>
I'm having this issue. pi_hole.disable
does disable the pi-hole, however in HA the status is still reflected as "on" and the switch shows blocking is enabled, contrary to what is in pi-hole.
As a workaround - can I request an update of the current states?
I am still having this issue.
Was this fixed? Today I clicked disable button in HA and my pi hole showed disabled in HA
this is after clicking the disable switch:
@warmfire540 No, it is not fixed.
I've done some digging on my side. This is because the status internal to pihole doesnt get updated fast enough, and HA is grabbing the status too quickly. This is reproducible with a shell script (which pulls every docker container on dockerhub to test)
#!/usr/bin/env bash
## grab all docker tags
docker_tags=$(curl -s https://hub.docker.com/v2/repositories/pihole/pihole/tags | jq -r '.results[].name')
for tag in $docker_tags ; do
echo $tag
docker run --rm -d -p 8125:80 -e WEBPASSWORD="" --name "pihole-${tag}" "pihole/pihole:$tag"
sleep 1 # let pihole start up
curl -s 'http://localhost:8125/admin/api.php?disable=true&auth=' ; echo # disable pihole - should respond {"status":"disabled"}
curl -s 'http://localhost:8125/admin/api.php?summaryRaw=' | jq '.status' # get status. SHOULD respond "disabled" but usually doesnt
sleep 0.1
curl -s 'http://localhost:8125/admin/api.php?summaryRaw=' | jq '.status' # get status. Responds "disabled" cause we let it sleep
docker rm -f "pihole-${tag}" ## cleanup
done
Output will look something like this (annotated):
dev # echo $tag line
dfecf668108f90ddd8c8cb4a2e454b47e2ddd19f3ca9c7a40e20b3dabff89dbb
{"status":"disabled"} # response from disable=true
"enabled" # first response of summaryRaw
"disabled" # second response of summaryRaw
pihole-dev
The ideal state is the first response of summaryRaw would match the response from the disabled=true
call, but it rarely does. I've toyed with sleep timing, and even 50ms is too fast at times. 100ms is longer than I'd like, but stills seems unperceivable when clicking the gui button in HA.
Ultimately this is a pihole bug, but since older versions need to be supported, its probably not the end of the world to add this. I'll make an MR to the python-hole code shortly.
The integration appears to be malfunctioning.
The problem
I have two Pi-Hole servers integrated with Home Assistant. When I click to disable ad blocking, the switch will turn off but the icon remains lit. The switch will turn itself back on while Pi-Hole is allowing ads. A second click will turn the icon off and the switch will remain off. Pi-Hole is still allowing ads. When I click the switch to enable, the icon will light up and the switch will briefly move to on, then back to off. Pi-Hole has already changed modes to block ads. After a second click, the switch will remain on and the ad blocking is unchanged.
Basically, I have to click the switch twice to get it to reflect proper ad-blocking state, though a single click actually changes the state of ad-blocking on the Pi-Hole.
What version of Home Assistant Core has the issue?
core-2024.4.4
What was the last working version of Home Assistant Core?
No response
What type of installation are you running?
Home Assistant OS
Integration causing the issue
Pi-Hole
Link to integration documentation on our website
https://www.home-assistant.io/integrations/pi_hole/
Diagnostics information
No response
Example YAML snippet
No response
Anything in the logs that might be useful for us?
Additional information
No response