Мой основной компьютер - macbook, который всегда со мной, и на котором я делаю почти все что нужно как дома так и вне его. Но также есть домашний комп, на котором бывает оптимальнее делать ресурсоемкие задачи. Кроме того, некоторые вещи на маке делать неудобно или вовсе невозможно, поэтому на домашнем на разных дисках установлены windows, ubuntu и proxmox с десятком виртуалок под разные случаи. И меня всегда очень напрягала невозможность удаленно включить нужную операционную систему на домашнем, чтобы потом подключиться к ней удаленно и сделать все что нужно.

И что вы думаете - решил я эту проблему. Теперь из любого места я могу запустить нужную мне операционную систему на домашнем компе одним кликом.

Конечно, без Home Assistant не обошлось.

Хорошенько подумав над задачей я увидел всего два надежных реализуемых варианта.
Первый - как то извне управлять GRUB, всегда запускаемым первым.
Второй - физически подключать нужный диск перед включением компьютера.
Поскольку мыжкампутерщики вариант загрузить что придется, руками поправить загрузчик и перезагрузиться не рассматривается. Ну и поскольку речь не о сервере а о бытовом компе варианта удаленной консоли управления тоже нет.

Как например можно реализовать первый вариант? Взять служебный небольшой диск, можно даже флешку или DoM. Установить на нее какую нибудь легковесную linux, и в конфиг ее grub'а записать все остальные диски, имеющиеся на компе. Компьютер должен всегда первым делом загружать эту служебную ось, а она, загрузившись, должна взять откуда то команду о том какую целевую ось загрузить следующей, внести изменения в свой конфиг, и перезагрузить компьютер. А затем из загрузившейся целевой системы первым делом исправить конфиг того загрузчика обратно. В целом рабочий вариант, но мне кажется сложным и ненадежным.

Второй вариант - управлять физическим подключением дисков. В биосе настроить каждый из этих дисков загрузочным, и собственно перед включением компа выключать лишние диски. Кажется надежнее и интереснее, но нужен какой то физический интерфейс управления. На этом варианте я и решил остановиться.

Часть первая - железная.

Купил вот такое четырехканальное zigbee реле Tuya.

Пока ехало, нарисовал и напечатал конструкцию для крепления дисков и реле

Немножко теории:
Современные sata диски по стандарту получают 5 (красный цвет) и 12 (желтый цвет) вольт. В целях совместимости еще 3,3 (оранжевый цвет) вольта иногда можно встретить, но чаще этот провод просто отсутствует.

Для работы SSD дискам нужно только 5 вольт. 12 по моему HDD нужно, а SSD без него прекрасно работают.
Поскольку у меня именно ssd, то врезаться будем в красный провод.

Дисклеймер: я не претендую на истину в последней инстанции, и все что делаю - делаю на свой страх и риск. Разумеется, это грубый обход стандартов, и он может мне аукнуться в будущем, но вряд ли серьезно, так как ничего важного или нерезервируемого на этих дисках нету, да и в целом этот комп мне не очень дорог. Если у вас ситуация другая, может быть вам стоит поискать другой вариант.

После сборки получилась такая конструкция:

Фото к сожалению не финальное, первой сборки, и там есть неточности. На фото реле управляет желтыми проводами, а нужно красными. Верную версию забыл сфотографировать. Верхний диск действительно hdd, правильный диск был занят пока, потом заменю. А еще в финальной версии выкинул колодку и все провода пропаял, на них были потери напряжения и это негативно сказывалось на работе.
Провода включены в нормально закрытые разъемы, то есть в выключенном состоянии реле все диски включены.

Раз дисков 3 а каналов 4 - а зачем же еще канал. А его я подключил к кнопке питания компьютера, прямо на контакты на материнке, в параллель к физической кнопке.

Следующим шагом было запитать реле и подключить его к home assistant. Для питания в закромах нашелся подходящий адаптер, ну а в процессе подключения нет ничего нового.
В результате у меня в HA появилось устройство, управляющее всем что нужно

Часть вторая - программная

Устройство есть, теперь надо сделать красиво.

Делаем скрипты в HA, которые будут нажимать на кнопки. Скрипт в данном контексте - это то же самое что автоматизация, только для ручного запуска, без авто-условий.

Скрипт запуска нужной операционной системы.

alias: Запустить Windows
sequence:
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l1
        - switch.rele_diskov_kompiutera_l2
        - switch.rele_diskov_kompiutera_l2
  - service: switch.turn_on
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l3
        - switch.rele_diskov_kompiutera_l2
  - service: switch.turn_on
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
  - delay:
      hours: 0
      minutes: 0
      seconds: 1
      milliseconds: 0
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
  - service: input_boolean.turn_on
    target:
      entity_id: input_boolean.compon
    data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 90
      milliseconds: 0
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l1
        - switch.rele_diskov_kompiutera_l2
        - switch.rele_diskov_kompiutera_l3
mode: single

Поясню. Сначала на всякий случай подключаем все диски, вдруг осталось что то выключенное. Потом выключаем ненужные диски. Потом нажимаем кнопку питания компа, ждем секунду, и отпускаем ее. Потом включаем вспомогательный переключатель, хранящий в себе состояние компьютера, о нем ниже. Потом ждем 90 секунд, и подключаем остальные диски, они уже не помешают.

Помним, что состояние дисков инвертировано, то есть включая "отключить диск" я его физически отключаю.
Такие же скрипты делаем для остальных операционных систем, номера контактов будут отличаться.

Добавляем еще два скрипта, эмулирующих нажатие кнопки питания.

alias: Тык питание компа
sequence:
  - service: switch.turn_on
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
  - delay:
      hours: 0
      minutes: 0
      seconds: 1
      milliseconds: 0
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
mode: single
alias: Долгий тык питание компа
sequence:
  - service: switch.turn_on
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
        - switch.rele_diskov_kompiutera_l4
mode: single

Долгий тык нужен для принудительного выключения компа, если операционная система не реагирует на короткий и не завершает работу правильно.

Теперь можно позапускать скрипты и насладиться перещелкиванием реле и запуском нужных осей. Но еще некрасиво. Добавим еще немного свистелок. Лично мне не хватает наглядной информации о том что сейчас запущено.

Сделаю это так - после запуска каждая из операционных систем будет периодически стучаться в HA представляться и сообщать что она запущена. А тот соответственно будет проверять - было ли обновление состояния, и если нет то считать комп выключенным. Получится такой примитивный активный мониторинг.

В HA добавляем вспомогательный элемент типа Список. Назовем его например compstate и заполним списком с текущими. И еще один типа Переключатель - compon.

Для возможности обращения по api добавим токен. Это делается в параметрах текущего пользователя

Теперь со всех операционных систем надо настроить обращение по api и передачу состояния. Я не буду описывать конкретные методы, они могут отличаться в разных системах. Суть проста. Надо отправить POST запрос на http://ip_адрес_сервера_HA:8123/api/states/input_select.compstate, авторизоваться токеном, и передать json с одним из вариантов, добавленных ранее в список. В большинстве случаев подойдет curl, он есть и для windows. Ну то есть добавляем в cron или в планировщик вызов курла, или делаем это любым другим подходящим способом.

curl \
  -H "Authorization: Bearer тут_вставить_токен" \
  -H "Content-Type: application/json" \
  -d '{"state": "ubuntu"}}' \
  http://ip_адрес_сервера_HA:8123/api/states/input_select.compstate

Можно попробовать, и убедиться что состояние вспомогательного элемента compstate меняется.

Теперь делаем автоматизацию, которая будет проверять состояние этого элемента. Я о ней упоминал выше, убедитесь что в скрипте запуска верное имя.
Создаем новую автоматизацию и вставляем код.

alias: Проверка состояния компа
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.compon
    from: "off"
    to: "on"
condition: []
action:
  - repeat:
      sequence:
        - delay:
            hours: 0
            minutes: 2
            seconds: 0
            milliseconds: 0
        - if:
            - condition: or
              conditions:
                - condition: state
                  entity_id: input_select.compstate
                  state: windows
                  for:
                    hours: 0
                    minutes: 3
                    seconds: 0
                - condition: state
                  entity_id: input_select.compstate
                  state: ubuntu
                  for:
                    hours: 0
                    minutes: 3
                    seconds: 0
                - condition: state
                  entity_id: input_select.compstate
                  state: proxmox
                  for:
                    hours: 0
                    minutes: 3
                    seconds: 0
          then:
            - service: input_boolean.turn_off
              target:
                entity_id: input_boolean.compon
              data: {}
            - service: input_select.select_option
              target:
                entity_id: input_select.compstate
              data:
                option: offline
      while:
        - condition: state
          entity_id: input_boolean.compon
          state: "on"
mode: single

Поясню. После запуска автоматизации при переключении служебного элемента она каждые две минуты повторяет одну и ту же проверку пока включен вспомогательный элемент compon.
Проверяем - если элемент compstate в течение 3 минут уже равен одному из значений списка, то делаем вывод что компьютер выключен или не отвечает, меняем статус на offline и виртуальный переключатель выключаем, после чего завершаем автоматизацию.

Ну и последний пункт - отображаем все на панели управления. Для этого добавляем на панель lovelace вертикальный стек с таким кодом:

type: vertical-stack
cards:
  - type: markdown
    content: >
      {% set p = states('input_boolean.compon') %} Компьютер {{ 'включен' if p
      == "on" else 'выключен' if p == "off" }}. 

      {% set s = states('input_select.compstate') %} Состояние - {{ 'Загружен
      windows' if s == "windows" else 'Загружен ubuntu' if s == "ubuntu" else
      'Загружен proxmox' if s == "proxmox" else 'offline' if s == "offline" }}. 
  - type: entities
    entities:
      - entity: script.windows
      - entity: script.ubuntu
      - entity: script.proxmox
      - entity: script.unknown
      - entity: script.unknown_2

Поясню - сверху показываем markdown карточку, в которой выполняем простые сравнения. Если переключатель compon включен то пишем Компьютер включен, иначе Компьютер выключен.
И второй строчкой выводим состояние compstate.
Снизу выводим команды запуска наших скриптов.
Вот что получается:

Я специально сделал скриншот с мобильного, чтобы показать насколько я теперь свободен в запуске нужной системы на домашнем компе :)

Вот как то так. Статья получилась несколько сумбурная, но надеюсь интересная. Помните - Home Assistant это не только ценный мех но и возможность управления другими компьютерами.

Ну и напоследок красивая картинка. Не знаю даже почему она в голове)

Комментарии (19)


  1. SUNsung
    20.04.2024 01:04
    +5

    А в чем проблема была ограничится переключением на уровне grub? Насколько мне известно можно взять серверный свисток и просто работать с апи свистка для запуска/ребута и тд внутри локальной сети (если материнка серверная то там уже все есть, свисток не нужен) и подключить как удобно к хомасистент. (если есть такая огромная необходимость к удаленному запуску ПК с выбором операционки)

    Да и переключение чисто по питанию такое себе решение. Как минимум при скачке напряжения (когда "могнет" реле) диск может превратится в тыкву.

    В целом же я не так много знаю именно за sata, но по логике вешей отсутсвие питания, при наличии живой логической шины может как то "сказатся". Но опять таки я не совсем вкурсе, если sata это независимые интерфейсы и требуется наличие питания "на конце" что бы начался обмен то все хорошо. Но эти это частичный случай какой-то асинхронной шины, где процессор просто "выбирает" нужное подключенное устройсво то как минимум будут потери на подключеных на шине, как максимум можно спалить пины шины.


    1. kolabaister Автор
      20.04.2024 01:04

      Чтобы выбрать систему из груба комп уже должен быть включен и нужен доступ к консоли.

      Реле управляет питанием дисков только в течение 90 сек после запуска. А так они включены всегда и что бы не случилось с реле или его питанием на дисках это не скажется.

      Пока все работает. Да, я тоже не очень знаю спецификацию sata, даже назначение напряжение плохо описано в популярных источниках.
      Собственно, как я написал, риски может и есть, но я считаю их допустимыми.


      1. CaptGg
        20.04.2024 01:04
        +6

        У вас уже используется Wake-on-LAN для включения ПК.

        Вам нужно было лишь в запускаемой по-умолчанию ОС добавить скрипт, который при загрузке запрашивает у Home Assistant по http REST API какую ОС необходимо загрузить и если она не совпадает с текущей, то выполняет grub-reboot [номер ОС].

        Такое программное решение выглядит проще и надежнее.

        Для удобства скрипту можно добавить предложение нажать ESC в течение 5 секунд, чтобы отменить перегрузку локально. Так можно будет включать ПК локально не задумываясь что там выбрано в Home Assistant.


        1. Goron_Dekar
          20.04.2024 01:04

          Класс! А как это сделать? Фиксированный IP? DHCP? У меня в компе, который имеет несколько систем, специально настроены разные mac адреса чтобы ip системы зависил от ОС: так проще домашний firewall насторить.

          Я когда-то думал для этого использовать DHCP запрос: в ответе сервера указать, какую ОС загрузить в доп. хедерах. Но как это сделать в grub os так и не понял.


          1. CaptGg
            20.04.2024 01:04
            +1

            На ПК должна быть зафиксирована ОС, загружающаяся по-умолчанию всегда, при помощи grub-set-default. Желательно Linux, т.к. в нем это можно сделать в несколько строк на Bash. После загрузки запускается скрипт, делающий исходящий запрос к Home Assistant API по HTTP, получает ответ какая ОС должна быть загружена и запускает с правами root grub-reboot <номер> && reboot с нужным номером загрузочной записи.

            Всё. Не важно какой IP и MAC у ПК, важен лишь доступ с него к Home Assistant.


            1. Goron_Dekar
              20.04.2024 01:04
              +2

              Точно! Жаль ,что это будет значить двойной ребут, что местами просто не красиво, но в моём случае это отличное решение. И, в отличие от метода, описанного в статье, всегда есть доступ до всех ЖД.


  1. artko
    20.04.2024 01:04

    А чем не подошел вариант грузить только proxmox, а в нем виртуалку с нужной ос? (Отдельно вопрос, зачем убунта, если уже есть proxmox, основаньій на дебиане...)


    1. kolabaister Автор
      20.04.2024 01:04

      не хочу терять в производительности и возиться с пробросом видеокарты.

      Потому что в убунте есть десктоп) Ну и вообще не стоит нагружать гипервизор непрофильными задачами


  1. NutsUnderline
    20.04.2024 01:04
    +1

    была статья (вроде тут на хабре но это не точно) - сделали некий девайс на stm32 который решал задачу выбора загрузочного диска в grub

    Поиск дает такое https://github.com/stecman/hw-boot-selection https://github.com/rw-hsma-fpga/grub-switch наверное что то еще есть

    Суть не в том что это аппаратное устройство а в том что grub может управляться "извне"


    1. kolabaister Автор
      20.04.2024 01:04

      Интересная какая разработка. Но как я понял смысл тут именно в программно-аппаратном комплексе. Программа нужна чтобы не надо было эмулировать клавиатуру и подать не ненадежную комбинацию кнопок вверх/вниз а что то вроде аппаратного api поддержать, а прямого управления по сети она не поддерживает. Может я конечно неправильно понял, по диагонали пробежался.


  1. Lev3250
    20.04.2024 01:04

    Грубо конечно, но мне нравится


  1. vp7
    20.04.2024 01:04

    Страх и ужас ;((

    А если не будет грузиться, ошибки какие-то выдавать?

    У вас же HA крутится на каком-то железе? Я бы добавил туда IP KVM и решил этим проблему. Если аппаратный IP KVM не нравится - возьмите USB свисток с HDMI входом, эмулирующий USB камеру (на Али в пределах 1 т.р.) + эмулятор клавиатуры (реально собрать готовый проект на всяких ESP32). А на релюхи - вывести кнопку включения и reset.


    1. kolabaister Автор
      20.04.2024 01:04

      Ну будут и будут. Выключу и попробую еще раз. Если не получится - ну и ладно, есть и другие варианты решения вопросов, например подключусь к какому нибудь рабочему серверу.

      Железные ip kvm - это как то совсем небюджетно. Для домашнего решения перебор.
      Второй вариант побюджетнее, не знал про hdmi камеры, спасибо.

      Но - мне не нравятся такие решения. KVM - это все же про работу и про кровавый энтерпрайс, я же в личной жизни стараюсь автоматизировать до уровня кнопки "сделать красиво". HA в этом плане мне сильно нравится потому что в нем можно почти все сделать. Получившаяся у меня схема отвечает этому критерию.


    1. nsmcan
      20.04.2024 01:04

      Могли бы Вы дать линку на конкретный USB свисток? И как с его помощью получить экран удалённо?


      1. SUNsung
        20.04.2024 01:04

        Вам не нужно получать экран для выбора grub

        Я тут почитал коментарии и понял что для решения задачи хватит одной ардуины на esp32.

        Esp32 для связи с умным домом (вайфай) а ардуина собственно для того что бы иметь связь с материнкой по ttl. А уже в самом grub сделать запрос запускаемого диска с ttl порта. Включение и ребут так же спокойно делается с esp так как обычно в материнке у кнопок управление землей


        1. vp7
          20.04.2024 01:04
          +1

          Для grub'а можно использовать serial console (com порт), для ядра linux тоже самое. Но это решает только часть возможных проблем при загрузке и только с linux'ом. Поэтому возможность зайти в BIOS мне кажется очень и очень полезной.


      1. vp7
        20.04.2024 01:04

        Последнее время их появилось очень много. Я купил два на пробу и оба хорошо работают, задержка минимальна (подключил вместо монитора одного компа, на экран другого компа вывел "usb камеру" и свободно пользовался первым компом):

        1. Просто свисток (1900 рублей) https://aliexpress.ru/item/1005004754486040.html

        2. Свисток с дублированием потока (1000 рублей) - есть HDMI In, HDMI Out, перехватывает видео по USB: https://aliexpress.ru/item/1005003576399052.html

        Также есть куча свистков за 200-400 рублей, но про них ничего сказать не могу, по отзывам - они не могут держать полноценно Full HD 30/60 FPS, но для задачи "IP KVM на случай проблем с загрузкой" они должны без проблем справиться.


      1. NutsUnderline
        20.04.2024 01:04

        свисток то это не проблема, только вот "за скобками" остался целый программно-аппаратный комплекс который надо собрать на коленке по не особо готовым рецептам.

        тут была недавно статья - человек даже готовое решение PiKVM на малинке не осилил


  1. DaemonGloom
    20.04.2024 01:04
    +1

    Есть ещё пара более простых методов.
    Grub можно грузить по pxe (и, соответственно, дать ему любые настройки для загрузки нужного).

    Или можно отдавать по pxe только переменную для выбора ОС при загрузке, а весь остальной загрузчик и конфиг держать в самом компе. Тогда при отсутствии pxe сервера - компьютер всё равно можно будет загрузить в любую ОС через меню grub.

    Ну а отредактировать файл через автоматизацию - это уже просто.