- Python 100%
| .gitignore | ||
| CHANGELOG.md | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| SHA256SUMS | ||
| yoradio-scheduler.py | ||
| yoradio-scheduler.service | ||
| yoradio-scheduler.toml | ||
yoRadio Scheduler
yoRadio Scheduler — планировщик для интернет-радиоприёмников на прошивке yoRadio.
Программа запускается как служба systemd на отдельном Linux-сервере или мини-компьютере. По расписанию она устанавливает начальную громкость, включает выбранную станцию и останавливает воспроизведение в конце интервала. При необходимости можно включить плановую перезагрузку приёмника.
Во время активного интервала программа не возвращает станцию или громкость после ручного изменения и не включает радио повторно после ручного STOP. Начальные настройки применяются снова только при следующем запланированном запуске.
Возможности
- отдельное расписание для каждого дня недели;
- общие правила для нескольких дней, например
mon-fri; - отдельные исключения поверх общего правила;
- интервалы, переходящие через полночь;
- запуск выбранной станции с заданной начальной громкостью;
- STOP вне активного интервала;
- ограниченное окно автоматического запуска после времени
start; - сохранение ручного STOP, PLAY, выбранной станции и громкости до конца текущего интервала;
- необязательная плановая перезагрузка yoRadio вне активного интервала;
- ожидание готовности приёмника после перезагрузки;
- увеличивающиеся паузы между проверками, если радио недоступно;
- сохранение служебного состояния между перезапусками службы;
- работа только на стандартной библиотеке Python, без пакетов из
pip.
Требования
- Linux с
systemd; - Python 3.11 или новее;
- сетевой доступ от Linux-сервера к yoRadio;
- включённый Telnet-сервер в настройках yoRadio.
Для штатной конфигурации yoRadio используются HTTP-порт 80 и Telnet-порт 23. Эти значения указываются в http_port и telnet_port.
Проверка связи с радио
Узнайте IP-адрес приёмника и проверьте, что сервер видит оба порта. В примере используется адрес 192.168.1.100:
python3 - <<'PY'
import socket
host = "192.168.1.100"
for port in (80, 23):
try:
with socket.create_connection((host, port), timeout=3):
print(f"{host}:{port} OK")
except Exception as exc:
print(f"{host}:{port} ERROR: {exc}")
PY
Веб-интерфейс приёмника должен открываться по адресу:
http://192.168.1.100/
Telnet нужен для чтения текущего состояния. Если Telnet отключён в настройках yoRadio, включите его перед запуском планировщика.
Установка
Распакуйте архив и перейдите в каталог выпуска:
tar -xzf yoradio-scheduler-1.0.0.tar.gz
cd yoradio-scheduler-1.0.0
Установите программу и пример конфигурации:
sudo install -d -o root -g root -m 0755 /opt/yoradio-scheduler
sudo install -o root -g root -m 0755 \
yoradio-scheduler.py \
/opt/yoradio-scheduler/yoradio-scheduler.py
sudo install -o root -g root -m 0644 \
yoradio-scheduler.toml \
/opt/yoradio-scheduler/yoradio-scheduler.toml
sudo install -o root -g root -m 0644 \
yoradio-scheduler.service \
/etc/systemd/system/yoradio-scheduler.service
Откройте /opt/yoradio-scheduler/yoradio-scheduler.toml любым текстовым редактором и укажите адрес приёмника, станцию, громкость, часовой пояс и расписание.
Перед запуском проверьте конфигурацию:
python3 /opt/yoradio-scheduler/yoradio-scheduler.py \
--config /opt/yoradio-scheduler/yoradio-scheduler.toml \
--check-config
Если ошибок нет:
sudo systemctl daemon-reload
sudo systemctl enable --now yoradio-scheduler.service
Настройка радио
Основные параметры находятся в секции [radio]:
[radio]
host = "192.168.1.100"
http_port = 80
telnet_port = 23
station = 1
volume = 50
host — IP-адрес yoRadio, доступный с Linux-сервера.
station — номер станции в списке yoRadio.
volume — громкость yoRadio по шкале 0..254; это не проценты.
Для обычного подключения к yoRadio используйте http_port = 80 и telnet_port = 23.
Расписание
Часовой пояс задаётся в секции [schedule]:
[schedule]
timezone = "Europe/Moscow"
Используется имя часового пояса из базы IANA, например Europe/Moscow, Asia/Yekaterinburg или Europe/Berlin.
Одно правило для нескольких дней
Одинаковый график с понедельника по пятницу:
[[schedule.rules]]
days = "mon-fri"
start = "09:00"
stop = "18:00"
Неуказанные дни считаются выключенными.
Названия дней:
mon tue wed thu fri sat sun
Можно перечислить отдельные дни:
[[schedule.rules]]
days = ["mon", "wed", "fri"]
start = "10:00"
stop = "17:00"
Или объединить несколько диапазонов и отдельных дней:
[[schedule.rules]]
days = ["mon-tue", "thu", "sat-sun"]
start = "10:00"
stop = "17:00"
Циклические диапазоны вроде fri-mon не используются — такие дни нужно перечислить явно.
Интервал через полночь
Если stop раньше start, интервал заканчивается на следующий календарный день:
[[schedule.rules]]
days = "mon-fri"
start = "22:00"
stop = "06:00"
День в days — день начала интервала. Поэтому fri 22:00–06:00 означает пятницу с 22:00 до субботы 06:00. Такой интервал продолжает действовать утром субботы, даже если отдельного субботнего правила нет.
Рабочие интервалы не должны пересекаться. Соприкасающиеся интервалы разрешены: один может закончиться ровно в момент начала следующего.
start и stop не могут быть одинаковыми. Значение 09:00–09:00 не означает круглосуточную работу.
Отдельное расписание для одного дня
Общее правило можно переопределить. Например, если по пятницам радио должно выключаться раньше:
[[schedule.rules]]
days = "mon-fri"
start = "09:00"
stop = "18:00"
[schedule.fri]
enabled = true
start = "09:00"
stop = "16:45"
Чтобы полностью отключить день, попавший в общее правило:
[schedule.wed]
enabled = false
Вместо [[schedule.rules]] можно описать все семь дней отдельными секциями schedule.mon ... schedule.sun. Если используется только такой способ, должны быть заданы все семь дней.
Автоматический запуск
В начале активного интервала программа читает текущее состояние радио. Если громкость отличается от указанной в конфигурации, сначала устанавливается новая громкость и проверяется её фактическое применение. После этого отправляется команда запуска выбранной станции.
Для одного интервала автоматический запуск выполняется не более одного раза. Состояние сохраняется на диске, поэтому перезапуск службы в середине интервала не должен запускать радио повторно.
Окно запуска
Параметр startup_window ограничивает время, в течение которого разрешён автоматический запуск после start:
[control]
startup_window = 300
При значении 300 запуск разрешён в течение первых пяти минут интервала. Если сервер был выключен дольше и запустился уже после этого окна, радио автоматически не включится.
Ручное управление
После автоматического запуска и до конца текущего интервала программа не восстанавливает начальные настройки.
Можно вручную:
- остановить или снова запустить воспроизведение;
- выбрать другую станцию;
- изменить громкость.
Эти действия сохраняются до следующего запланированного запуска. По телеметрии yoRadio нельзя надёжно отличить ручной STOP от остановки потока по другой причине, поэтому автоматического восстановления PLAY внутри интервала нет.
Остановка вне расписания
Когда ни один рабочий интервал не активен, программа поддерживает состояние STOP. Если приёмник уже остановлен, лишняя команда не отправляется.
Если радио временно недоступно, частота проверок уменьшается согласно offline_backoff:
[monitor]
offline_backoff = [300, 600, 900]
В этом примере повторные проверки выполняются через 5 минут, затем через 10 минут и далее через 15 минут.
Плановая перезагрузка
Функция выключена по умолчанию:
[planned_reboot]
enabled = false
days = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
time = "03:00"
window = 300
post_reboot_delay = 35
Если её включить, программа выполняет перезагрузку только вне рабочего интервала:
- проверяет состояние приёмника;
- переводит его в STOP, если он играет;
- записывает на диск отметку о выполняемой перезагрузке;
- отправляет команду
reboot; - выдерживает
post_reboot_delay; - ждёт готовности Telnet и HTTP;
- проверяет, что радио после загрузки не осталось в состоянии PLAYING.
post_reboot_delay — минимальная пауза после отправки reboot. После аварийного завершения или перезапуска службы фактическое ожидание может оказаться немного больше.
Один и тот же плановый reboot после перезапуска Linux-службы повторно не отправляется.
SmartStart
Если в yoRadio включён SmartStart, после перезагрузки приёмник может самостоятельно возобновить воспроизведение раньше, чем планировщик успеет проверить его состояние.
Если после плановой перезагрузки радио не должно начинать воспроизведение самостоятельно, отключите SmartStart в настройках yoRadio.
Файл состояния
Служебное состояние хранится в:
/var/lib/yoradio-scheduler/state.json
Файл используется для защиты от повторного автоматического запуска и повторной плановой перезагрузки после рестарта службы. Редактировать его вручную не нужно.
Если файл повреждён, автоматический START и плановая перезагрузка блокируются. STOP вне расписания остаётся доступным.
Управление службой
Проверить состояние службы:
systemctl status yoradio-scheduler.service --no-pager -l
Остановить:
sudo systemctl stop yoradio-scheduler.service
Запустить:
sudo systemctl start yoradio-scheduler.service
Перезапустить после изменения конфигурации:
python3 /opt/yoradio-scheduler/yoradio-scheduler.py \
--config /opt/yoradio-scheduler/yoradio-scheduler.toml \
--check-config
sudo systemctl restart yoradio-scheduler.service
Перезапуск службы во время рабочего интервала не должен повторять уже выполненный автоматический запуск.
Журнал и текущее состояние
Последние записи журнала:
journalctl -u yoradio-scheduler.service -n 100 --no-pager
Просмотр журнала в реальном времени:
journalctl -u yoradio-scheduler.service -f
Текущее состояние радио можно прочитать без управляющих команд:
python3 /opt/yoradio-scheduler/yoradio-scheduler.py \
--config /opt/yoradio-scheduler/yoradio-scheduler.toml \
--status
Пример:
Время : 2026-09-24T14:02:00+03:00 (Europe/Moscow)
Ожидается: рабочий интервал (ручное управление)
Станция : 1 My Radio
Громкость: 50
Играет : True
Ограничения
- один экземпляр службы управляет одним приёмником;
- для каждого дня начала задаётся один непрерывный интервал
start–stop; - пересекающиеся рабочие интервалы запрещены;
PLAYING— состояние, которое сообщает yoRadio, а не измерение звука на физическом выходе;- программа не восстанавливает интернет-поток и не заменяет внутренний watchdog yoRadio;
- автоматического восстановления PLAY внутри активного интервала нет.
Безопасность
yoRadio Scheduler рассчитан на работу с приёмником в доверенной локальной сети. HTTP и Telnet yoRadio не должны быть доступны напрямую из Интернета.
Служба запускается с DynamicUser=yes, использует отдельный каталог состояния и ограничения systemd. После запуска права root ей не нужны.
Удаление
sudo systemctl disable --now yoradio-scheduler.service
sudo rm -f /etc/systemd/system/yoradio-scheduler.service
sudo systemctl daemon-reload
sudo rm -rf /opt/yoradio-scheduler
sudo rm -rf /var/lib/yoradio-scheduler
Последняя команда удаляет сохранённое состояние.
Лицензия
MIT. Полный текст находится в файле LICENSE.
Автор
Разработка: Виталий Егоров
E-mail: egorowitaliy@gmail.com