From b7fece4c5145046b59f03943a7423829bf413798 Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Sun, 31 Aug 2025 21:48:49 +0900 Subject: [PATCH] wol proxy & wol emulator added. --- .env-example | 4 ++- Dockerfile.wol | 4 +-- deploy.sh | 14 ++++----- docker-compose.yml | 3 -- src/wol_proxy.py | 76 ++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 75 insertions(+), 26 deletions(-) mode change 100644 => 100755 deploy.sh diff --git a/.env-example b/.env-example index 07edb8a..0bd5b3e 100644 --- a/.env-example +++ b/.env-example @@ -12,9 +12,11 @@ SYNOLOGY_VERIFY_SSL=False # Проверка SSL-сертификата SYNOLOGY_TIMEOUT=10 # Таймаут для API запросов в секундах SYNOLOGY_API_VERSION=1 # Версия API SYNOLOGY_POWER_API=SYNO.Core.System # API для управления питанием +SYNOLOGY_INFO_API=SYNO.DSM.Info # API для получения информации о DSM +MAC_ADDRESS=00:11:22:33:44:55 # MAC-адрес Synology NAS +SYNOLOGY_MAC=00:11:22:33:44:55 # Альтернативное имя для MAC-адреса (для обратной совместимости) # WOL (Wake-on-LAN) -MAC_ADDRESS=00:11:22:33:44:55 # MAC-адрес Synology NAS WOL_BROADCAST=255.255.255.255 # Broadcast-адрес для WOL WOL_PORT=9 # Порт для WOL (обычно 7 или 9) diff --git a/Dockerfile.wol b/Dockerfile.wol index 19122ea..4423411 100644 --- a/Dockerfile.wol +++ b/Dockerfile.wol @@ -2,6 +2,6 @@ FROM python:3.11-slim WORKDIR /app COPY src/wol_proxy.py ./ -RUN pip install flask -EXPOSE 5000 +RUN pip install flask python-dotenv +EXPOSE 5002 CMD ["python", "wol_proxy.py"] diff --git a/deploy.sh b/deploy.sh old mode 100644 new mode 100755 index fc7e1aa..e2c22fe --- a/deploy.sh +++ b/deploy.sh @@ -16,8 +16,8 @@ if ! [ -x "$(command -v docker)" ]; then fi echo -e "${YELLOW}Проверка наличия Docker Compose...${NC}" -if ! [ -x "$(command -v docker-compose)" ] && ! [ -x "$(command -v docker compose)" ]; then - echo -e "${RED}Ошибка: Docker Compose не установлен.${NC}" >&2 +if ! docker compose version > /dev/null 2>&1; then + echo -e "${RED}Ошибка: Docker Compose не установлен или не работает.${NC}" >&2 echo -e "Установите Docker Compose, следуя инструкциям: https://docs.docker.com/compose/install/" exit 1 fi @@ -37,13 +37,13 @@ chmod 777 logs # Сборка и запуск Docker контейнеров echo -e "${YELLOW}Сборка и запуск Docker контейнеров...${NC}" -docker-compose down -docker-compose up -d --build +docker compose down +docker compose up -d --build # Проверка статуса контейнеров echo -e "${YELLOW}Проверка статуса контейнеров...${NC}" -docker-compose ps +docker compose ps echo -e "${GREEN}Развертывание завершено успешно!${NC}" -echo -e "Для просмотра логов: ${YELLOW}docker-compose logs -f${NC}" -echo -e "Для остановки: ${YELLOW}docker-compose down${NC}" +echo -e "Для просмотра логов: ${YELLOW}docker compose logs -f${NC}" +echo -e "Для остановки: ${YELLOW}docker compose down${NC}" diff --git a/docker-compose.yml b/docker-compose.yml index ceab1e8..f711f33 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,6 @@ services: build: context: . dockerfile: Dockerfile - container_name: synology-power-control-bot restart: unless-stopped env_file: - .env @@ -26,7 +25,6 @@ services: build: context: . dockerfile: Dockerfile.wol - container_name: wol-proxy restart: unless-stopped network_mode: host @@ -34,7 +32,6 @@ services: build: context: . dockerfile: Dockerfile.nas - container_name: nas-emulator restart: unless-stopped network_mode: host networks: diff --git a/src/wol_proxy.py b/src/wol_proxy.py index e037670..1b15777 100644 --- a/src/wol_proxy.py +++ b/src/wol_proxy.py @@ -2,11 +2,25 @@ from flask import Flask, request, jsonify import socket import struct import os +from dotenv import load_dotenv + +# Загружаем переменные окружения из файла .env +load_dotenv() app = Flask(__name__) +# Получаем параметры из переменных окружения +MAC_ADDRESS = os.getenv('MAC_ADDRESS', '00:11:22:33:44:55') +WOL_BROADCAST = os.getenv('WOL_BROADCAST', '255.255.255.255') +WOL_PORT = int(os.getenv('WOL_PORT', '9')) +SYNOLOGY_HOST = os.getenv('SYNOLOGY_HOST', '192.168.1.100') + # Функция отправки WOL-пакета -def send_wol(mac_address): +def send_wol(mac_address=None): + # Если MAC-адрес не предоставлен, используем из .env + if not mac_address: + mac_address = MAC_ADDRESS + # Проверка формата MAC mac_address = mac_address.replace(':', '').replace('-', '') if len(mac_address) != 12: @@ -19,30 +33,47 @@ def send_wol(mac_address): # Отправка пакета sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - sock.sendto(send_data, ('', 9)) + sock.sendto(send_data, (WOL_BROADCAST, WOL_PORT)) sock.close() @app.route('/wol', methods=['POST']) def wol(): - data = request.get_json() + data = request.get_json() if request.is_json else {} mac = data.get('mac') - if not mac: - return jsonify({'error': 'MAC-адрес обязателен'}), 400 try: - send_wol(mac) - return jsonify({'status': 'WOL sent', 'mac': mac}) + # Если MAC не указан, используем MAC из .env + if not mac: + send_wol() + return jsonify({'status': 'WOL sent', 'mac': MAC_ADDRESS}) + else: + send_wol(mac) + return jsonify({'status': 'WOL sent', 'mac': mac}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/wol', methods=['GET']) +def wol_get(): + try: + # Используем MAC из .env по умолчанию + send_wol() + return jsonify({'status': 'WOL sent', 'mac': MAC_ADDRESS}) except Exception as e: return jsonify({'error': str(e)}), 500 -# Пример получения IP по MAC через парсинг DHCP lease-файла +# Получение IP адреса NAS @app.route('/ip', methods=['GET']) def get_ip(): - mac = request.args.get('mac') + mac = request.args.get('mac', MAC_ADDRESS) + + # Пробуем получить IP из переменной окружения + if not mac or mac == MAC_ADDRESS: + return jsonify({'ip': SYNOLOGY_HOST, 'mac': MAC_ADDRESS, 'source': 'env'}) + + # Если запрашивается другой MAC - пробуем найти его в lease-файле lease_file = '/var/lib/dhcp/dhcpd.leases' # путь к lease-файлу - if not mac: - return jsonify({'error': 'MAC-адрес обязателен'}), 400 if not os.path.exists(lease_file): return jsonify({'error': 'Lease-файл не найден'}), 500 + ip = None with open(lease_file, 'r') as f: for line in f: @@ -50,10 +81,29 @@ def get_ip(): # Пример: lease 192.168.1.100 { ... hardware ethernet 00:11:22:33:44:55; ... } if 'lease' in line: ip = line.split()[1] + if ip: - return jsonify({'ip': ip, 'mac': mac}) + return jsonify({'ip': ip, 'mac': mac, 'source': 'lease'}) else: return jsonify({'error': 'IP не найден для MAC'}), 404 +# Маршрут для отображения информации о конфигурации +@app.route('/', methods=['GET']) +def index(): + return jsonify({ + 'status': 'running', + 'config': { + 'mac_address': MAC_ADDRESS, + 'wol_broadcast': WOL_BROADCAST, + 'wol_port': WOL_PORT, + 'synology_host': SYNOLOGY_HOST + }, + 'endpoints': { + 'wol_get': 'GET /wol - отправка WOL пакета на MAC из .env', + 'wol_post': 'POST /wol - отправка WOL пакета с указанным MAC', + 'ip': 'GET /ip - получение IP по MAC из .env или указанному в параметре' + } + }) + if __name__ == '__main__': - app.run(host='0.0.0.0', port=5000) + app.run(host='0.0.0.0', port=5002)