Một khi đã sử dụng Hass – Home Assistant, hẳn bạn sẽ phải sử dụng đến automation – tự động hoá, một trong các tính năng mạnh mẽ nhất của Hass so với các nền tảng Nhà Thông Minh khác. Thậm chí hiện tại bạn đã có đến hàng trăm automation giải quyết các kịch bản khác nhau trong sinh hoạt hàng ngày (riêng người viết có đến hơn 100 automation sử dụng trong gia đình dù đã rất hạn chế và đã thấy rất nhiều hệ thống Home Assistant có đến hơn 300 automation).
Để xem số lượng automation hiện tại bạn có thể vào Developer Tools > Template, xoá hết nội dung có sẵn và gõ vào dòng sau: {{ states.automation | count }}
Tuy nhiên, có một vấn đề cơ bản với automation: chúng chỉ hoạt động theo kịch bản đặt trước, dù có vẻ thông minh với rất nhiều thông tin đầu vào nhưng vẫn bị hạn chế bởi tính máy móc và không có khả năng phản ứng. Sự xung đột tranh giành quyền điều khiển thiết bị giữa máy móc (ở đây là Home Assistant) và người dùng là một trong các hệ quả của hạn chế trên (mà chúng tôi hi vọng sẽ khắc phục được phần lớn với thế hệ Nhà Thông Minh cấp độ III).
Hiện tại, giải pháp vẫn là tạo các automation “thông minh” hơn, tốt hơn ở các thiết bị hay khu vực tiềm tàng xảy ra khả năng tranh chấp cao.
Trong bài viết này, ta sẽ cố gắng giải quyết một bài toán đơn giản, thực tế xảy ra với người viết từ nhiều năm trước, như dưới đây.
Vấn đề
Mình có một đèn bàn trên bàn làm việc và đèn này có thể được điều khiển qua Home Assistant hoặc công tắc trên đèn, tuy nhiên công tắc này không tiện lắm do nó nằm ở phía bên kia bàn. Mình cũng hay rời khỏi bàn để đi loanh quanh, có lúc đi rất lâu, do vậy mình muốn tự động hoá việc điều khiển đèn dựa trên việc mình có ngồi tại bàn làm việc hay không.
Automation này rất căn bản trong Hass, logic của nó như sau: khi cảm biến Desk Occupied ở trạng thái ‘on’, Hass sẽ ra lệnh bật đèn và ngược lại. Trong thực tế thì mình có thêm vài điều kiện khác như chỉ tắt đèn sau 5 phút từ lúc cảm biến ‘off’ để phù hợp hơn với sinh hoạt thông thường của mình. Automation này trong Hass, ở dạng YAML như sau:
- id: '158691749761643' alias: Reading Room Desk Lamp and Occupancy description: Switch Desk Lamp based on Occupancy sensor trigger: - entity_id: binary_sensor.reading_room_desk_occupancy from: 'on' platform: state to: 'off' - entity_id: binary_sensor.reading_room_desk_occupancy for: 00:05:00 from: 'off' platform: state to: 'on' condition: [] action: - entity_id: switch.reading_room_desk_lamp service_template: > {% if is_state(''binary_sensor.reading_room_desk_occupancy'',''on'') %} switch.turn_on {% else %} switch.turn_off {% endif %}
Automation này hoạt động rất tốt, nếu mình cứ mặc kệ cho nó điều khiển tự động. Vấn đề chỉ phát sinh khi mình, đôi lúc muốn bật đèn này dù không ngồi tại bàn hoặc tắt đèn này dù vẫn ngồi tại bàn (có một số thời điểm trong ngày ánh sáng trong phòng rất ổn và đẹp). Lúc này sẽ phát sinh xung đột giữa mong muốn của mình và lập trình tự động của Home Assistant.
- Nếu mình tự bật đèn (qua Home Assistant hay công tắc) rồi ngồi vào ghế sau đó rời khỏi khiến cảm biến thay đổi trạng thái thì sau đó đèn vẫn bị tắt tự động.
- Trường hợp khác, khi mình ngồi vào bàn và tắt đèn nhưng rời khỏi bàn rồi quay lại thì đèn vẫn tự động bật lên.
Đôi lúc vấn đề này chỉ là phiền hà nhỏ và có thể chịu đựng được, nhưng trong một số trường hợp, nó có thể gây khó chịu rất lớn.
Giải pháp cho vấn đề trên
Giải pháp bình thường
Giải pháp thứ nhất là khi nào cần điều khiển thủ công thì ta sẽ tắt automation tương ứng đi. Rất thẳng thắn và đơn giản, nếu không muốn tự động hoá, ta tắt nó đi là xong.
Nhược điểm của cách này là phải động tay động chân, 2 lần khi tắt và mở lại automation; và có vẻ gì đó làm cho Nhà Thông Minh (và Home Assistant) trông “không được thông minh” cho lắm.
Giải pháp tự động
Giải pháp thứ hai, làm cho automation trên “thông minh” hơn. Để được vậy, mình sẽ làm mấy việc sau với automation trên, mà không cần phải bổ sung hay thay thế thiết bị (như cảm biến):
- Tách automation trên thành 2 phần (vâng, từ đầu mình luôn muốn gom các automation lại và giờ vẫn thế).
Sẽ có 2 automation riêng biệt chịu trách nhiệm tắt và mở đèn.
(nếu bạn không muốn tách, chuyển sang cách bổ sung nhưng vẫn nên đọc hết phần kế tiếp). - Thêm vào các điều kiện để Home Assistant nhận biết được đèn được tắt/mở lần cuối do automation hay không phải. Nếu do automation, tiếp tục điều khiển đèn; nếu không phải, không điều khiển đèn tự động nữa.
Sau khi tách ra làm 2 automation riêng biệt, mà ở đây mình tạm đặt tên là Automation 1 và Automation 2. Ta sẽ thêm vào các điều kiện kiểm tra và action bổ sung như sau:
- Kiểm tra xem đèn có ở trạng thái tắt hay không thì mới bật và ngược lại. Điều này rất quan trọng trong giải pháp này. Mình biết nhiều bạn vẫn kiểm tra cái này với mọi automation dù không thật sự cần thiết.
- Mỗi khi tắt/bật đèn ta sẽ đồng thời tắt luôn automation đang thực hiện và mở automation còn lại lên.
Ví dụ, Automation 1 kích hoạt khi cảm biến ‘on’, kiểm tra thấy đèn đang tắt sẽ ra lệnh:
– Bật đèn
– Bật Automation 2
– Tắt chính mình (Automation 1)
Như vậy:
- Cùng một thời điểm chỉ có 1 trong 2 automation hoạt động.
- Automation chỉ hoạt động khi trạng thái đèn ngược với trạng thái của cảm biến.
Làm cách nào mà điều này giải quyết được vấn đề xung đột ở trên:
Giả định cảm biến vừa ‘on’ và đèn đang tắt, Automation 1 sẽ bật đèn, tự tắt nó và bật Automation 2. Trong lúc này, bạn tắt đèn thủ công rồi rời khỏi ghế.
Cảm biến sẽ chuyển sang ‘off’. Automation 2 được kích hoạt, tuy nhiên do trạng thái của đèn không đúng (lẽ ra phải đang bật), Automation 2 bỏ qua, không có gì xảy ra.
Bạn quay lại ghế, cảm biến chuyển sang ‘on’ nhưng lúc này Automation 1 đang tắt (bởi chính nó) nên không thể bật đèn. Đèn vẫn tắt như ý bạn.
Vậy làm sao để automation hoạt động lại? Rất đơn giản, bạn tự mình bật/tắt đèn lại lần nữa, lúc này trạng thái đèn sẽ khớp với Automation đang được mở.
Bên dưới là cấu hình mẫu của 2 automation này, khi sử dụng bạn thay đổi tên automation và các entity_id cho phù hợp. Cần nhớ rằng, thay đổi tên automation (alias) cũng làm thay đổi entity_id của automation này và do vậy phải thay đổi cả trong mục action cho đúng.
- id: '1586921612588' alias: 1 Bat Den description: Bật đèn bàn khi cảm biến ON initial_state: true trigger: - entity_id: binary_sensor.reading_room_desk_occupancy from: 'off' platform: state to: 'on' condition: - condition: state entity_id: switch.reading_room_desk_lamp state: 'off' action: - data: {} entity_id: switch.reading_room_desk_lamp service: switch.turn_on - data: {} entity_id: automation.2_tat_den service: automation.turn_on - data: {} entity_id: automation.1_bat_den service: automation.turn_off - id: '1586921612589' alias: 2 Tat Den description: Tắt đèn bàn khi cảm biến OFF initial_state: true trigger: - entity_id: binary_sensor.reading_room_desk_occupancy from: 'on' platform: state to: 'off' for: 00:05:00 condition: - condition: state entity_id: switch.reading_room_desk_lamp state: 'on' action: - data: {} entity_id: switch.reading_room_desk_lamp service: switch.turn_off - data: {} entity_id: automation.1_bat_den service: automation.turn_on - data: {} entity_id: automation.2_tat_den service: automation.turn_off
Hiệu ứng của 2 automation này được minh hoạ bởi video dưới đây:
Chú thích: Bạn có thể thấy tuỳ chọn initial_state: true
trong Automation 1 Bật Đèn. Tuỳ chọn này để phòng trường hợp automation bị tắt khi Home Assistant khởi động lại. Trong hầu hết trường hợp, các switch sẽ ở trạng thái ‘off’ khi Home Assistant khởi động, nếu switch của bạn không vậy, hãy chuyển tuỳ chọn initial_state: true
sang Automation 2 Tắt Đèn.
Giải pháp tự động số 2
Dành cho các bạn không muốn tách ra làm 2 automation. Thay vì tách automation, ta sẽ thêm vào Home Assistant một input_boolean để so sánh trạng thái của input_boolean này và đèn khi automation kích hoạt, tạm có thể coi là sử dụng một biến toàn cục – global variables để lưu giữ trạng thái.
Cấu hình mẫu như bên dưới, phía trên là cấu hình của input_boolean.
Trong cấu hình có sử dụng template, bạn có thể tìm hiểu thêm các Cấu trúc và Filter thường dùng trong templating ở bài viết này.
input_boolean: reading_room_desk_lamp: name: "Reading Room Desk Lamp"
- id: '158691749761643' alias: Reading Room Desk Lamp and Occupancy description: Switch Desk Lamp based on Occupancy sensor trigger: - entity_id: binary_sensor.reading_room_desk_occupancy from: 'on' platform: state to: 'off' for: 00:05:00 - entity_id: binary_sensor.reading_room_desk_occupancy from: 'off' platform: state to: 'on' condition: - condition: template value_template: '{{ states(''switch.reading_room_desk_lamp'') == states(''input_boolean.reading_room_desk_lamp'') }}' action: - entity_id: switch.reading_room_desk_lamp service_template: '{% if is_state(''binary_sensor.reading_room_desk_occupancy'',''on'') %} switch.turn_on {% else %} switch.turn_off {% endif %}' - entity_id: input_boolean.reading_room_desk_lamp service_template: '{% if is_state(''binary_sensor.reading_room_desk_occupancy'',''on'') %} input_boolean.turn_on {% else %} input_boolean.turn_off {% endif %}'
Nguyên tắc và hoạt động thực tế của 2 cách trên là tương tự, tuy có một vài khác biệt nhỏ nhưng không đáng kể.
Hạn chế của các giải pháp tự động trên
Giải pháp bên trên tuy giải quyết được vấn đề nhưng vẫn có hạn chế nhất định:
- Bạn phải tác động vào đèn lần nữa để tự động hoá hoạt động trở lại.
- Tuỳ cách cấu hình Home Assistant và thiết bị, đôi khi trạng thái của các automation, đèn hay input_boolean trên kia sẽ không khớp khi Home Assistant bị khởi động lại hay reload automation và do vậy, tự động hoá sẽ hoạt động lại hoặc bị vô hiệu không theo ý của bạn.
- Phải áp dụng cho từng thiết bị hay tự động hoá. Sẽ bất tiện nếu bạn có quá nhiều trường hợp cần áp dụng cách này.
Để giải quyết 2 hạn chế đầu tiên, bạn có thể:
- Tạo automation để tự động khớp trạng thái của automation và đèn vào một thời điểm nào đó hoặc sau một thời gian nào đó. Ví dụ như tự động bật lại đèn sau khi Automation 2 Tắt Đèn được bật lên (nhưng không kích hoạt do đèn bị tắt thủ công) 3-5 giờ chẳng hạn.
- Cẩn thận với các tuỳ chọn initial_state của 2 automation riêng biệt và intial của input_boolean.
- Cuối cùng, mặc kệ. Automation có thể sai ở lần đầu tiên nhưng sau khi bạn bật hoặc tắt đèn thủ công, mặc nhiên nó sẽ hoạt động đúng trở lại.
Về Bài viết
Bài viết chưa đầy đủ hoặc bạn còn có ý kiến khác? Bạn có thắc mắc và cần thêm thông tin. Vui lòng đăng ý kiến vào mục bình luận để tác giả và Team có thêm thông tin cải thiện chất lượng bài viết. Chúng tôi sẽ giải đáp các thắc mắc ngay trong mục bình luận để giúp được nhiều đọc giả với cùng vấn đề hơn hoặc chúng tôi sẽ trả lời trong một bài viết riêng. Trân trọng cảm ơn bạn!
Cảm ơn bạn đã xem bài viết này!
konnectED Team.