wol proxy & wol emulator added.

This commit is contained in:
2025-08-31 21:48:49 +09:00
parent 147f1dec22
commit b7fece4c51
5 changed files with 75 additions and 26 deletions

View File

@@ -12,9 +12,11 @@ SYNOLOGY_VERIFY_SSL=False # Проверка SSL-сертификата
SYNOLOGY_TIMEOUT=10 # Таймаут для API запросов в секундах SYNOLOGY_TIMEOUT=10 # Таймаут для API запросов в секундах
SYNOLOGY_API_VERSION=1 # Версия API SYNOLOGY_API_VERSION=1 # Версия API
SYNOLOGY_POWER_API=SYNO.Core.System # 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) # WOL (Wake-on-LAN)
MAC_ADDRESS=00:11:22:33:44:55 # MAC-адрес Synology NAS
WOL_BROADCAST=255.255.255.255 # Broadcast-адрес для WOL WOL_BROADCAST=255.255.255.255 # Broadcast-адрес для WOL
WOL_PORT=9 # Порт для WOL (обычно 7 или 9) WOL_PORT=9 # Порт для WOL (обычно 7 или 9)

View File

@@ -2,6 +2,6 @@
FROM python:3.11-slim FROM python:3.11-slim
WORKDIR /app WORKDIR /app
COPY src/wol_proxy.py ./ COPY src/wol_proxy.py ./
RUN pip install flask RUN pip install flask python-dotenv
EXPOSE 5000 EXPOSE 5002
CMD ["python", "wol_proxy.py"] CMD ["python", "wol_proxy.py"]

14
deploy.sh Normal file → Executable file
View File

@@ -16,8 +16,8 @@ if ! [ -x "$(command -v docker)" ]; then
fi fi
echo -e "${YELLOW}Проверка наличия Docker Compose...${NC}" echo -e "${YELLOW}Проверка наличия Docker Compose...${NC}"
if ! [ -x "$(command -v docker-compose)" ] && ! [ -x "$(command -v docker compose)" ]; then if ! docker compose version > /dev/null 2>&1; then
echo -e "${RED}Ошибка: Docker Compose не установлен.${NC}" >&2 echo -e "${RED}Ошибка: Docker Compose не установлен или не работает.${NC}" >&2
echo -e "Установите Docker Compose, следуя инструкциям: https://docs.docker.com/compose/install/" echo -e "Установите Docker Compose, следуя инструкциям: https://docs.docker.com/compose/install/"
exit 1 exit 1
fi fi
@@ -37,13 +37,13 @@ chmod 777 logs
# Сборка и запуск Docker контейнеров # Сборка и запуск Docker контейнеров
echo -e "${YELLOW}Сборка и запуск Docker контейнеров...${NC}" echo -e "${YELLOW}Сборка и запуск Docker контейнеров...${NC}"
docker-compose down docker compose down
docker-compose up -d --build docker compose up -d --build
# Проверка статуса контейнеров # Проверка статуса контейнеров
echo -e "${YELLOW}Проверка статуса контейнеров...${NC}" echo -e "${YELLOW}Проверка статуса контейнеров...${NC}"
docker-compose ps docker compose ps
echo -e "${GREEN}Развертывание завершено успешно!${NC}" echo -e "${GREEN}Развертывание завершено успешно!${NC}"
echo -e "Для просмотра логов: ${YELLOW}docker-compose logs -f${NC}" echo -e "Для просмотра логов: ${YELLOW}docker compose logs -f${NC}"
echo -e "Для остановки: ${YELLOW}docker-compose down${NC}" echo -e "Для остановки: ${YELLOW}docker compose down${NC}"

View File

@@ -3,7 +3,6 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: synology-power-control-bot
restart: unless-stopped restart: unless-stopped
env_file: env_file:
- .env - .env
@@ -26,7 +25,6 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile.wol dockerfile: Dockerfile.wol
container_name: wol-proxy
restart: unless-stopped restart: unless-stopped
network_mode: host network_mode: host
@@ -34,7 +32,6 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile.nas dockerfile: Dockerfile.nas
container_name: nas-emulator
restart: unless-stopped restart: unless-stopped
network_mode: host network_mode: host
networks: networks:

View File

@@ -2,11 +2,25 @@ from flask import Flask, request, jsonify
import socket import socket
import struct import struct
import os import os
from dotenv import load_dotenv
# Загружаем переменные окружения из файла .env
load_dotenv()
app = Flask(__name__) 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-пакета # Функция отправки WOL-пакета
def send_wol(mac_address): def send_wol(mac_address=None):
# Если MAC-адрес не предоставлен, используем из .env
if not mac_address:
mac_address = MAC_ADDRESS
# Проверка формата MAC # Проверка формата MAC
mac_address = mac_address.replace(':', '').replace('-', '') mac_address = mac_address.replace(':', '').replace('-', '')
if len(mac_address) != 12: if len(mac_address) != 12:
@@ -19,30 +33,47 @@ def send_wol(mac_address):
# Отправка пакета # Отправка пакета
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(send_data, ('<broadcast>', 9)) sock.sendto(send_data, (WOL_BROADCAST, WOL_PORT))
sock.close() sock.close()
@app.route('/wol', methods=['POST']) @app.route('/wol', methods=['POST'])
def wol(): def wol():
data = request.get_json() data = request.get_json() if request.is_json else {}
mac = data.get('mac') mac = data.get('mac')
if not mac:
return jsonify({'error': 'MAC-адрес обязателен'}), 400
try: try:
send_wol(mac) # Если MAC не указан, используем MAC из .env
return jsonify({'status': 'WOL sent', 'mac': mac}) 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: except Exception as e:
return jsonify({'error': str(e)}), 500 return jsonify({'error': str(e)}), 500
# Пример получения IP по MAC через парсинг DHCP lease-файла @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 адреса NAS
@app.route('/ip', methods=['GET']) @app.route('/ip', methods=['GET'])
def get_ip(): 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-файлу lease_file = '/var/lib/dhcp/dhcpd.leases' # путь к lease-файлу
if not mac:
return jsonify({'error': 'MAC-адрес обязателен'}), 400
if not os.path.exists(lease_file): if not os.path.exists(lease_file):
return jsonify({'error': 'Lease-файл не найден'}), 500 return jsonify({'error': 'Lease-файл не найден'}), 500
ip = None ip = None
with open(lease_file, 'r') as f: with open(lease_file, 'r') as f:
for line in 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; ... } # Пример: lease 192.168.1.100 { ... hardware ethernet 00:11:22:33:44:55; ... }
if 'lease' in line: if 'lease' in line:
ip = line.split()[1] ip = line.split()[1]
if ip: if ip:
return jsonify({'ip': ip, 'mac': mac}) return jsonify({'ip': ip, 'mac': mac, 'source': 'lease'})
else: else:
return jsonify({'error': 'IP не найден для MAC'}), 404 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__': if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000) app.run(host='0.0.0.0', port=5002)