Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant
Mỗi lần nhận được tiền điện, nước, tôi lại ngạc nhiên - gia đình tôi có thực sự tiêu tốn nhiều như vậy không? Vâng, vâng, phòng tắm có hệ thống sưởi sàn và nồi hơi, nhưng không phải lúc nào họ cũng đốt lửa. Chúng ta dường như cũng đang tiết kiệm nước (mặc dù chúng ta cũng thích té nước trong phòng tắm). Cách đây vài năm tôi đã đồng hồ nước kết nối и điện đến một ngôi nhà thông minh, nhưng đó là lúc mọi thứ trở nên bế tắc. Bây giờ chúng ta mới bắt đầu phân tích mức tiêu thụ, đó chính là nội dung thực sự của bài viết này.

Gần đây tôi đã chuyển sang Home Assistant làm hệ thống nhà thông minh của mình. Một trong những lý do chính là cơ hội tổ chức thu thập một lượng lớn dữ liệu với khả năng xây dựng nhiều loại biểu đồ khác nhau một cách thuận tiện.

Thông tin được mô tả trong bài viết này không phải là mới, tất cả những thứ dưới các loại nước sốt khác nhau đều đã được mô tả trên Internet. Nhưng mỗi bài viết thường chỉ mô tả một cách tiếp cận hoặc một khía cạnh. Tôi đã phải so sánh tất cả các cách tiếp cận này và tự mình chọn ra cách phù hợp nhất. Bài viết vẫn chưa cung cấp thông tin toàn diện về việc thu thập dữ liệu mà chỉ là một dạng tóm tắt về cách tôi đã thực hiện. Vì vậy, những lời phê bình mang tính xây dựng và đề xuất cải tiến đều được hoan nghênh.

Báo cáo sự cố

Vì vậy, mục tiêu của bài tập hôm nay là có được biểu đồ đẹp về mức tiêu thụ điện, nước:

  • Hàng giờ trong 2 ngày
  • Hàng ngày trong 2 tuần
  • (tùy chọn) hàng tuần và hàng tháng

Có một số khó khăn với điều này:

  • Các thành phần biểu đồ tiêu chuẩn thường khá kém. Tốt nhất, bạn có thể xây dựng biểu đồ đường theo từng điểm.

    Nếu chịu khó tìm kiếm, bạn có thể tìm thấy các thành phần của bên thứ ba giúp mở rộng khả năng của biểu đồ tiêu chuẩn. Đối với một trợ lý tại nhà, về nguyên tắc, đây là một thành phần tốt và đẹp thẻ đồ thị nhỏ, nhưng nó cũng có phần hạn chế:

    • Rất khó để thiết lập các tham số của biểu đồ thanh theo các khoảng lớn (chiều rộng của thanh được đặt theo phân số của một giờ, nghĩa là các khoảng dài hơn một giờ sẽ được đặt ở số phân số)
    • Bạn không thể thêm các thực thể khác nhau vào một biểu đồ (ví dụ: nhiệt độ và độ ẩm hoặc kết hợp biểu đồ thanh với một đường)
  • Theo mặc định, trợ lý gia đình không chỉ sử dụng cơ sở dữ liệu SQLite nguyên thủy nhất (và tôi, một người siêng năng, không thể cài đặt MySQL hoặc Postgres), mà dữ liệu cũng không được lưu trữ theo cách tối ưu nhất. Vì vậy, ví dụ, mỗi khi bạn thay đổi ngay cả tham số kỹ thuật số nhỏ nhất của một tham số, một json khổng lồ có kích thước khoảng một kilobyte sẽ được ghi vào cơ sở dữ liệu
    {"entity_id": "sensor.water_cold_hourly", "old_state": {"entity_id": "sensor.water_cold_hourly", "state": "3", "attributes": {"source": "sensor.water_meter_cold", "status": "collecting", "last_period": "29", "last_reset": "2020-02-23T21:00:00.022246+02:00", "meter_period": "hourly", "unit_of_measurement": "l", "friendly_name": "water_cold_hourly", "icon": "mdi:counter"}, "last_changed": "2020-02-23T19:05:06.897604+00:00", "last_updated": "2020-02-23T19:05:06.897604+00:00", "context": {"id": "aafc8ca305ba4e49ad4c97f0eddd8893", "parent_id": null, "user_id": null}}, "new_state": {"entity_id": "sensor.water_cold_hourly", "state": "4", "attributes": {"source": "sensor.water_meter_cold", "status": "collecting", "last_period": "29", "last_reset": "2020-02-23T21:00:00.022246+02:00", "meter_period": "hourly", "unit_of_measurement": "l", "friendly_name": "water_cold_hourly", "icon": "mdi:counter"}, "last_changed": "2020-02-23T19:11:11.251545+00:00", "last_updated": "2020-02-23T19:11:11.251545+00:00", "context": {"id": "0de64b8af6f14bb9a419dcf3b200ef56", "parent_id": null, "user_id": null}}}

    Tôi có khá nhiều cảm biến (cảm biến nhiệt độ trong mỗi phòng, đồng hồ đo điện nước), và một số còn tạo ra khá nhiều dữ liệu. Ví dụ, chỉ riêng đồng hồ điện SDM220 tạo ra khoảng chục giá trị cứ sau 10-15 giây và tôi muốn lắp khoảng 8 đồng hồ như vậy, ngoài ra còn có cả đống thông số được tính toán dựa trên các cảm biến khác. Cái đó. tất cả những giá trị này có thể dễ dàng tăng cơ sở dữ liệu thêm 100-200 MB mỗi ngày. Trong một tuần, hệ thống sẽ hầu như không di chuyển và trong một tháng, ổ đĩa flash sẽ chết (trong trường hợp cài đặt trợ lý gia đình thông thường trên Raspberry PI) và việc lưu trữ dữ liệu trong cả năm là điều không thể.

  • Nếu bạn may mắn, đồng hồ của bạn có thể tự tính mức tiêu thụ. Bạn có thể quay sang đồng hồ bất cứ lúc nào và hỏi giá trị tiêu thụ tích lũy là mấy giờ. Theo quy định, tất cả các đồng hồ đo điện có giao diện kỹ thuật số (RS232/RS485/Modbus/Zigbee) đều mang lại cơ hội này.

    Sẽ tệ hơn nếu thiết bị chỉ có thể đo một số thông số tức thời (ví dụ: công suất hoặc dòng điện tức thời) hoặc chỉ tạo ra các xung sau mỗi X watt-giờ hoặc lít. Sau đó, bạn cần suy nghĩ về cách thức và nội dung để tích hợp nó cũng như nơi tích lũy giá trị. Có nguy cơ bỏ lỡ báo cáo tiếp theo vì bất kỳ lý do gì và tính chính xác của toàn bộ hệ thống đặt ra câu hỏi. Tất nhiên, bạn có thể giao phó tất cả những điều này cho một hệ thống nhà thông minh như trợ lý gia đình, nhưng không ai hủy quan điểm về số lượng bản ghi trong cơ sở dữ liệu và sẽ không thể thăm dò các cảm biến nhiều hơn một lần một giây (a hạn chế của kiến ​​trúc trợ lý gia đình).

Phương pháp 1

Đầu tiên, hãy xem trợ lý tại nhà cung cấp những gì. Đo lường mức tiêu thụ trong một khoảng thời gian là một chức năng được nhiều người ưa chuộng. Tất nhiên, nó đã được triển khai từ lâu dưới dạng một thành phần chuyên dụng - Utility_meter.

Bản chất của thành phần này là nó tạo ra một biến current_accumulated_value bên trong và đặt lại nó sau một khoảng thời gian xác định (giờ/tuần/tháng). Bản thân thành phần này giám sát biến đầu vào (giá trị của một số cảm biến), tự đăng ký các thay đổi về giá trị - bạn chỉ nhận được kết quả cuối cùng. Điều này được mô tả chỉ bằng một vài dòng trong tệp cấu hình

utility_meter:
  water_cold_hour_um:
    source: sensor.water_meter_cold
    cycle: hourly
  water_cold_day_um:
    source: sensor.water_meter_cold
    cycle: daily

Ở đây cảm biến.water_meter_cold là giá trị đồng hồ đo hiện tại tính bằng lít mà tôi nhận được trực tiếp từ miếng sắt bởi mqtt. Thiết kế tạo ra 2 cảm biến mới Water_cold_hour_um và Water_cold_day_um, giúp tích lũy số liệu đọc hàng giờ và hàng ngày, đặt lại chúng về XNUMX sau khi hết thời gian. Đây là biểu đồ pin hàng giờ trong nửa ngày.

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Mã cho biểu đồ hàng giờ và hàng ngày cho lovelace-UI trông như thế này:

      - type: history-graph
        title: 'Hourly water consumption using vars'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Daily water consumption using vars'
        hours_to_show: 360
        entities:
          - sensor.water_day

Trên thực tế, vấn đề với cách tiếp cận này nằm ở thuật toán này. Như tôi đã đề cập, đối với mỗi giá trị đầu vào (số đo hiện tại của đồng hồ đo cho mỗi lít tiếp theo), 1kb bản ghi được tạo trong cơ sở dữ liệu. Mỗi đồng hồ tiện ích cũng tạo ra một giá trị mới, giá trị này cũng được thêm vào cơ sở. Nếu tôi muốn thu thập số liệu đọc hàng giờ/hàng ngày/hàng tuần/hàng tháng và đối với một số ống nước tăng và thêm một bộ đồng hồ đo điện, thì đó sẽ là rất nhiều dữ liệu. Chà, chính xác hơn là không có nhiều dữ liệu, nhưng vì trợ lý gia đình ghi một loạt thông tin không cần thiết vào cơ sở dữ liệu, nên kích thước của cơ sở dữ liệu sẽ tăng vọt. Tôi thậm chí còn ngại ước tính kích thước của nền giá cho biểu đồ hàng tuần và hàng tháng.

Ngoài ra, bản thân đồng hồ tiện ích không giải quyết được vấn đề. Biểu đồ của các giá trị do đồng hồ tiện ích tạo ra là một hàm tăng đơn điệu được đặt lại về 0 mỗi giờ. Chúng ta cần một biểu đồ tiêu thụ mà người dùng có thể hiểu được, cho biết số lít đã tiêu thụ trong kỳ. Thành phần biểu đồ lịch sử tiêu chuẩn không thể thực hiện được điều này, nhưng thành phần bên ngoài thẻ biểu đồ mini có thể giúp chúng ta.

Đây là mã thẻ cho lovelace-UI:

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_hour_um
        group_by: hour
        hours_to_show: 48
        name: "Hourly water consumption aggregated by utility meter"
        points_per_hour: 1
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Ngoài các cài đặt tiêu chuẩn như tên cảm biến, loại biểu đồ, màu sắc (tôi không thích màu cam tiêu chuẩn), điều quan trọng cần lưu ý là 3 cài đặt:

  • group_by:hour - biểu đồ sẽ được tạo với các thanh được căn chỉnh theo đầu giờ
  • point_per_hour: 1 - một thanh cho mỗi giờ
  • Và quan trọng nhất, tổng hợp: max - lấy giá trị tối đa trong mỗi giờ. Chính tham số này biến đồ thị răng cưa thành thanh

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Đừng chú ý đến hàng cột bên trái - đây là hành vi tiêu chuẩn của thành phần nếu không có dữ liệu. Nhưng không có dữ liệu - tôi chỉ bật tính năng thu thập dữ liệu đồng hồ tiện ích vài giờ trước chỉ vì mục đích của bài viết này (tôi sẽ mô tả cách tiếp cận hiện tại của mình bên dưới).

Trong hình ảnh này, tôi muốn chứng tỏ rằng đôi khi việc hiển thị dữ liệu vẫn hoạt động và các thanh thực sự phản ánh các giá trị chính xác. Nhưng đó không phải là tất cả. Vì lý do nào đó, cột được chọn trong khoảng thời gian từ 11 đến 12 giờ sáng hiển thị 19 lít, mặc dù trên biểu đồ răng cưa cao hơn một chút trong cùng khoảng thời gian từ cùng một cảm biến, chúng ta thấy mức tiêu thụ là 62 lít. Hoặc là có lỗi hoặc tay bị cong. Nhưng tôi vẫn không hiểu tại sao dữ liệu bên phải lại bị hỏng - mức tiêu thụ ở đó là bình thường, điều này cũng có thể nhìn thấy được từ biểu đồ răng cưa.

Nói chung, tôi không thể đạt được tính hợp lý của phương pháp này - biểu đồ hầu như luôn thể hiện một số kiểu dị giáo.

Mã tương tự cho cảm biến ban ngày.

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_day_um
        group_by: interval
        hours_to_show: 360
        name: "Daily water consumption aggregated by utility meter"
        points_per_hour: 0.0416666666
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Xin lưu ý rằng tham số group_by được đặt thành khoảng thời gian và tham số point_per_hour quy định mọi thứ. Và trong đó có một vấn đề khác với thành phần này - point_per_hour hoạt động tốt trên các biểu đồ có thời lượng một giờ hoặc ít hơn, nhưng lại hoạt động kém trong các khoảng thời gian lớn hơn. Vì vậy, để có được một cột trong một ngày, tôi phải nhập giá trị 1/24=0.04166666. Tôi thậm chí không nói về biểu đồ hàng tuần và hàng tháng.

Phương pháp 2

Trong khi vẫn đang tìm hiểu về trợ lý tại nhà, tôi đã xem được video này:


Một người bạn thu thập dữ liệu tiêu thụ từ một số loại ổ cắm Xiaomi. Nhiệm vụ của anh ta đơn giản hơn một chút - chỉ cần hiển thị giá trị tiêu thụ cho ngày hôm nay, hôm qua và trong tháng. Không cần lịch trình.

Hãy gác lại các cuộc thảo luận về việc tích hợp thủ công các giá trị công suất tức thời - tôi đã viết ở trên về “độ chính xác” của phương pháp này. Không rõ tại sao anh ta không sử dụng số tiền tiêu thụ tích lũy đã được thu thập bởi cùng một cửa hàng. Theo tôi, việc tích hợp bên trong phần cứng sẽ hoạt động tốt hơn.

Từ video, chúng ta sẽ lấy ý tưởng tính mức tiêu thụ theo cách thủ công trong một khoảng thời gian. Anh chàng chỉ đếm các giá trị của ngày hôm nay và ngày hôm qua, nhưng chúng ta sẽ tiến xa hơn và cố gắng vẽ một biểu đồ. Bản chất của phương pháp được đề xuất trong trường hợp của tôi là như sau.

Hãy tạo một biến value_at_the_beginning_of_hour, trong đó chúng ta sẽ ghi lại chỉ số đồng hồ đo hiện tại
Sử dụng bộ đếm thời gian, vào cuối giờ (hoặc vào đầu giờ tiếp theo), chúng tôi tính toán sự khác biệt giữa số đọc hiện tại và số được lưu vào đầu giờ. Sự khác biệt này sẽ là mức tiêu thụ cho giờ hiện tại - chúng tôi sẽ lưu giá trị vào cảm biến và trong tương lai chúng tôi sẽ xây dựng biểu đồ dựa trên giá trị này.
Bạn cũng cần “đặt lại” biến value_at_beginning_of_hour bằng cách viết giá trị bộ đếm hiện tại vào đó.

Tất cả điều này có thể được thực hiện thông qua chính trợ lý gia đình.

Bạn sẽ phải viết mã nhiều hơn một chút so với cách tiếp cận trước. Đầu tiên, hãy tạo những “biến” tương tự. Ngay từ đầu, chúng tôi không có thực thể “biến”, nhưng chúng tôi có thể sử dụng các dịch vụ của nhà môi giới mqtt. Chúng tôi sẽ gửi các giá trị đến đó bằng cờ keep=true - điều này sẽ lưu giá trị bên trong trình môi giới và nó có thể được lấy ra khỏi đó bất kỳ lúc nào, ngay cả khi trợ lý chính được khởi động lại. Tôi đã thực hiện các bộ đếm hàng giờ và hàng ngày cùng một lúc.

- platform: mqtt
  state_topic: "test/water/hour"
  name: water_hour
  unit_of_measurement: l

- platform: mqtt
  state_topic: "test/water/hour_begin"
  name: water_hour_begin
  unit_of_measurement: l

- platform: mqtt
  state_topic: "test/water/day"
  name: water_day
  unit_of_measurement: l

- platform: mqtt
  state_topic: "test/water/day_begin"
  name: water_day_begin
  unit_of_measurement: l

Tất cả điều kỳ diệu xảy ra trong quá trình tự động hóa, chạy tương ứng hàng giờ và hàng đêm.

- id: water_new_hour
  alias: water_new_hour
  initial_state: true
  trigger:
    - platform: time_pattern
      minutes: 0
  action:
    - service: mqtt.publish
      data:
        topic: "test/water/hour"
        payload_template: >
          {{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_hour_begin.state|int) }}
        retain: true
    - service: mqtt.publish
      data:
        topic: "test/water/hour_begin"
        payload_template: >
          {{ states.sensor.water_meter_cold.state }}
        retain: true

- id: water_new_day
  alias: water_new_day
  initial_state: true
  trigger:
    - platform: time
      at: "00:00:00"
  action:
    - service: mqtt.publish
      data:
        topic: "test/water/day"
        payload_template: >
          {{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_day_begin.state|int) }}
        retain: true
    - service: mqtt.publish
      data:
        topic: "test/water/day_begin"
        payload_template: >
          {{ states.sensor.water_meter_cold.state }}
        retain: true

Cả hai quá trình tự động hóa đều thực hiện 2 hành động:

  • Tính giá trị cho một khoảng bằng chênh lệch giữa giá trị đầu và cuối
  • Cập nhật giá trị cơ sở cho khoảng thời gian tiếp theo

Việc xây dựng đồ thị trong trường hợp này được giải quyết bằng đồ thị lịch sử thông thường:

      - type: history-graph
        title: 'Hourly water consumption using vars'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Daily water consumption using vars'
        hours_to_show: 360
        entities:
          - sensor.water_day

Dường như thế này:

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Về nguyên tắc, đây đã là điều cần thiết. Ưu điểm của phương pháp này là dữ liệu được tạo một lần trong mỗi khoảng thời gian. Những thứ kia. chỉ có 24 bản ghi mỗi ngày cho biểu đồ hàng giờ.

Thật không may, điều này vẫn không giải quyết được vấn đề chung về cơ sở đang phát triển. Nếu tôi muốn có biểu đồ tiêu thụ hàng tháng, tôi sẽ phải lưu trữ dữ liệu trong ít nhất một năm. Và vì trợ lý gia đình chỉ cung cấp một cài đặt thời lượng lưu trữ cho toàn bộ cơ sở dữ liệu, điều này có nghĩa là TẤT CẢ dữ liệu trong hệ thống sẽ phải được lưu trữ trong cả năm. Ví dụ, trong một năm tôi tiêu thụ 200 mét khối nước, điều đó có nghĩa là có 200000 mục trong cơ sở dữ liệu. Và nếu bạn tính đến các cảm biến khác, thì con số nhìn chung sẽ trở nên không đứng đắn.

Phương pháp 3

May mắn thay, những người thông minh đã giải quyết được vấn đề này bằng cách viết cơ sở dữ liệu InfluxDB. Cơ sở dữ liệu này được tối ưu hóa đặc biệt để lưu trữ dữ liệu dựa trên thời gian và lý tưởng để lưu trữ các giá trị của các cảm biến khác nhau. Hệ thống cũng cung cấp ngôn ngữ truy vấn giống như SQL cho phép bạn trích xuất các giá trị từ cơ sở dữ liệu và sau đó tổng hợp chúng theo nhiều cách khác nhau. Cuối cùng, dữ liệu khác nhau có thể được lưu trữ trong những thời điểm khác nhau. Ví dụ: các chỉ số thay đổi thường xuyên như nhiệt độ hoặc độ ẩm có thể được lưu trữ chỉ trong vài tuần, trong khi các chỉ số tiêu thụ nước hàng ngày có thể được lưu trữ trong cả năm.

Bên cạnh InfluxDB, những người thông minh còn phát minh ra Grafana, một hệ thống vẽ đồ thị dựa trên dữ liệu từ InfluxDB. Grafana có thể vẽ các loại biểu đồ khác nhau, tùy chỉnh chúng một cách chi tiết và quan trọng nhất là những biểu đồ này có thể được “cắm” vào trợ lý gia đình lovelace-UI.

Lấy cảm hứng đây и đây. Các bài viết mô tả chi tiết quá trình cài đặt và kết nối InfluxDB và Grafana với trợ lý gia đình. Tôi sẽ tập trung vào việc giải quyết vấn đề cụ thể của mình.

Vì vậy, trước hết, hãy bắt đầu thêm giá trị bộ đếm vào InfluxDB. Một phần của cấu hình trợ lý gia đình (trong ví dụ này, tôi sẽ tận hưởng niềm vui không chỉ với nước lạnh mà còn cả nước nóng):

influxdb:
  host: localhost
  max_retries: 3
  default_measurement: state
  database: homeassistant
  include:
    entities:
      - sensor.water_meter_hot
      - sensor.water_meter_cold

Hãy vô hiệu hóa việc lưu cùng dữ liệu này vào cơ sở dữ liệu trợ lý gia đình nội bộ để không làm nó bị phồng lên nữa:

recorder:
  purge_keep_days: 10
  purge_interval: 1
  exclude:
    entities:
      - sensor.water_meter_hot
      - sensor.water_meter_cold

Bây giờ chúng ta hãy đi tới bảng điều khiển InfluxDB và định cấu hình cơ sở dữ liệu của chúng ta. Đặc biệt, bạn cần định cấu hình thời gian lưu trữ một số dữ liệu nhất định. Điều này được quy định bởi cái gọi là. chính sách lưu giữ - điều này tương tự như cơ sở dữ liệu trong cơ sở dữ liệu chính, với mỗi cơ sở dữ liệu nội bộ có cài đặt riêng. Theo mặc định, tất cả dữ liệu được lưu trữ trong chính sách lưu giữ được gọi là autogen; dữ liệu này sẽ được lưu trữ trong một tuần. Tôi muốn dữ liệu hàng giờ được lưu giữ trong một tháng, dữ liệu hàng tuần được lưu giữ trong một năm và dữ liệu hàng tháng không bao giờ bị xóa. Hãy tạo chính sách lưu giữ phù hợp

CREATE RETENTION POLICY "month" ON "homeassistant" DURATION 30d REPLICATION 1
CREATE RETENTION POLICY "year" ON "homeassistant" DURATION 52w REPLICATION 1
CREATE RETENTION POLICY "infinite" ON "homeassistant" DURATION INF REPLICATION 1

Trên thực tế, thủ thuật chính là tổng hợp dữ liệu bằng truy vấn liên tục. Đây là cơ chế tự động chạy truy vấn theo các khoảng thời gian được chỉ định, tổng hợp dữ liệu cho truy vấn này và thêm kết quả vào một giá trị mới. Hãy xem một ví dụ (tôi viết thành một cột cho dễ đọc, nhưng thực tế tôi phải nhập lệnh này vào một dòng)

CREATE CONTINUOUS QUERY cq_water_hourly ON homeassistant 
BEGIN 
  SELECT max(value) AS value 
  INTO homeassistant.month.water_meter_hour 
  FROM homeassistant.autogen.l 
  GROUP BY time(1h), entity_id fill(previous) 
END

Lệnh này:

  • Tạo một truy vấn liên tục có tên cq_water_cold_hourly trong cơ sở dữ liệu trợ lý gia đình
  • Yêu cầu sẽ được thực hiện mỗi giờ (thời gian (1h))
  • Yêu cầu sẽ loại bỏ tất cả dữ liệu từ phép đo' homeassistant.autogen.l (lít), bao gồm cả chỉ số nước lạnh và nước nóng
  • Dữ liệu tổng hợp sẽ được nhóm theo instance_id, sẽ cho chúng ta các giá trị riêng biệt cho nước lạnh và nước nóng
  • Vì bộ đếm lít là dãy tăng dần trong mỗi giờ nên cần lấy giá trị lớn nhất nên việc tổng hợp sẽ được thực hiện bởi hàm max(value)
  • Giá trị mới sẽ được ghi vào homeassistant.month.water_meter_hour, trong đó tháng là tên của chính sách lưu giữ có thời hạn lưu giữ là một tháng. Hơn nữa, dữ liệu về nước lạnh và nước nóng sẽ được phân tán thành các bản ghi riêng biệt với mã_id và giá trị thực thể tương ứng trong trường giá trị

Vào ban đêm hoặc khi không có ai ở nhà, không có lượng nước tiêu thụ và do đó không có mục mới nào trong homeassistant.autogen.l. Để tránh thiếu giá trị trong các truy vấn thông thường, bạn có thể sử dụng fill(previous). Điều này sẽ buộc InfluxDB sử dụng giá trị của giờ trước.

Thật không may, truy vấn liên tục có một điểm đặc biệt: thủ thuật điền (trước đó) không hoạt động và đơn giản là các bản ghi không được tạo. Hơn nữa, đây là một dạng vấn đề không thể giải quyết được mà đã được thảo luận trong nhiều năm nay. Chúng tôi sẽ giải quyết vấn đề này sau, nhưng hãy để điền (trước) vào truy vấn liên tục - nó không gây trở ngại.

Hãy kiểm tra xem điều gì đã xảy ra (tất nhiên, bạn cần đợi vài giờ):

> select * from homeassistant.month.water_meter_hour group by entity_id
...
name: water_meter_hour
tags: entity_id=water_meter_cold
time                 value
----                 -----
...
2020-03-08T01:00:00Z 370511
2020-03-08T02:00:00Z 370513
2020-03-08T05:00:00Z 370527
2020-03-08T06:00:00Z 370605
2020-03-08T07:00:00Z 370635
2020-03-08T08:00:00Z 370699
2020-03-08T09:00:00Z 370761
2020-03-08T10:00:00Z 370767
2020-03-08T11:00:00Z 370810
2020-03-08T12:00:00Z 370818
2020-03-08T13:00:00Z 370827
2020-03-08T14:00:00Z 370849
2020-03-08T15:00:00Z 370921

Lưu ý rằng các giá trị trong cơ sở dữ liệu được lưu trữ trong UTC, vì vậy danh sách này chênh lệch 3 giờ - các giá trị 7 giờ sáng trong đầu ra InfluxDB tương ứng với các giá trị 10 giờ sáng trong biểu đồ trên. Cũng lưu ý rằng từ 2 đến 5 giờ sáng đơn giản là không có bản ghi nào - đây là tính năng tương tự của truy vấn liên tục.

Như bạn có thể thấy, giá trị tổng hợp cũng là một chuỗi tăng dần đều, chỉ có các mục xuất hiện ít thường xuyên hơn - một lần mỗi giờ. Nhưng đây không phải là vấn đề - chúng ta có thể viết một truy vấn khác để lấy dữ liệu chính xác cho biểu đồ.

SELECT difference(max(value)) 
FROM homeassistant.month.water_meter_hour 
WHERE entity_id='water_meter_cold' and time >= now() -24h 
GROUP BY time(1h), entity_id 
fill(previous)

Tôi sẽ giải mã:

  • Từ cơ sở dữ liệu homeassistant.month.water_meter_hour, chúng tôi sẽ trích xuất dữ liệu cho instance_id='water_meter_cold' cho ngày cuối cùng (thời gian >= now() -24h).
  • Như tôi đã đề cập, một số mục có thể bị thiếu trong chuỗi homeassistant.month.water_meter_hour. Chúng tôi sẽ tạo lại dữ liệu này bằng cách chạy truy vấn với thời gian GROUP BY(1h). Lần này fill(previous) sẽ hoạt động như mong đợi, tạo ra dữ liệu bị thiếu (hàm sẽ lấy giá trị trước đó)
  • Điều quan trọng nhất trong yêu cầu này là hàm chênh lệch, hàm này sẽ tính toán sự khác biệt giữa các mốc giờ. Nó không tự hoạt động và yêu cầu chức năng tổng hợp. Đặt đây là max() được sử dụng trước đó.

Kết quả thực hiện trông như thế này

name: water_meter_hour
tags: entity_id=water_meter_cold
time                 difference
----                 ----------
...
2020-03-08T02:00:00Z 2
2020-03-08T03:00:00Z 0
2020-03-08T04:00:00Z 0
2020-03-08T05:00:00Z 14
2020-03-08T06:00:00Z 78
2020-03-08T07:00:00Z 30
2020-03-08T08:00:00Z 64
2020-03-08T09:00:00Z 62
2020-03-08T10:00:00Z 6
2020-03-08T11:00:00Z 43
2020-03-08T12:00:00Z 8
2020-03-08T13:00:00Z 9
2020-03-08T14:00:00Z 22
2020-03-08T15:00:00Z 72

Từ 2 đến 5 giờ sáng (UTC) không có lượng tiêu thụ nào. Tuy nhiên, truy vấn sẽ trả về cùng một giá trị tiêu thụ nhờ điền (trước đó) và hàm sai phân sẽ trừ giá trị này khỏi chính nó và đầu ra sẽ bằng 0, đây chính xác là những gì được yêu cầu.

Tất cả những gì còn lại là xây dựng một biểu đồ. Để thực hiện việc này, hãy mở Grafana, mở một số trang tổng quan hiện có (hoặc tạo trang mới) và tạo bảng điều khiển mới. Cài đặt biểu đồ sẽ như thế này.

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Tôi sẽ hiển thị dữ liệu nước lạnh và nước nóng trên cùng một biểu đồ. Yêu cầu hoàn toàn giống như tôi đã mô tả ở trên.

Các thông số hiển thị được thiết lập như sau. Đối với tôi, nó sẽ là một biểu đồ có các đường đi theo từng bậc (cầu thang). Tôi sẽ giải thích tham số Stack bên dưới. Có một vài tùy chọn hiển thị khác bên dưới, nhưng chúng không thú vị lắm.

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Để thêm biểu đồ kết quả vào trợ lý tại nhà, bạn cần:

  • thoát khỏi chế độ chỉnh sửa biểu đồ. Vì lý do nào đó, cài đặt chia sẻ biểu đồ chính xác chỉ được cung cấp từ trang bảng điều khiển
  • Nhấp vào hình tam giác bên cạnh tên biểu đồ và chọn chia sẻ từ menu
  • Trong cửa sổ mở ra, hãy chuyển đến tab nhúng
  • Bỏ chọn phạm vi thời gian hiện tại - chúng tôi sẽ đặt phạm vi thời gian qua URL
  • Chọn chủ đề cần thiết. Trong trường hợp của tôi thì nó nhẹ
  • Sao chép URL kết quả vào thẻ cài đặt lovelace-UI

      - type: iframe
        id: graf_water_hourly
        url: "http://192.168.10.200:3000/d-solo/rZARemQWk/water?orgId=1&panelId=2&from=now-2d&to=now&theme=light"

Xin lưu ý rằng phạm vi thời gian (2 ngày qua) được đặt ở đây chứ không phải trong cài đặt trang tổng quan.

Biểu đồ trông như thế này. Tôi không sử dụng nước nóng trong 2 ngày qua nên chỉ vẽ biểu đồ nước lạnh.

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Tôi vẫn chưa quyết định cho mình biểu đồ nào tôi thích hơn, bước đường hay thanh thực. Vì vậy, tôi sẽ chỉ đưa ra một ví dụ về biểu đồ tiêu thụ hàng ngày, lần này chỉ tính bằng thanh. Các truy vấn được xây dựng tương tự như những mô tả ở trên. Các tùy chọn hiển thị là:

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Biểu đồ này trông như thế này:

Nhà thông minh: Chúng tôi xây dựng biểu đồ tiêu thụ điện nước trong Home Assistant

Vậy về tham số Stack. Trong biểu đồ này, một cột nước lạnh được vẽ phía trên cột nước nóng. Tổng chiều cao tương ứng với tổng lượng nước nóng và lạnh tiêu thụ trong kỳ.

Tất cả các biểu đồ hiển thị là động. Bạn có thể di chuột qua điểm quan tâm và xem chi tiết cũng như giá trị tại một điểm cụ thể.

Thật không may, có một vài con ruồi trong thuốc mỡ. Trên biểu đồ thanh (không giống như biểu đồ có các đường bậc thang), phần giữa của thanh không nằm ở giữa ngày mà ở vị trí 00:00. Những thứ kia. nửa bên trái của cột được vẽ thay cho ngày hôm trước. Vì vậy, đồ thị cho Thứ Bảy và Chủ Nhật được vẽ hơi lệch về bên trái của vùng màu xanh lam. Cho đến khi tôi tìm ra cách đánh bại nó.

Một vấn đề khác là không có khả năng hoạt động bình thường hàng tháng. Thực tế là độ dài của giờ/ngày/tuần là cố định, nhưng độ dài của tháng ở mỗi thời điểm lại khác nhau. InfluxDB chỉ có thể hoạt động trong khoảng thời gian bằng nhau. Cho đến nay bộ não của tôi đã đủ để thiết lập một khoảng thời gian cố định là 30 ngày. Có, biểu đồ sẽ nổi một chút trong suốt cả năm và các thanh sẽ không tương ứng chính xác với các tháng. Nhưng vì tôi quan tâm đến thứ này chỉ đơn giản là đồng hồ hiển thị nên tôi đồng ý với nó.

Tôi thấy ít nhất hai giải pháp:

  • Hãy từ bỏ các biểu đồ hàng tháng và giới hạn bản thân ở những biểu đồ hàng tuần. 52 thanh hàng tuần trong năm trông khá đẹp
  • Hãy coi mức tiêu thụ hàng tháng là phương pháp số 2 và chỉ sử dụng grafana để có đồ thị đẹp. Nó sẽ là một giải pháp khá chính xác. Bạn thậm chí có thể xếp chồng các biểu đồ của năm vừa qua để so sánh - grafana cũng có thể làm điều đó.

Kết luận

Tôi không biết tại sao, nhưng tôi bị ám ảnh bởi những loại biểu đồ này. Chúng cho thấy cuộc sống đang sôi động và mọi thứ đang thay đổi. Hôm qua thì nhiều, hôm nay thì ít, ngày mai lại có chuyện khác. Tất cả những gì còn lại là làm việc với các thành viên trong gia đình về chủ đề tiêu dùng. Nhưng ngay cả với nhu cầu hiện tại, chỉ một con số lớn và khó hiểu trên phiếu thanh toán cũng đã trở thành một bức tranh tiêu dùng khá dễ hiểu.

Mặc dù đã có gần 20 năm làm lập trình viên nhưng tôi hầu như không có liên hệ gì với cơ sở dữ liệu. Do đó, việc cài đặt cơ sở dữ liệu bên ngoài có vẻ như một điều gì đó quá khó hiểu và khó hiểu. Đã thay đổi mọi thứ bài viết trên — hóa ra việc gắn một công cụ phù hợp được thực hiện chỉ trong vài cú nhấp chuột và với một công cụ chuyên dụng, công việc vẽ biểu đồ trở nên dễ dàng hơn một chút.

Trong tiêu đề tôi đã đề cập đến việc tiêu thụ điện. Thật không may, hiện tại tôi không thể cung cấp bất kỳ biểu đồ nào. Một đồng hồ đo SDM120 đã chết đối với tôi và đồng hồ còn lại bị trục trặc khi truy cập qua Modbus. Tuy nhiên, điều này không ảnh hưởng gì đến chủ đề của bài viết này - các biểu đồ sẽ được xây dựng theo cách tương tự như đối với nước.

Trong bài viết này, tôi đã trình bày các phương pháp mà bản thân tôi đã thử. Chắc chắn còn một số cách khác để tổ chức thu thập và trực quan hóa dữ liệu mà tôi chưa biết. Hãy cho tôi biết về nó trong phần bình luận, tôi sẽ rất quan tâm. Tôi sẽ vui mừng với những lời chỉ trích mang tính xây dựng và những ý tưởng mới. Tôi hy vọng tài liệu được trình bày cũng sẽ giúp được ai đó.

Nguồn: www.habr.com

Thêm một lời nhận xét