โปรเจกต์งานอดิเรก → อินพุตทีวี LG
เขียนเมื่อ 7 ตุลาคม 2026 · HOME ASSISTANT 2026.9.4
Home Assistant · webOS · ควบคุมภาพและเสียง

สลับอินพุตทีวี LG ให้ได้ผลจริงทุกครั้ง

สั่ง Home Assistant ให้ทีวี LG webOS ไปที่ HDMI 2 ด้วยวิธีตรง ๆ แล้วบางเย็นทีวีกลับเปิดแอปสตรีมมิงแทน หน้านี้อธิบายว่าทำไม ให้วิธีที่ได้ผล — เปิดอินพุตในฐานะแอปที่มันเป็นอยู่ลับ ๆ ซ้ำไปเรื่อย ๆ จนสถานะยืนยัน — และปิดท้ายด้วยสคริปต์ฉบับเต็มที่พาเครื่องเกมจากปิดไปจนเล่นบนจอ รวมถึงรีซีฟเวอร์ และรายงานเฉพาะสิ่งที่ตรวจสอบแล้วเท่านั้น

กับดัก

บน webOS ทุกอินพุต HDMI คือแอปพลิเคชัน — com.webos.app.hdmi1, hdmi2 และอื่น ๆ — และรายการแหล่งสัญญาณของทีวีปนแอปอินพุตเหล่านั้นเข้ากับแอปจริง media_player.select_source จับคู่กับรายการที่ปนกันนั้น และขึ้นกับว่าทีวีรายงานอะไรในขณะนั้น “เลือก HDMI 2” อาจกลายเป็นการเปิดแอปไหนก็ได้ที่ทีวีเพิ่งนึกชอบ กับดักที่สองคือจังหวะเวลา: ทีวี webOS ที่เพิ่งตื่นจะรับคำสั่งก่อนที่จะลงมือทำตาม คำสั่งสลับที่ส่งครั้งเดียวจึงหายไปในความว่างเปล่า และกับดักที่สามโหดที่สุด: การเชื่อมต่อ webOS ของ Home Assistant ตอบว่าสำเร็จสำหรับคำสั่งที่ส่งไปยังทีวีซึ่ง websocket หลุดไปเงียบ ๆ — คำสั่ง “สำเร็จ” แต่ไม่มีอะไรเกิดขึ้น

กฎที่ได้จากเรื่องนี้: อย่าใช้ media_player.select_source กับอินพุต HDMI บนทีวี LG และอย่าเชื่อคำสั่งแบบยิงแล้วลืมเพียงครั้งเดียว เปิดอินพุตในฐานะแอป ในลูป แล้วให้สถานะของเอนทิตีเองเป็นตัวตัดสินว่าเสร็จเมื่อไร

วิธีที่ได้ผล แบบเล็กที่สุด

เคล็ดลับทั้งหมดในสคริปต์เล็ก ๆ ตัวเดียว: เปิดทีวี (ไม่เสียหายอะไรถ้าเปิดอยู่แล้ว) แล้วเปิดแอป HDMI ทุกสองวินาทีจนทีวีรายงานว่าเปิดอยู่ แทนที่ entity id ด้วยของทีวีคุณ และแทน hdmi2 ด้วยอินพุตที่คุณต้องการ

สวิตช์อินพุตแบบเล็กที่สุด · scripts.yaml
select_hdmi2:
  alias: Select HDMI 2
  mode: single
  sequence:
    - action: media_player.turn_on
      target:
        entity_id: media_player.lg_webos_tv
      continue_on_error: true
    - repeat:
        until:
          - condition: or
            conditions:
              - condition: state
                entity_id: media_player.lg_webos_tv
                state: "on"
              - "{{ repeat.index >= 15 }}"
        sequence:
          - action: media_player.turn_on
            target:
              entity_id: media_player.lg_webos_tv
            continue_on_error: true
          - delay:
              seconds: 2
    - action: webostv.command
      data:
        command: system.launcher/launch
        payload:
          id: com.webos.app.hdmi2
      target:
        entity_id: media_player.lg_webos_tv
      continue_on_error: true

รายละเอียดสองอย่างแบกน้ำหนักทั้งหมด media_player.turn_on บนเอนทิตี webOS จะส่ง Wake-on-LAN เมื่อทีวีปิดอยู่ — ลูปจึงเป็นเส้นทางปลุกเครื่องไปในตัว และการส่งซ้ำระหว่างทีวีกำลังบูตคือสิ่งที่แพ็กเก็ตแรกที่อาจหลุดต้องการพอดี และ continue_on_error ทุกจุด ทำให้ทีวีที่กำลังบูตไม่ทำให้สคริปต์หยุดกลางคัน ลูปแค่ลองใหม่

รูปแบบเต็ม: เครื่องเกม รีซีฟเวอร์ ทีวี พร้อมการตรวจสอบ

คำขอจริงคือ “เปิด PlayStation” ซึ่งหมายถึงอุปกรณ์สามชิ้นทำงานประสานกัน: ปลุกเครื่องเกม ปลุกทีวี ตั้งรีซีฟเวอร์ไปที่อินพุตของเครื่องเกม ตั้งทีวีไปที่ HDMI ของรีซีฟเวอร์ — และกดทั้งหมดซ้ำไปเรื่อย ๆ จนรีซีฟเวอร์รายงานอินพุตที่ถูกต้อง และทีวีรายงานว่าเปิด หรือจนหมดงบเวลา 50 วินาที สคริปต์ด้านล่างคือเวอร์ชันที่ใช้งานจริงจากห้องนั่งเล่นของเรา เปิดให้ผู้ช่วยเสียงใช้ มันคืนประโยคให้พูดที่ไม่เคยอ้างเกินกว่าที่สถานะแสดง ในภาษาใดก็ได้จากสามภาษาที่คำขอส่งมา เปลี่ยน entity id ทั้งสี่และชื่ออินพุตเป็นของคุณ

ตัวอย่างที่ใช้งานจริง · scripts.yaml
select_ps5:
  alias: Select PS5
  icon: mdi:sony-playstation
  mode: single
  description: >-
    Turns the PlayStation 5 ON for the living room, end to end: wakes the console
    (switch.living_room_ps5_pro), turns on the LG TV and the receiver, then switches
    the receiver to its PlayStation 5 input and the TV to HDMI 2, retrying every 2 s
    (re-sending wake-on-LAN to the TV while it is off) until the receiver reports the
    PlayStation 5 input AND the TV is on (at most ~50 s). Use this for "turn on the
    PS5", "switch to the PlayStation", "I want to play" and their translations.
    Never use the bare console switch for these requests: it wakes the console but
    leaves the TV and receiver untouched. Returns a sentence to speak verbatim; do
    not say the PlayStation is on unless it is the returned message.
  fields:
    language:
      name: Language
      description: "Language of the sentence to return: en, th or zh."
      selector:
        select:
          options:
            - en
            - th
            - zh
      default: en
  sequence:
    - action: switch.turn_on
      target:
        entity_id: switch.living_room_ps5_pro
      continue_on_error: true
    - action: media_player.turn_on
      target:
        entity_id: media_player.lg_webos_tv_oled77c1ptb
      continue_on_error: true
    - action: media_player.turn_on
      target:
        entity_id: media_player.living_room
      continue_on_error: true
    - repeat:
        until:
          - condition: or
            conditions:
              - condition: and
                conditions:
                  - condition: state
                    entity_id: media_player.living_room
                    attribute: source
                    state: PlayStation 5
                  - condition: state
                    entity_id: media_player.lg_webos_tv_oled77c1ptb
                    state: "on"
              - "{{ repeat.index >= 25 }}"
        sequence:
          - if:
              - condition: not
                conditions:
                  - condition: state
                    entity_id: media_player.lg_webos_tv_oled77c1ptb
                    state: "on"
            then:
              - action: media_player.turn_on
                target:
                  entity_id: media_player.lg_webos_tv_oled77c1ptb
                continue_on_error: true
          - action: media_player.select_source
            data:
              source: PlayStation 5
            target:
              entity_id: media_player.living_room
            continue_on_error: true
          - if:
              - condition: state
                entity_id: media_player.lg_webos_tv_oled77c1ptb
                state: "on"
            then:
              - action: webostv.command
                data:
                  command: system.launcher/launch
                  payload:
                    id: com.webos.app.hdmi2
                target:
                  entity_id: media_player.lg_webos_tv_oled77c1ptb
                continue_on_error: true
          - delay:
              seconds: 2
    - if:
        - condition: state
          entity_id: media_player.lg_webos_tv_oled77c1ptb
          state: "on"
      then:
        - action: webostv.command
          data:
            command: system.launcher/launch
            payload:
              id: com.webos.app.hdmi2
          target:
            entity_id: media_player.lg_webos_tv_oled77c1ptb
          continue_on_error: true
    - variables:
        avr_ok: "{{ is_state_attr('media_player.living_room', 'source', 'PlayStation 5') }}"
        ps5_on: "{{ is_state('switch.living_room_ps5_pro', 'on') }}"
        tv_on: "{{ is_state('media_player.lg_webos_tv_oled77c1ptb', 'on') }}"
        result:
          message: >-
            {% set lang = language | default('en') %}
            {% if avr_ok and ps5_on and tv_on %}{{ {'en': 'The PlayStation is on and the TV is set to it.',
              'th': 'เปิดเพลย์สเตชั่นแล้ว และตั้งทีวีไปที่เพลย์สเตชั่นเรียบร้อยครับ',
              'zh': 'PlayStation 已开机,电视已切换到它。'}[lang] }}
            {% elif ps5_on and avr_ok %}{{ {'en': 'The PlayStation and receiver are on, but the TV did not wake up. Press the TV power button.',
              'th': 'เพลย์สเตชั่นและรีซีฟเวอร์เปิดแล้ว แต่ทีวียังไม่ติด กรุณากดปุ่มเปิดทีวีครับ',
              'zh': 'PlayStation 和功放已开机,但电视没有唤醒。请按电视电源键。'}[lang] }}
            {% elif ps5_on %}{{ {'en': 'The PlayStation is awake, but the receiver did not switch to the PlayStation input. Try again or use the remote.',
              'th': 'เพลย์สเตชั่นเปิดแล้ว แต่รีซีฟเวอร์ยังไม่สลับไปที่ช่องเพลย์สเตชั่น ลองสั่งอีกครั้งหรือใช้รีโมทครับ',
              'zh': 'PlayStation 已唤醒,但功放没有切换到 PlayStation 输入。请再试一次或使用遥控器。'}[lang] }}
            {% else %}{{ {'en': 'The PlayStation did not wake up. Check it is plugged in and on the network.',
              'th': 'เพลย์สเตชั่นไม่ตื่นขึ้นมา กรุณาตรวจสอบว่าเสียบปลั๊กและเชื่อมต่อเครือข่ายอยู่ครับ',
              'zh': 'PlayStation 没有唤醒。请检查是否已插电并连接网络。'}[lang] }}
            {% endif %}
    - stop: Done
      response_variable: result

ฝั่งรีซีฟเวอร์ใช้ media_player.select_source — บนรีซีฟเวอร์ภาพและเสียงแบบเครือข่าย นี่คือคำสั่งที่ถูกต้อง เพราะรีซีฟเวอร์รายงานและสลับอินพุตตามชื่ออย่างซื่อตรง มีเพียงการเลือก HDMI ของทีวี LG ที่ต้องใช้เส้นทางเปิดแอป สังเกตโครงสร้างของตอนจบ: สคริปต์อ่านสถานะทั้งสามหลังลูป แล้วสร้างคำตอบจากสถานะเหล่านั้น โดยมีแขนงสำหรับทุกผลลัพธ์ที่ซื่อตรง ผู้ช่วยเสียงที่ได้สคริปต์นี้ไปจะพูดความจริงได้ — รวมถึง “กรุณากดปุ่มเปิดทีวี” ในเย็นที่หายากซึ่งจอเพิกเฉยต่อแพ็กเก็ตปลุกทุกอัน

ต่อเข้ากับผู้ช่วยเสียง

เปิดให้ผู้ช่วยเห็นสคริปต์ ไม่ใช่ตัวอุปกรณ์ description ยาว ๆ ในตัวอย่างกำลังทำงานจริง: มันบอกผู้ช่วยแบบโมเดลภาษาว่าควรเรียกสคริปต์เมื่อไร ครอบคลุมรูปประโยคแบบไหน และ — สำคัญไม่แพ้กัน — อะไรที่ห้ามทำ (“never use the bare console switch”) ฟิลด์ language คู่กับ response_variable ให้ประโยคสำเร็จรูปแก่ผู้ช่วยไว้พูด มันจึงด้นความสำเร็จที่ฮาร์ดแวร์ไม่เคยทำได้ขึ้นมาเองไม่ได้ หนึ่งสคริปต์ต่อหนึ่งปลายทาง (select_ps5, select_shield, select_appletv…) ทำให้คำอธิบายแต่ละอันสั้น และคำตัดสินแต่ละอันซื่อตรง

ระวังเรื่องเหล่านี้