feat: Added stuff
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
description = "Hyprland monitor control server";
|
||||
homepage = "https://github.com/your-username/hyprmonitors";
|
||||
homepage = "https://git.darksailor.dev/servius/hyprmonitors";
|
||||
license = licenses.mit;
|
||||
maintainers = [];
|
||||
};
|
||||
|
||||
301
homeassistant/DOCKER_TROUBLESHOOTING.md
Normal file
301
homeassistant/DOCKER_TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,301 @@
|
||||
# Docker Troubleshooting Guide for Hyprmonitors Home Assistant Integration
|
||||
|
||||
This guide helps resolve common networking issues when running Home Assistant in Docker containers and trying to connect to the Hyprmonitors daemon running on the host system.
|
||||
|
||||
## Quick Fix Summary
|
||||
|
||||
**TL;DR**: Replace `localhost` with `host.docker.internal` when configuring the integration in Home Assistant.
|
||||
|
||||
## The Problem
|
||||
|
||||
When Home Assistant runs inside a Docker container, `localhost` refers to the container's internal network, not the host system where your Hyprmonitors daemon is running. This causes connection timeouts and failures.
|
||||
|
||||
## Solutions
|
||||
|
||||
### Solution 1: Use Docker Host Alias (Recommended)
|
||||
|
||||
**For Docker Desktop (Windows/Mac):**
|
||||
```
|
||||
Host: host.docker.internal
|
||||
Port: 3000
|
||||
```
|
||||
|
||||
**For Docker on Linux:**
|
||||
Add to your `docker-compose.yml`:
|
||||
```yaml
|
||||
services:
|
||||
homeassistant:
|
||||
# ... other config ...
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
```
|
||||
|
||||
Or add to `docker run` command:
|
||||
```bash
|
||||
docker run --add-host=host.docker.internal:host-gateway ...
|
||||
```
|
||||
|
||||
### Solution 2: Use Host Machine's IP Address
|
||||
|
||||
Find your host machine's IP address:
|
||||
```bash
|
||||
# Linux/Mac
|
||||
hostname -I | awk '{print $1}'
|
||||
# or
|
||||
ip route get 8.8.8.8 | awk '{print $7}'
|
||||
|
||||
# Windows
|
||||
ipconfig | findstr IPv4
|
||||
```
|
||||
|
||||
Then use this IP in Home Assistant:
|
||||
```
|
||||
Host: 192.168.1.100 # Your actual IP
|
||||
Port: 3000
|
||||
```
|
||||
|
||||
### Solution 3: Host Network Mode
|
||||
|
||||
Run Home Assistant with host networking (Linux only):
|
||||
```bash
|
||||
docker run --network host ...
|
||||
```
|
||||
|
||||
Or in `docker-compose.yml`:
|
||||
```yaml
|
||||
services:
|
||||
homeassistant:
|
||||
network_mode: host
|
||||
# Remove ports section when using host mode
|
||||
```
|
||||
|
||||
## Testing Connectivity
|
||||
|
||||
### Step 1: Run the Connectivity Test
|
||||
|
||||
From the `hyprmonitors/homeassistant` directory:
|
||||
|
||||
```bash
|
||||
# Test default localhost (will likely fail in Docker)
|
||||
python3 test_connectivity.py
|
||||
|
||||
# Test Docker host alias
|
||||
python3 test_connectivity.py host.docker.internal 3000
|
||||
|
||||
# Test specific IP
|
||||
python3 test_connectivity.py 192.168.1.100 3000
|
||||
```
|
||||
|
||||
### Step 2: Test from Inside Home Assistant Container
|
||||
|
||||
```bash
|
||||
# Get into the HA container
|
||||
docker exec -it homeassistant bash
|
||||
|
||||
# Test connectivity
|
||||
curl http://host.docker.internal:3000/health
|
||||
# or
|
||||
curl http://192.168.1.100:3000/health
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{"success":true,"message":"Hyprland Monitor Control Server is running","monitor":null}
|
||||
```
|
||||
|
||||
## Common Docker Configurations
|
||||
|
||||
### Docker Compose Example
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
homeassistant:
|
||||
container_name: homeassistant
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
volumes:
|
||||
- ./config:/config
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
ports:
|
||||
- "8123:8123"
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # Linux
|
||||
# For Windows/Mac, this is automatic
|
||||
```
|
||||
|
||||
### Docker Run Example
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name homeassistant \
|
||||
--privileged \
|
||||
--restart=unless-stopped \
|
||||
-e TZ=America/New_York \
|
||||
-v /home/user/homeassistant:/config \
|
||||
-v /etc/localtime:/etc/localtime:ro \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
-p 8123:8123 \
|
||||
ghcr.io/home-assistant/home-assistant:stable
|
||||
```
|
||||
|
||||
## Firewall Configuration
|
||||
|
||||
Make sure port 3000 is accessible from Docker containers:
|
||||
|
||||
### UFW (Ubuntu)
|
||||
```bash
|
||||
sudo ufw allow 3000
|
||||
```
|
||||
|
||||
### iptables
|
||||
```bash
|
||||
# Allow Docker containers to access host port 3000
|
||||
sudo iptables -A INPUT -i docker0 -p tcp --dport 3000 -j ACCEPT
|
||||
```
|
||||
|
||||
### firewalld (RHEL/CentOS)
|
||||
```bash
|
||||
sudo firewall-cmd --permanent --add-port=3000/tcp
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
## Troubleshooting Steps
|
||||
|
||||
### 1. Verify Hyprmonitors is Running
|
||||
```bash
|
||||
# Check if service is running
|
||||
systemctl --user status hyprmonitors
|
||||
|
||||
# Check if port is listening
|
||||
ss -tlnp | grep :3000
|
||||
|
||||
# Test locally on host
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
### 2. Check Docker Network
|
||||
```bash
|
||||
# See Docker networks
|
||||
docker network ls
|
||||
|
||||
# Inspect Home Assistant container network
|
||||
docker inspect homeassistant | grep -A 20 NetworkSettings
|
||||
```
|
||||
|
||||
### 3. Debug Container DNS
|
||||
```bash
|
||||
# From inside HA container
|
||||
docker exec -it homeassistant bash
|
||||
|
||||
# Test DNS resolution
|
||||
nslookup host.docker.internal
|
||||
|
||||
# Test network connectivity
|
||||
ping host.docker.internal
|
||||
|
||||
# Check what localhost resolves to
|
||||
ping localhost # Should be 127.0.0.1 (container internal)
|
||||
```
|
||||
|
||||
### 4. Check Home Assistant Logs
|
||||
```bash
|
||||
# View HA logs for connection errors
|
||||
docker logs homeassistant | grep hyprmonitors
|
||||
|
||||
# Enable debug logging in Home Assistant configuration.yaml:
|
||||
# logger:
|
||||
# default: info
|
||||
# logs:
|
||||
# custom_components.hyprmonitors: debug
|
||||
```
|
||||
|
||||
## Platform-Specific Notes
|
||||
|
||||
### Docker Desktop (Windows/Mac)
|
||||
- `host.docker.internal` works automatically
|
||||
- No extra configuration needed
|
||||
- Gateway IP is handled transparently
|
||||
|
||||
### Docker Engine (Linux)
|
||||
- Must add `--add-host=host.docker.internal:host-gateway`
|
||||
- Or use actual host IP address
|
||||
- Gateway IP varies by Docker version
|
||||
|
||||
### Podman
|
||||
- Use `host.containers.internal` instead of `host.docker.internal`
|
||||
- May need `--add-host=host.containers.internal:host-gateway`
|
||||
|
||||
## Alternative Solutions
|
||||
|
||||
### 1. Run Hyprmonitors in Container
|
||||
Create a Dockerfile for Hyprmonitors and run it in the same Docker network as Home Assistant.
|
||||
|
||||
### 2. Use Docker Bridge Network
|
||||
Create a custom bridge network and connect both containers.
|
||||
|
||||
### 3. Use Docker Secrets/Configs
|
||||
Store connection details in Docker secrets for better security.
|
||||
|
||||
## Error Messages Reference
|
||||
|
||||
### "Connection timed out"
|
||||
- **Cause**: Cannot reach the host from container
|
||||
- **Solution**: Use `host.docker.internal` or host IP
|
||||
|
||||
### "Connection refused"
|
||||
- **Cause**: Service not running or wrong port
|
||||
- **Solution**: Check if Hyprmonitors daemon is running
|
||||
|
||||
### "Name or service not known"
|
||||
- **Cause**: DNS resolution failure
|
||||
- **Solution**: Use IP address instead of hostname
|
||||
|
||||
### "No route to host"
|
||||
- **Cause**: Network/firewall blocking connection
|
||||
- **Solution**: Check firewall rules and Docker network config
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you're still having issues:
|
||||
|
||||
1. Run the connectivity test: `python3 test_connectivity.py`
|
||||
2. Check Home Assistant logs for detailed error messages
|
||||
3. Verify your Docker configuration matches the examples above
|
||||
4. Test the connection manually using curl from inside the container
|
||||
|
||||
## Example Working Configuration
|
||||
|
||||
Here's a complete working example:
|
||||
|
||||
**docker-compose.yml:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
homeassistant:
|
||||
container_name: homeassistant
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
volumes:
|
||||
- ./config:/config
|
||||
ports:
|
||||
- "8123:8123"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
**Home Assistant Integration Config:**
|
||||
```
|
||||
Host: host.docker.internal
|
||||
Port: 3000
|
||||
```
|
||||
|
||||
**Test Command:**
|
||||
```bash
|
||||
docker exec -it homeassistant curl http://host.docker.internal:3000/health
|
||||
```
|
||||
|
||||
This configuration should work in most Docker setups and resolve the networking issues between Home Assistant and your Hyprmonitors daemon.
|
||||
@@ -255,19 +255,62 @@ filter:
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Docker Networking Issues
|
||||
|
||||
**Most Common Issue**: If you're running Home Assistant in Docker and getting connection timeouts:
|
||||
|
||||
1. **Use Docker host networking**:
|
||||
- Replace `localhost` with `host.docker.internal` (Docker Desktop)
|
||||
- Or use your host machine's IP address (e.g., `192.168.1.100`)
|
||||
- Or add `--network host` to your Docker run command
|
||||
|
||||
2. **Docker Compose example**:
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
homeassistant:
|
||||
container_name: homeassistant
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
volumes:
|
||||
- ./config:/config
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
ports:
|
||||
- "8123:8123"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # For Docker on Linux
|
||||
```
|
||||
|
||||
3. **Testing connectivity from Docker**:
|
||||
```bash
|
||||
# From inside the Home Assistant container:
|
||||
docker exec -it homeassistant curl http://host.docker.internal:3000/health
|
||||
|
||||
# Or test with your host IP:
|
||||
docker exec -it homeassistant curl http://192.168.1.100:3000/health
|
||||
```
|
||||
|
||||
### Connection Issues
|
||||
|
||||
1. **Cannot connect to server**:
|
||||
- **Docker users**: Use `host.docker.internal` instead of `localhost`
|
||||
- Verify the Hyprmonitors server is running: `curl http://localhost:3000/health`
|
||||
- Check host and port configuration
|
||||
- Ensure firewall allows connections
|
||||
- Ensure firewall allows connections on port 3000
|
||||
|
||||
2. **Monitors not detected**:
|
||||
2. **Timeout errors in logs**:
|
||||
- Check if Home Assistant is in Docker (see Docker section above)
|
||||
- Verify network connectivity between Home Assistant and hyprmonitors server
|
||||
- Check if firewall is blocking port 3000
|
||||
- Try increasing timeout in integration settings
|
||||
|
||||
3. **Monitors not detected**:
|
||||
- Check if Hyprland is running
|
||||
- Verify monitors are detected: `hyprctl monitors`
|
||||
- Restart the Hyprmonitors server
|
||||
- Check server logs for errors
|
||||
|
||||
3. **Integration not loading**:
|
||||
4. **Integration not loading**:
|
||||
- Check Home Assistant logs for errors
|
||||
- Verify all files are copied correctly
|
||||
- Restart Home Assistant completely
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Config flow for Hyprland Monitor Control integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
@@ -47,12 +48,17 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,
|
||||
if not result.get("success", False):
|
||||
raise CannotConnect
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error("Timeout connecting to Hyprmonitors API at %s (10s timeout exceeded)", url)
|
||||
_LOGGER.error("If running Home Assistant in Docker, use host.docker.internal instead of localhost")
|
||||
raise CannotConnect
|
||||
except aiohttp.ClientError as err:
|
||||
_LOGGER.error("Error connecting to Hyprmonitors API: %s", err)
|
||||
_LOGGER.error("Error connecting to Hyprmonitors API at %s: %s", url, err)
|
||||
_LOGGER.error("Make sure the hyprmonitors daemon is running and accessible")
|
||||
raise CannotConnect from err
|
||||
except Exception as err:
|
||||
_LOGGER.exception("Unexpected exception")
|
||||
raise InvalidAuth from err
|
||||
_LOGGER.exception("Unexpected exception connecting to %s", url)
|
||||
raise CannotConnect from err
|
||||
|
||||
# Try to get monitor list to verify full functionality
|
||||
try:
|
||||
@@ -64,8 +70,11 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,
|
||||
result = await response.json()
|
||||
monitors = result.get("monitors", {})
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error("Timeout getting monitor status from %s:%s (10s timeout exceeded)", host, port)
|
||||
raise CannotConnect
|
||||
except aiohttp.ClientError as err:
|
||||
_LOGGER.error("Error getting monitor status: %s", err)
|
||||
_LOGGER.error("Error getting monitor status from %s:%s: %s", host, port, err)
|
||||
raise CannotConnect from err
|
||||
|
||||
# Return info that you want to store in the config entry.
|
||||
|
||||
@@ -11,6 +11,19 @@ DEFAULT_HOST = "localhost"
|
||||
DEFAULT_PORT = 3000
|
||||
DEFAULT_SCAN_INTERVAL = 30
|
||||
|
||||
# Error messages for better user guidance
|
||||
ERROR_CANNOT_CONNECT = "cannot_connect"
|
||||
ERROR_TIMEOUT = "timeout"
|
||||
ERROR_INVALID_RESPONSE = "invalid_response"
|
||||
ERROR_UNKNOWN = "unknown"
|
||||
|
||||
# Docker networking hints
|
||||
DOCKER_HOST_ALTERNATIVES = [
|
||||
"host.docker.internal", # Docker Desktop
|
||||
"172.17.0.1", # Default Docker bridge gateway
|
||||
"docker.host.internal" # Some Docker variants
|
||||
]
|
||||
|
||||
# Configuration keys
|
||||
CONF_HOST = "host"
|
||||
CONF_PORT = "port"
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Failed to connect to the Hyprmonitors server. Please check the host and port.",
|
||||
"cannot_connect": "Failed to connect to the Hyprmonitors server. If running Home Assistant in Docker, try using 'host.docker.internal' instead of 'localhost'. Please check the host and port are correct.",
|
||||
"timeout": "Connection timed out. If running Home Assistant in Docker, use 'host.docker.internal' or your host machine's IP address instead of 'localhost'.",
|
||||
"invalid_response": "Invalid response from Hyprmonitors server. Please verify the server is running correctly.",
|
||||
"invalid_auth": "Authentication failed. Please check your credentials.",
|
||||
"unknown": "Unexpected error occurred."
|
||||
"unknown": "Unexpected error occurred. Check Home Assistant logs for details."
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "This Hyprmonitors server is already configured."
|
||||
|
||||
@@ -175,10 +175,12 @@ check_hyprmonitors_server() {
|
||||
else
|
||||
print_warning "Hyprmonitors server not reachable at $host:$port"
|
||||
print_info "Make sure the Rust server is running: cargo run"
|
||||
print_info "For Docker users, run: python3 test_connectivity.py to diagnose issues"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_warning "curl not available, cannot test server connection"
|
||||
print_info "Use: python3 test_connectivity.py to test connectivity"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -192,17 +194,23 @@ show_next_steps() {
|
||||
echo " - If using Docker: docker restart homeassistant"
|
||||
echo " - If using HAOS: Settings → System → Restart"
|
||||
echo
|
||||
echo "2. Add the integration:"
|
||||
echo "2. Test connectivity (especially for Docker users):"
|
||||
echo " - cd $(dirname "$SOURCE_DIR")/homeassistant"
|
||||
echo " - python3 test_connectivity.py"
|
||||
echo " - For Docker: python3 test_connectivity.py host.docker.internal 3000"
|
||||
echo
|
||||
echo "3. Add the integration:"
|
||||
echo " - Go to Settings → Devices & Services"
|
||||
echo " - Click 'Add Integration'"
|
||||
echo " - Search for 'Hyprland Monitor Control'"
|
||||
echo " - Configure with your server details"
|
||||
echo " - Docker users: Use 'host.docker.internal' instead of 'localhost'"
|
||||
echo
|
||||
echo "3. Make sure your Hyprmonitors server is running:"
|
||||
echo "4. Make sure your Hyprmonitors server is running:"
|
||||
echo " - cd $(dirname "$SOURCE_DIR")"
|
||||
echo " - cargo run"
|
||||
echo
|
||||
echo "4. Optional: Check the examples.yaml file for automation ideas"
|
||||
echo "5. Optional: Check the examples.yaml file for automation ideas"
|
||||
echo
|
||||
print_success "Enjoy controlling your monitors from Home Assistant! 🖥️"
|
||||
}
|
||||
@@ -215,11 +223,13 @@ usage() {
|
||||
echo " -h, --help Show this help message"
|
||||
echo " --check-server HOST:PORT Check if Hyprmonitors server is running"
|
||||
echo " --dry-run Show what would be done without making changes"
|
||||
echo " --test-connectivity Run connectivity test with detailed diagnostics"
|
||||
echo
|
||||
echo "Examples:"
|
||||
echo " $0 # Auto-detect HA config directory"
|
||||
echo " $0 -c /config # Specify config directory"
|
||||
echo " $0 --check-server localhost:3000 # Test server connection"
|
||||
echo " $0 --test-connectivity # Run full connectivity test"
|
||||
echo " $0 --dry-run # Preview installation"
|
||||
}
|
||||
|
||||
@@ -227,6 +237,7 @@ main() {
|
||||
local ha_config=""
|
||||
local check_server=""
|
||||
local dry_run=false
|
||||
local test_connectivity=false
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@@ -243,6 +254,10 @@ main() {
|
||||
check_server="$2"
|
||||
shift 2
|
||||
;;
|
||||
--test-connectivity)
|
||||
test_connectivity=true
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
dry_run=true
|
||||
shift
|
||||
@@ -264,6 +279,24 @@ main() {
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Handle connectivity test
|
||||
if [[ "$test_connectivity" == true ]]; then
|
||||
local test_script="$SOURCE_DIR/test_connectivity.py"
|
||||
if [[ -f "$test_script" ]]; then
|
||||
print_info "Running connectivity test..."
|
||||
if command -v python3 &> /dev/null; then
|
||||
python3 "$test_script"
|
||||
exit $?
|
||||
else
|
||||
print_error "Python3 not found, cannot run connectivity test"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
print_error "Connectivity test script not found: $test_script"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detect Home Assistant config directory
|
||||
if [[ -z "$ha_config" ]]; then
|
||||
ha_config=$(detect_ha_config)
|
||||
|
||||
239
homeassistant/test_connectivity.py
Normal file
239
homeassistant/test_connectivity.py
Normal file
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Hyprmonitors Home Assistant Connectivity Test
|
||||
|
||||
This script helps diagnose connectivity issues between Home Assistant and
|
||||
the Hyprmonitors server, particularly for Docker setups.
|
||||
|
||||
Usage:
|
||||
python test_connectivity.py [host] [port]
|
||||
|
||||
Examples:
|
||||
python test_connectivity.py
|
||||
python test_connectivity.py localhost 3000
|
||||
python test_connectivity.py host.docker.internal 3000
|
||||
python test_connectivity.py 192.168.1.100 3000
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import sys
|
||||
import time
|
||||
from typing import Optional, Tuple
|
||||
|
||||
|
||||
async def test_connection(host: str = "localhost", port: int = 3000) -> bool:
|
||||
"""Test connection to Hyprmonitors server."""
|
||||
url = f"http://{host}:{port}/health"
|
||||
print(f"Testing connection to {url}...")
|
||||
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=10)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
start_time = time.time()
|
||||
async with session.get(url) as response:
|
||||
end_time = time.time()
|
||||
response_time = (end_time - start_time) * 1000 # Convert to ms
|
||||
|
||||
print(f"✓ Connection successful! Response time: {response_time:.2f}ms")
|
||||
print(f" Status: {response.status}")
|
||||
print(f" Content-Type: {response.headers.get('content-type', 'unknown')}")
|
||||
|
||||
if response.status == 200:
|
||||
try:
|
||||
data = await response.json()
|
||||
print(f" Response: {data}")
|
||||
|
||||
if data.get("success"):
|
||||
print("✓ Health check passed!")
|
||||
return True
|
||||
else:
|
||||
print("✗ Health check failed - server returned success=false")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"✗ Failed to parse JSON response: {e}")
|
||||
text = await response.text()
|
||||
print(f" Raw response: {text[:200]}...")
|
||||
return False
|
||||
else:
|
||||
print(f"✗ Server returned status {response.status}")
|
||||
return False
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
print("✗ Connection timed out (10 seconds)")
|
||||
print(" This usually means:")
|
||||
print(" - The server is not running")
|
||||
print(" - Wrong host/port configuration")
|
||||
print(" - Network/firewall blocking the connection")
|
||||
return False
|
||||
|
||||
except aiohttp.ClientConnectorError as e:
|
||||
print(f"✗ Connection failed: {e}")
|
||||
print(" This usually means:")
|
||||
print(" - The server is not running")
|
||||
print(" - Wrong host/port configuration")
|
||||
print(" - If using Docker: try 'host.docker.internal' instead of 'localhost'")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Unexpected error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def test_monitor_status(host: str = "localhost", port: int = 3000) -> bool:
|
||||
"""Test monitor status endpoint."""
|
||||
url = f"http://{host}:{port}/monitors/status"
|
||||
print(f"\nTesting monitor status endpoint: {url}...")
|
||||
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=10)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.get(url) as response:
|
||||
if response.status == 200:
|
||||
try:
|
||||
data = await response.json()
|
||||
print(f"✓ Monitor status retrieved successfully!")
|
||||
print(f" Success: {data.get('success')}")
|
||||
monitors = data.get('monitors', {})
|
||||
print(f" Found {len(monitors)} monitors:")
|
||||
for monitor, status in monitors.items():
|
||||
print(f" - {monitor}: {status}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ Failed to parse monitor status response: {e}")
|
||||
return False
|
||||
else:
|
||||
print(f"✗ Monitor status request failed with status {response.status}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Monitor status test failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_docker_alternatives(port: int = 3000) -> list:
|
||||
"""Test common Docker host alternatives."""
|
||||
alternatives = [
|
||||
"host.docker.internal",
|
||||
"172.17.0.1",
|
||||
"docker.host.internal",
|
||||
"gateway.docker.internal"
|
||||
]
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("TESTING DOCKER HOST ALTERNATIVES")
|
||||
print("="*60)
|
||||
|
||||
working_hosts = []
|
||||
|
||||
for host in alternatives:
|
||||
print(f"\nTesting {host}:{port}...")
|
||||
try:
|
||||
result = asyncio.run(test_connection(host, port))
|
||||
if result:
|
||||
working_hosts.append(host)
|
||||
print(f"✓ {host} works!")
|
||||
else:
|
||||
print(f"✗ {host} failed")
|
||||
except Exception as e:
|
||||
print(f"✗ {host} error: {e}")
|
||||
|
||||
return working_hosts
|
||||
|
||||
|
||||
def print_summary(host: str, port: int, health_ok: bool, status_ok: bool):
|
||||
"""Print test summary and recommendations."""
|
||||
print("\n" + "="*60)
|
||||
print("TEST SUMMARY")
|
||||
print("="*60)
|
||||
|
||||
print(f"Host: {host}")
|
||||
print(f"Port: {port}")
|
||||
print(f"Health check: {'✓ PASS' if health_ok else '✗ FAIL'}")
|
||||
print(f"Monitor status: {'✓ PASS' if status_ok else '✗ FAIL'}")
|
||||
|
||||
if health_ok and status_ok:
|
||||
print("\n🎉 All tests passed! You can use these settings in Home Assistant:")
|
||||
print(f" Host: {host}")
|
||||
print(f" Port: {port}")
|
||||
else:
|
||||
print("\n❌ Tests failed. Try these troubleshooting steps:")
|
||||
print("\n1. Make sure the Hyprmonitors server is running:")
|
||||
print(" systemctl --user status hyprmonitors")
|
||||
print(" # or if using cargo:")
|
||||
print(" cargo run --release")
|
||||
|
||||
print("\n2. Test locally on the host machine:")
|
||||
print(f" curl http://localhost:{port}/health")
|
||||
|
||||
print("\n3. If Home Assistant is in Docker, try:")
|
||||
print(" - Use 'host.docker.internal' instead of 'localhost'")
|
||||
print(" - Use your host machine's IP address")
|
||||
print(" - Add '--network host' to Docker run command")
|
||||
|
||||
print("\n4. Check firewall settings:")
|
||||
print(f" sudo ufw allow {port}")
|
||||
print(f" # or check iptables rules")
|
||||
|
||||
if host == "localhost":
|
||||
print("\n5. For Docker users, run this script with Docker alternatives:")
|
||||
print(" python test_connectivity.py host.docker.internal 3000")
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main function."""
|
||||
# Parse command line arguments
|
||||
host = "localhost"
|
||||
port = 3000
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
host = sys.argv[1]
|
||||
if len(sys.argv) > 2:
|
||||
try:
|
||||
port = int(sys.argv[2])
|
||||
except ValueError:
|
||||
print(f"Invalid port: {sys.argv[2]}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Hyprmonitors Home Assistant Connectivity Test")
|
||||
print("="*50)
|
||||
|
||||
# Test basic connectivity and health
|
||||
health_ok = await test_connection(host, port)
|
||||
|
||||
# Test monitor status endpoint
|
||||
status_ok = False
|
||||
if health_ok:
|
||||
status_ok = await test_monitor_status(host, port)
|
||||
|
||||
# If localhost failed and we might be in Docker, test alternatives
|
||||
if not health_ok and host == "localhost":
|
||||
print(f"\nLocalhost failed. Testing Docker alternatives...")
|
||||
working_hosts = test_docker_alternatives(port)
|
||||
|
||||
if working_hosts:
|
||||
print(f"\n✓ Working Docker hosts found: {working_hosts}")
|
||||
print(f"Recommendation: Use '{working_hosts[0]}' as your host in Home Assistant")
|
||||
|
||||
# Test the first working host
|
||||
print(f"\nTesting monitor status with {working_hosts[0]}...")
|
||||
status_ok = await test_monitor_status(working_hosts[0], port)
|
||||
host = working_hosts[0] # Update for summary
|
||||
health_ok = True # We know it works
|
||||
|
||||
# Print summary and recommendations
|
||||
print_summary(host, port, health_ok, status_ok)
|
||||
|
||||
# Exit with appropriate code
|
||||
sys.exit(0 if (health_ok and status_ok) else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
asyncio.run(main())
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nTest cancelled by user")
|
||||
sys.exit(130)
|
||||
except Exception as e:
|
||||
print(f"\nUnexpected error: {e}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user