Появилась необходимость собрать медиацентр для просмотра видео, прослушивания музыки на основе компьютера (системного блока) и современного телевизора (Samsung). Казалось что всё просто, соединилразьёмы HDMI на системнике с телевизором и всё. Но, оказывается, телевизор в плане включения/выключения не работает как монитор и когда компьютер выключается, то телевизор остаётся включённым и продолжает ждать сигнала. Потом он выключается минут через 15 и при запуске компьютера его приходится включать с пульта. В общем не удобно.
После поиска по сайтам, на ютубе, на Алиэкспрессе выяснилось, что ничего сделать с этим нельзя, настроек в телевизоре нет, каких-то специальных доступных устройств тоже нет. Пришлось искать решение.
Помогла в этом решении такая особенность телевизора, что если он работал, но был выключен из розетки, а потом снова включен в розетку, то он включался в то же самое состояние (то есть рабочее, не выключенное).
И пришла идея этим воспользоваться и управлять электропитанием розетки, в которую включен телевизор.
В принципе тут ничего сложного нет, покупается китайский модуль рэле, в биосе делаются настройки питания USB, чтобы в выключенном состоянии не было питаня на порты USB и подключаем провод от USB к рэле таким способом, чтобы при подаче 5 вольт рэле включалось, и при отсутствии питания выключалось. Рэле, естественно, управляет нагрузкой в 220 вольт и подключается к блоку розеток.
Можно было бы и так оставить, но есть нюанс. В настройках Windows есть такие параметры: Питание и спящий режим -> Экран (отключение через столько-то минут) и Спящий режим (который переводит систему в спящий режим, но питание на портах USB при этом остаётся), экран при этом, естественно, должен выключаться.
Вот тут и начались реальные проблемы. Просто так получить какие-то данные откуда-нибудь, что экран находится в ждущем режиме, то есть выключен, или что комп находится в спящем режиме и соответственно, нужно выключить телевизор.
По кабелю HDMI инфу такую не получить в нормальном виде, типа наличия или отсутствия +5V. Программно это тоже никак не вытащить из винды. Сторонние программы использовать не хотелось, разбираться в их функционале. Что же делать?
Короче, решение я придумал такое. Оно сложное, но процентов 90 различных сценариев включения/выключения телевизора-монитора выполняет. Да, 90% а не 100!!! Но и это уже неплохо.
Итак, что нам потребуется.
- Паяльник и всё что с этим связано.
- Плата Arduino Nano (если вы не знаете, что такое ардуино, то у меня для вас плохие новости... Вам придётся изучить что это такое, установить нужный софт для прошивки: Arduino IDE, и, возможно, драйвера для платы и пакеты Java JRE. Подробнее об этом можно посмотреть здесь Гайд для новичков Arduino)
Плату Ардуино Нано можно купить здесь, вроде нормальная, мне пришла полностью рабочая https://aliexpress.ru/item/1994733794.html я брал с разьемом Type-C.
Пришла плата с ATmega328P, в Arduino IDE выбирается именно как просто ATmega328P, а не ATmega328P(Old Bootloader), это важно, иначе невозможно будет загрузить прошивку.
Если плата не определяется системой , то нужно установить драйвера для неё.
- Провод USB - Type-C. Провод должен уметь передавать данные, а не только для зарядки.
- Модуль рэле. Я использовал такой на 5V-220V на 30 А https://aliexpress.ru/item/1005005559047128.html. Он хорошо работает, контакты не залипают, хоть и размером побольше.
- Какой-нибудь конденсатор.
- Подходящий Корпус для РЭА, куда всё это безобразие можно убрать.
- Розеточный модуль, например такой https://www.ozon.ru/product/rozetka-chetyrehmestnaya-dlya-otkrytoy-ustanovki-serii-praleska-bylectrica-svetopribor-ra16-264cher-672626230/
- Различные провода.
- Мультиметр.
Из программного обеспечения нам потребуется:
- Скетч для Ардуино
- Скрипт PowerShell для отслеживания активности на компьютере.
- Скрипт для фонового (незаметного) запуска скрипта PowerShell при запуске системы.
- Настройка в Windows запуска скрипта через Планировщик заданий
Для начала нам нужно правильно спаять ардуино и соединить её с рэлейным модулем.
Я сделал это по такой схеме:
Конденсатор нужен для того, чтобы Ардуино не перезагружалась при подкючении к COM порту, его надо подключать после загрузки прошивки, иначе прошивка не загрузится
Ардуино будет управлять рэле в зависимости от сигналов от скрипта PowerShell.
Логика тут такая:
Допустим у нас в настройках Windows: Питание и спящий режим -> Экран указано 45 минут, значит экран отключится через 45 минут бездействия пользователя, но система будет продолжать так же работать.
Нам нужно отключить питание телевизора через 45 минут бездействия.
Но так как мы не можем напрямую получать данные когда экран отключен, мы делаем это с помощью скрипта PowerShell. То есть начинаем независимо следить за последней активностью пользователя, а именно мышью и клавиатурой.
То есть мы с помощью скрипта PowerShell:
- Проверяем активность каждые 60 секунд и отправляем команду на Ардуино каждые 60 секунд, что активность есть и рэле должно быть включено.
- Если активность пропадает через 45 минут, мы посылаем на Ардуино, что рэле нужно выключить.
- После этого начинаем проверять активность через каждые 5 секунд (предположительно экран выключен, но система продолжает работать).
- Если активность появляется, то отправляем команду включить рэле.
Это значит, что мы включим рэле через 5 секунд, например после движения мыши и в то же время мы не грузим систему частыми проверками на активность, делаем это раз в 60 секунд.
Допустим Ардуино полдключена к порту COM3.
Скрипт PowerShell будет такой:
# Подключение к последовательному порту
$port = new-Object System.IO.Ports.SerialPort COM3,9600,None,8,one
$port.Open()
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class IdleTimeFinder {
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
public static int GetIdleTime() {
LASTINPUTINFO lastInPut = new LASTINPUTINFO();
lastInPut.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
GetLastInputInfo(ref lastInPut);
return Environment.TickCount - (int)lastInPut.dwTime;
}
}
"@
$checkInterval = 60 # Интервал проверки по умолчанию — 60 секунд
while ($true) {
$idleTime = [IdleTimeFinder]::GetIdleTime()
if ($idleTime -gt 2700000) { # 45 минут
Write-Host "Monitor likely OFF"
$port.WriteLine("0") # Отправляем команду на выключение реле
$checkInterval = 5 # Если монитор неактивен, проверять каждые 5 секунд
} else {
Write-Host "Monitor likely ON"
$port.WriteLine("1") # Отправляем команду на включение реле
$checkInterval = 60 # Если монитор активен, проверять каждые 60 секунд
}
Start-Sleep -Seconds $checkInterval # Задержка проверки на основе состояния
}
# Закрытие порта по завершению
$port.Close()
Сохраните его в блокноте и переименуйтк файл в monitor_control.ps1 и поместите его в папку C:\Scripts\monitor_control.ps1
Что делает Ардуино?
- При запуске компьютера на ЮСБ появляется 5 вольт. Ардуино включает рэле и начинает ждать 3 минуты до появления команд от PowerShell. 3 минуты должно хватить на загрузку системы и запуска PowerShell.
- Далее Ардуино начинает получать сигналы от PowerShell (каждые 60 секунд).
- Если сигнал приходит, что активности нет, то выключает рэле (45 минут).
- Если сигнал приходит, что активность есть - включает рэле.
- Если вдруг какие-либо сигналы перестают приходить от PowerShell в течении 3 минут, то отключаем рэле (комп ушел в спящий режим).
- При выходе из спящего режима PowerShell снова начинает отправлять команды на включение рэле. И экран телевизора включается.
Скетч для Ардуино такой:
const int relayPin = A4; // Пин, к которому подключено реле
bool relayState = true; // Состояние реле по умолчанию - включено
unsigned long lastSignalTime = 0; // Время последнего полученного сигнала
const unsigned long timeout = 180000; // Таймаут в 3 минуты (180000 миллисекунд)
void setup() {
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH); // Включаем реле при старте
Serial.begin(9600); // Открытие последовательного порта
lastSignalTime = millis(); // Устанавливаем текущее время как время последнего сигнала
}
void loop() {
// Проверяем, есть ли данные в последовательном порту
if (Serial.available() > 0) {
char command = Serial.read(); // Чтение команды из последовательного порта
if (command == '0') {
relayState = false; // Выключаем реле при команде '0'
} else if (command == '1') {
relayState = true; // Включаем реле при команде '1'
}
// Обновляем время последнего получения сигнала
lastSignalTime = millis();
}
// Проверяем, прошло ли больше 3 минут с последнего сигнала
if (millis() - lastSignalTime > timeout) {
relayState = false; // Отключаем реле, если прошло больше 3 минут
}
// Управляем реле на основе состояния
if (relayState) {
digitalWrite(relayPin, HIGH); // Реле включено
} else {
digitalWrite(relayPin, LOW); // Реле выключено
}
}
Для того чтобы запустить PowerShell-скрипт скрытно при загрузке Windows через wscript.exe, следуйте этим шагам:
- Создание VBS-файла для скрытого запуска PowerShell-скрипта
- Откройте Блокнот и ставьте следующий код:
Set objShell = CreateObject("WScript.Shell") objShell.Run "powershell.exe -ExecutionPolicy Bypass -File ""C:\Scripts\monitor_control.ps1""", 0, False
Обратите внимание:
Путь "C:\Scripts\monitor_control.ps1" замените на полный путь к вашему PowerShell-скрипту. - Сохраните файл как VBS-скрипт: hidden_monitor_control.vbs и поместите также в папку: C:\Scripts\hidden_monitor_control.vbs.
- Откройте Блокнот и ставьте следующий код:
- Создание задачи в Планировщике заданий для запуска VBS-файла
- Откройте Планировщик заданий:
- Нажмите Win + R, введите taskschd.msc, и нажмите Enter.
- В левой панели выберите "Библиотека планировщика заданий".
- В правой панели выберите "Создать задачу...".
- В окне создания задачи на вкладке "Общие":
- Введите имя для задачи, например, "Hidden PowerShell Script".
- Выберите "Выполнять независимо от входа пользователя".
- Поставьте галочку "Запускать с наивысшими правами".
- Перейдите на вкладку "Триггеры":
- Нажмите "Создать...".
- В поле "Начать задачу" выберите "При входе в систему".
- Нажмите ОК.
- Перейдите на вкладку "Действия":
- Нажмите "Создать...".
- В поле "Действие" выберите "Запустить программу".
- В поле "Программа или сценарий" введите:
wscript.exe
- В поле "Добавить аргументы" введите путь к вашему VBS-файлу, например:
"C:\Scripts\hidden_monitor_control.vbs"
- Нажмите ОК.
- Перейдите на вкладку "Условия":
- Снимите галочку с опции "Запускать только при питании от электросети", если вы хотите, чтобы задача выполнялась даже при питании от батареи (например, на ноутбуке).
- Откройте Планировщик заданий:
- Проверка работы
- Перезагрузите компьютер.
- PowerShell-скрипт должен запуститься автоматически, не показывая окна консоли.
- Перезагрузите компьютер.
Этот метод позволит вам запускать PowerShell-скрипт при старте Windows скрытно, без отображения окон консоли.