خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار
هر بار که پولی برای برق و آب دریافت می کنم، تعجب می کنم - آیا واقعاً خانواده من خیلی زیاد مصرف می کنند؟ خوب، بله، حمام دارای یک کف گرم و یک دیگ بخار است، اما آنها دائماً استوکرها را اخراج نمی کنند. همچنین به نظر می رسد در مصرف آب صرفه جویی می کنیم (اگرچه ما آب پاشیدن در حمام را نیز دوست داریم). چندین سال پیش من قبلا کنتورهای آب متصل и برق به یک خانه هوشمند، اما اینجاست که همه چیز گیر کرده است. دست‌ها به تحلیل مصرف رسیده‌اند، که در واقع این مقاله در مورد آن است.

من اخیراً به عنوان سیستم خانه هوشمند خود به Home Assistant تغییر مکان داده ام. یکی از دلایل فقط توانایی سازماندهی مجموعه ای از حجم زیادی از داده ها با امکان ساخت راحت انواع مختلف نمودارها بود.

اطلاعاتی که در این مقاله توضیح داده شده است جدید نیست، همه این موارد زیر سس های مختلف قبلاً در اینترنت شرح داده شده است. اما هر مقاله، به عنوان یک قاعده، تنها یک رویکرد یا جنبه را توصیف می کند. مجبور شدم همه این رویکردها را با هم مقایسه کنم و خودم مناسب ترین آنها را انتخاب کنم. مقاله هنوز اطلاعات جامعی در مورد جمع آوری داده ها ارائه نمی دهد، اما نوعی خلاصه ای از نحوه انجام آن است. بنابراین انتقاد سازنده و پیشنهادات برای بهبود استقبال می شود.

بیانیه مشکل

بنابراین، هدف از تمرین امروز دریافت نمودارهای زیبا از مصرف آب و برق است:

  • ساعتی به مدت 2 روز
  • روزانه به مدت 2 هفته
  • (اختیاری) هفتگی و ماهانه

در این زمینه مشکلاتی وجود دارد:

  • اجزای نمودار استاندارد معمولاً بسیار ضعیف هستند. در بهترین حالت، می توانید یک نمودار خطی را بر اساس نقاط بسازید.

    اگر خوب جستجو کنید، می توانید اجزای شخص ثالثی را پیدا کنید که قابلیت های نمودار استاندارد را گسترش می دهد. برای دستیار خانه، در اصل، یک جزء خوب و زیبا است کارت گرافیک کوچک، اما همچنین تا حدودی محدود است:

    • تنظیم پارامترهای نمودار میله ای در فواصل زیاد دشوار است (عرض میله بر حسب کسری از ساعت تنظیم می شود، به این معنی که فواصل بیشتر از یک ساعت به اعداد کسری تنظیم می شود)
    • شما نمی توانید موجودیت های مختلف را به یک نمودار اضافه کنید (به عنوان مثال، دما و رطوبت، یا ترکیب یک نمودار میله ای با یک خط)
  • نه تنها دستیار خانگی به طور پیش‌فرض از ابتدایی‌ترین پایگاه داده SQLite استفاده می‌کند (و من، کارشناس، بر نصب MySQL یا Postgres تسلط نداشتم)، داده‌ها به بهترین شکل ذخیره نمی‌شوند. بنابراین، برای مثال، با هر تغییر حتی کوچکترین پارامتر دیجیتالی یک پارامتر، یک json بزرگ در اندازه یک کیلوبایت در پایگاه داده نوشته می شود.
    {"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}}}

    من تعداد کمی سنسور دارم (سنسورهای دما در هر اتاق، کنتورهای آب و برق)، و برخی نیز داده‌های بسیار زیادی تولید می‌کنند. به عنوان مثال، تنها کنتور برق SDM220 در هر 10-15 ثانیه حدود ده مقدار تولید می کند و من می خواهم 8 عدد از این مترها را نصب کنم و همچنین یک دسته کامل از پارامترها وجود دارد که بر اساس سنسورهای دیگر محاسبه می شوند. که همه این مقادیر به راحتی می توانند پایگاه داده را 100-200 مگابایت در روز افزایش دهند. در عرض یک هفته، سیستم به سختی پرتاب می شود و در عرض یک ماه فلش مموری می میرد (در مورد نصب معمولی دستیار خانگی در Raspberry PI) و نمی توان صحبتی از ذخیره داده ها برای یک سال کامل کرد. .

  • اگر خوش شانس باشید، خود متر شما می تواند میزان مصرف را محاسبه کند. شما می توانید در هر زمان با کنتور تماس بگیرید و بپرسید که مقدار مصرف انباشته چند ساعت است. به عنوان یک قاعده، تمام کنتورهای برق که دارای رابط دیجیتال هستند (RS232/RS485/Modbus/Zigbee) چنین فرصتی را فراهم می کنند.

    بدتر از آن، اگر دستگاه به سادگی بتواند برخی از پارامترهای آنی (مثلاً توان یا جریان لحظه ای) را اندازه گیری کند، یا به سادگی پالس هایی را در هر X وات ساعت یا لیتر تولید کند. سپس باید به این فکر کنید که چگونه و با چه چیزی آن را ادغام کنید و کجا ارزش انباشته کنید. خطر از دست دادن گزارش بعدی به هر دلیلی وجود دارد و صحت سیستم در کل سؤالاتی را ایجاد می کند. مطمئناً می‌توانید همه اینها را به یک سیستم خانه هوشمند مانند دستیار خانگی بسپارید، اما هیچ‌کس موضوع تعداد ورودی‌های پایگاه داده را لغو نکرده است و سنسورهای نظرسنجی بیش از یک بار در ثانیه کار نمی‌کنند (محدودیت معماری دستیار خانه).

رویکرد 1

ابتدا، بیایید ببینیم چه دستیار خانگی خارج از جعبه ارائه می شود. اندازه گیری مصرف در یک دوره یک عملکرد بسیار درخواستی است. البته مدتها پیش به عنوان یک جزء تخصصی - utility_meter پیاده سازی شد.

ماهیت کامپوننت این است که متغیر current_accumulated_value را در داخل شروع می کند و پس از یک دوره مشخص (ساعت/هفته/ماه) آن را بازنشانی می کند. خود مؤلفه متغیر ورودی (مقدار نوعی سنسور) را نظارت می کند ، در تغییرات خود مقدار مشترک می شود - شما فقط نتیجه نهایی را دریافت می کنید. این مورد فقط در چند خط در فایل پیکربندی توضیح داده شده است

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

در اینجا sensor.water_meter_cold مقدار فعلی متر بر حسب لیتر است که من دریافت می کنم مستقیما از اتو توسط mqtt. این طراحی 2 حسگر جدید water_cold_hour_um و water_cold_day_um را ایجاد می‌کند که قرائت‌های ساعتی و روزانه را جمع‌آوری می‌کنند و پس از یک دوره آن‌ها را به صفر می‌رسانند. در اینجا نموداری از باتری ساعتی برای نیم روز است.

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

کد نمودار ساعتی و روزانه برای lovelace-UI به شکل زیر است:

      - 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

در واقع مشکل این رویکرد در این الگوریتم نهفته است. همانطور که قبلاً اشاره کردم، برای هر مقدار ورودی (خوانش کنتور فعلی برای هر لیتر بعدی)، 1 کیلوبایت رکورد در پایگاه داده تولید می شود. هر متر ابزار یک مقدار جدید نیز تولید می کند که به پایه نیز اضافه می شود. اگر بخواهم قرائت های ساعتی/روزانه/هفتگی/ماهانه را جمع آوری کنم، بله، برای چندین بالابر آب، و حتی یک بسته کنتور برق اضافه کنم، این داده های زیادی خواهد بود. خوب، به طور دقیق تر، داده های زیادی وجود ندارد، اما از آنجایی که دستیار خانگی مجموعه ای از اطلاعات غیر ضروری را در پایگاه داده می نویسد، اندازه پایگاه داده با جهش و مرز افزایش می یابد. من حتی از تخمین اندازه پایه برای نمودارهای هفتگی و ماهانه می ترسم.

علاوه بر این، کنتور برق خود مشکل را حل نمی کند. نمودار متر ابزار یک تابع افزایش یکنواخت است که هر ساعت به 0 بازنشانی می شود. ما همچنین به یک برنامه مصرف کاربر پسند نیاز داریم که در طول دوره چند لیتر خورده شده است. مؤلفه استاندارد history-graph این کار را انجام نمی دهد، اما مولفه کارت گرافیک کوچک خارجی می تواند به ما کمک کند.

این کد کارت برای 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'

علاوه بر تنظیمات استاندارد مانند نام سنسور، نوع نمودار، رنگ (من نارنجی استاندارد را دوست نداشتم)، توجه به 3 تنظیمات در اینجا مهم است:

  • group_by:hour - نمودار با ستون های تراز اول ساعت ایجاد می شود
  • نقاط_در_ساعت: 1 - یک بار در ساعت
  • و مهمتر از همه، aggregate_func: max این است که حداکثر مقدار را در هر ساعت بگیرید. این پارامتر است که نمودار دندانه اره را به میله تبدیل می کند.

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

به ردیف ستون ها در سمت چپ توجه نکنید - اگر داده ای وجود نداشته باشد این رفتار استاندارد مؤلفه است. اما هیچ داده ای وجود نداشت - من فقط چند ساعت پیش به خاطر این مقاله جمع آوری داده ها را با استفاده از ابزار سنج روشن کردم (رویکرد فعلی خود را کمی پایین تر شرح خواهم داد).

در این تصویر می خواستم نشان دهم که گاهی اوقات نمایش داده ها حتی کار می کند و نوارها واقعاً مقادیر صحیح را منعکس می کنند. اما این همه ماجرا نیست. بنا به دلایلی، ستون برجسته شده برای بازه زمانی 11 صبح تا 12 صبح، 19 لیتر را نشان می دهد، اگرچه در نمودار دندانه دار کمی بالاتر برای مدت مشابه از همان سنسور شاهد مصرف 62 لیتر هستیم. یا حشره یا دست ها کج هستند. اما من هنوز نمی فهمم که چرا داده های سمت راست قطع شد - مصرف در آنجا طبیعی بود که از نمودار دندانه دار نیز قابل مشاهده است.

به طور کلی، من نتوانستم به معقول بودن این رویکرد دست پیدا کنم - نمودار تقریباً همیشه نوعی بدعت را نشان می دهد.

کد مشابه برای سنسور روز.

      - 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'

لطفاً توجه داشته باشید که پارامتر group_by روی فاصله تنظیم شده است و پارامتر points_per_hour همه چیز را کنترل می کند. و این یکی دیگر از مشکلات این مؤلفه است - points_per_hour روی نمودارهای یک ساعت یا کمتر به خوبی کار می کند، اما در فواصل زمانی بزرگتر به طرز مشمئز کننده ای کار می کند. بنابراین برای بدست آوردن یک ستون در یک روز، باید مقدار 1/24=0.04166666 را وارد کنم. من در مورد نمودارهای هفتگی و ماهانه صحبت نمی کنم.

رویکرد 2

در حالی که هنوز در حال کشف دستیار خانگی بودم، با این ویدیو روبرو شدم:


رفیق داده های مصرف را از چندین نوع سوکت شیائومی جمع آوری می کند. وظیفه او کمی ساده تر است - فقط ارزش مصرف را برای امروز، دیروز و برای ماه نمایش دهید. بدون نمودار مورد نیاز است.

بیایید بحث های مربوط به ادغام دستی مقادیر توان لحظه ای را کنار بگذاریم - قبلاً در مورد "دقت" این رویکرد در بالا نوشتم. مشخص نیست چرا او از مقادیر مصرف انباشته که قبلاً توسط همان خروجی جمع آوری شده است استفاده نکرده است. به نظر من ادغام داخل قطعه آهن بهتر عمل خواهد کرد.

از ویدیو، ایده شمارش دستی مصرف برای یک دوره را می گیریم. برای یک مرد، فقط مقادیر امروز و دیروز در نظر گرفته می شود، اما ما جلوتر می رویم و سعی می کنیم یک نمودار ترسیم کنیم. ماهیت روش پیشنهادی در مورد من به شرح زیر است.

ما یک متغیر value_at_the_beginning_of_hour ایجاد می کنیم که در آن خوانش شمارنده فعلی را می نویسیم.
با توجه به تایمر در پایان ساعت (یا در ابتدای ساعت بعدی)، ما تفاوت بین قرائت فعلی و ذخیره شده در ابتدای ساعت را محاسبه می کنیم. این تفاوت مصرف ساعت فعلی خواهد بود - ما مقدار را در سنسور ذخیره می کنیم و در آینده یک نمودار بر اساس این مقدار خواهیم ساخت.
همچنین باید با نوشتن مقدار فعلی شمارنده در آنجا، متغیر value_at_beginning_of_hour را "تنظیم مجدد" کنید.

همه اینها را می توان از طریق ... توسط خود دستیار خانگی انجام داد.

شما باید کمی بیشتر از روش قبلی کد بنویسید. بیایید با این "متغیرها" شروع کنیم. خارج از جعبه، ما موجودیت "متغیر" نداریم، اما می توانید از خدمات یک کارگزار mqtt استفاده کنید. ما مقادیر را با پرچم retain=true به آنجا ارسال می‌کنیم - این مقدار را در داخل کارگزار ذخیره می‌کند و می‌توان آن را در هر زمان بیرون کشید، حتی زمانی که دستیار خانگی مجددا راه‌اندازی شود. شمارنده های ساعتی و روزانه را به یکباره درست کردم.

- 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

همه جادوها در اتوماسیون اتفاق می افتد که به ترتیب هر ساعت و هر شب اجرا می شود.

- 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

هر دو اتوماسیون 2 کار را انجام می دهند:

  • مقدار در هر بازه را به عنوان تفاوت بین مقدار شروع و پایان محاسبه کنید
  • مقدار پایه را برای بازه بعدی به روز کنید

ساخت نمودارها در این مورد با نمودار تاریخچه معمول حل می شود:

      - 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

این به نظر می رسد:

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

در اصل، این همان چیزی است که شما نیاز دارید. مزیت این روش این است که داده ها یک بار در هر بازه تولید می شوند. آن ها در مجموع 24 ورودی در روز برای نمودار ساعتی.

متأسفانه، این هنوز هم مشکل کلی یک پایگاه رو به رشد را حل نمی کند. اگر من یک نمودار مصرف ماهانه بخواهم، باید حداقل یک سال اطلاعات را ذخیره کنم. و از آنجایی که دستیار خانگی تنها یک تنظیم مدت زمان ذخیره سازی را برای کل پایگاه داده ارائه می دهد، این بدان معناست که تمام داده های سیستم باید برای یک سال کامل ذخیره شوند. به عنوان مثال، من در یک سال 200 متر مکعب آب مصرف می کنم، یعنی 200000 ورودی در پایگاه داده. و اگر سنسورهای دیگر را در نظر بگیرید، این رقم به طور کلی ناپسند می شود.

رویکرد 3

خوشبختانه افراد باهوش قبلا این مشکل را با نوشتن پایگاه داده InfluxDB حل کرده اند. این پایگاه داده به طور ویژه برای ذخیره داده های مبتنی بر زمان بهینه شده است و برای ذخیره مقادیر سنسورهای مختلف ایده آل است. این سیستم همچنین یک زبان پرس و جو مانند SQL ارائه می دهد که به شما امکان می دهد مقادیر را از پایگاه داده استخراج کنید و سپس آنها را به روش های مختلف جمع آوری کنید. در نهایت، داده های مختلف را می توان برای زمان های مختلف ذخیره کرد. به عنوان مثال، مقادیر مکرر تغییر مانند دما یا رطوبت را می توان تنها برای چند هفته ذخیره کرد، در حالی که قرائت روزانه مصرف آب را می توان برای یک سال کامل ذخیره کرد.

علاوه بر InfluxDB، افراد باهوش نیز Grafana را اختراع کردند، سیستمی برای ترسیم نمودارها از داده های InfluxDB. Grafana می تواند انواع مختلفی از نمودارها را ترسیم کند، آنها را با جزئیات سفارشی کند، و مهمتر از همه، این نمودارها را می توان به دستیار خانگی lovelace-UI "وصل کرد".

الهام گرفته شود اینجا и اینجا. مقالات به طور مفصل روند نصب و اتصال InfluxDB و Grafana به دستیار خانگی را شرح می دهند. من بر حل مشکل خاص خود تمرکز خواهم کرد.

بنابراین، اول از همه، اجازه دهید شروع به اضافه کردن مقدار شمارنده در influxDB کنیم. بخشی از پیکربندی دستیار خانگی (در این مثال، نه تنها با آب سرد، بلکه با آب گرم نیز سرگرم خواهم شد):

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

بیایید ذخیره همان داده ها را در پایگاه داده داخلی دستیار خانگی خاموش کنیم تا یک بار دیگر آن را افزایش ندهیم:

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

بیایید اکنون به کنسول InfluxDB برویم و پایگاه داده خود را راه اندازی کنیم. به ویژه، باید پیکربندی کنید که چه مدت داده های خاصی ذخیره می شوند. این است که توسط به اصطلاح تنظیم می شود. سیاست حفظ - این شبیه به پایگاه داده های داخل پایگاه داده اصلی است، با هر پایگاه داده داخلی تنظیمات خاص خود را دارد. به طور پیش فرض، تمام داده ها به سیاست حفظ به نام autogen اضافه می شود، این داده ها به مدت یک هفته ذخیره می شوند. من می خواهم داده های ساعتی برای یک ماه، داده های هفتگی برای یک سال و داده های ماهانه هرگز حذف نشوند. ما سیاست های نگهداری مناسب ایجاد خواهیم کرد

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

اکنون، در واقع، ترفند اصلی تجمیع داده ها با استفاده از پرس و جو مداوم است. این مکانیزمی است که به طور خودکار یک پرس و جو را در بازه های زمانی مشخص راه اندازی می کند، داده های این پرس و جو را جمع می کند و نتیجه را به یک مقدار جدید اضافه می کند. بیایید به یک مثال نگاه کنیم (من برای خوانایی در یک ستون می نویسم، اما در واقع باید این دستور را در یک خط وارد می کردم)

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

این دستور:

  • یک پرسش پیوسته با نام cq_water_cold_hourly در پایگاه داده homeassistant ایجاد می کند.
  • پرس و جو هر ساعت اجرا می شود (زمان (1 ساعت))
  • پرس و جو همه داده ها را از اندازه گیری homeassistant.autogen.l (لیتر) از جمله خواندن آب سرد و گرم خارج می کند.
  • داده های جمع آوری شده توسط entity_id گروه بندی می شوند که مقادیر جداگانه ای برای آب سرد و گرم ایجاد می کند.
  • از آنجایی که شمارشگر لیتر یک توالی افزایشی یکنواخت در هر ساعت است، باید حداکثر مقدار را بگیرید، بنابراین تجمیع توسط تابع max(value) انجام می شود.
  • مقدار جدید در homeassistant.month.water_meter_hour نوشته می‌شود که ماه نام خط‌مشی نگهداری با دوره نگهداری یک ماهه است. علاوه بر این، داده‌های مربوط به آب سرد و گرم در رکوردهای جداگانه با entity_id مربوطه و مقدار در فیلد مقدار پراکنده می‌شوند.

در شب یا زمانی که کسی در خانه نیست، مصرف آب وجود ندارد و بر این اساس در homeassistant.autogen.l نیز رکورد جدیدی ثبت نشده است. برای جلوگیری از گم شدن مقادیر در پرس و جوهای معمولی، می توانید از fill(previous) استفاده کنید. این باعث می شود InfluxDB از مقدار ساعت گذشته استفاده کند.

متأسفانه، پرس و جو پیوسته یک ویژگی خاص دارد: ترفند fill (قبلی) کار نمی کند و رکوردها به سادگی ایجاد نمی شوند. علاوه بر این، این یک نوع مشکل غیر قابل حل است که بیش از یک سال است که مورد بحث قرار گرفته است. ما بعداً با این مشکل برخورد خواهیم کرد و اجازه می‌دهیم پر (قبلی) در پرس و جوی مداوم وجود داشته باشد - تداخلی ندارد.

بیایید بررسی کنیم که چه اتفاقی افتاده است (البته، باید چند ساعت صبر کنید):

> 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

توجه داشته باشید که مقادیر موجود در پایگاه داده در UTC ذخیره می شوند، بنابراین این لیست 3 ساعت متفاوت است - مقادیر 7am در خروجی InfluxDB با مقادیر 10am در نمودارهای بالا مطابقت دارد. همچنین توجه داشته باشید که بین ساعت 2 و 5 صبح به سادگی هیچ رکوردی وجود ندارد - این همان ویژگی جستجوی مداوم است.

همانطور که می بینید، مقدار انباشته نیز یک توالی یکنواخت در حال افزایش است، فقط ورودی ها کمتر تکرار می شوند - یک بار در ساعت. اما این مشکلی نیست - ما می توانیم پرس و جو دیگری بنویسیم که داده های صحیح را برای نمودار استخراج می کند.

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)

رمزگشایی خواهم کرد:

  • از پایگاه داده homeassistant.month.water_meter_hour، داده‌های مربوط به entity_id='water_meter_cold' را برای آخرین روز (time >= now() -24h) می‌گیریم.
  • همانطور که اشاره کردم، برخی از ورودی‌ها ممکن است در دنباله homeassistant.month.water_meter_hour وجود نداشته باشند. ما این داده ها را با اجرای پرس و جو با زمان (1 ساعت) GROUP BY دوباره تولید می کنیم. این بار fill(previous) به درستی کار می کند و داده های از دست رفته را تولید می کند (تابع مقدار قبلی را می گیرد)
  • مهمترین چیز در این پرس و جو تابع تفاوت است که تفاوت بین علائم ساعت را محاسبه می کند. به خودی خود کار نمی کند و به یک تابع تجمیع نیاز دارد. اجازه دهید این حداکثر () مورد استفاده قبل باشد.

نتیجه اجرا به این شکل است

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

از ساعت 2 صبح تا 5 صبح (UTC) هیچ مصرفی وجود نداشت. با این وجود، پرس و جو به لطف fill(previous) همان مقدار مصرف را برمی گرداند، و تابع تفاوت این مقدار را از خودش کم می کند و در خروجی 0 می گیرد که در واقع مورد نیاز است.

تنها کاری که باید انجام دهید این است که یک نمودار بسازید. برای انجام این کار، Grafana را باز کنید، داشبورد موجود (یا ایجاد یک جدید) را باز کنید، یک پنل جدید ایجاد کنید. تنظیمات نمودار به صورت زیر خواهد بود.

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

من داده های آب سرد و گرم را در همان نمودار نمایش خواهم داد. درخواست دقیقاً همان است که در بالا توضیح دادم.

پارامترهای نمایش به صورت زیر تنظیم می شوند. برای من این یک نمودار با خطوط (خطوط) خواهد بود که در مراحل (پله ها) پیش می رود. پارامتر Stack در زیر توضیح داده خواهد شد. چند گزینه نمایش دیگر در زیر وجود دارد، اما آنها چندان جالب نیستند.

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

برای افزودن نمودار حاصل به دستیار خانگی، باید:

  • از حالت ویرایش نمودار خارج شوید. به دلایلی، تنظیمات صحیح اشتراک‌گذاری نمودار فقط از صفحه داشبورد ارائه می‌شود
  • روی مثلث کنار نام نمودار کلیک کنید، از منو گزینه share را انتخاب کنید
  • در پنجره باز شده به تب embed بروید
  • علامت محدوده زمانی فعلی را بردارید - ما محدوده زمانی را از طریق URL تنظیم می کنیم
  • موضوع مورد نیاز را انتخاب کنید. در مورد من سبک است
  • URL حاصل را در کارت تنظیمات 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"

لطفاً توجه داشته باشید که محدوده زمانی (2 روز گذشته) در اینجا تنظیم شده است و در تنظیمات داشبورد نیست.

نمودار به این شکل است. من در 2 روز گذشته از آب گرم استفاده نکرده ام، بنابراین فقط نمودار آب سرد رسم می شود.

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

من برای خودم تصمیم نگرفته ام که کدام نمودار را بیشتر دوست دارم، یک خط پله یا میله های واقعی. بنابراین، من به سادگی یک مثال از برنامه مصرف روزانه، فقط این بار در بارها را بیان می کنم. کوئری ها به همان روشی که در بالا توضیح داده شد ساخته می شوند. گزینه های نمایش عبارتند از:

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

این نمودار به شکل زیر است:

خانه هوشمند: نمودار مصرف آب و برق در خانه دستیار

بنابراین، در مورد پارامتر Stack. در این نمودار یک نوار آب سرد در بالای یک میله گرم ترسیم شده است. ارتفاع کل مربوط به کل مصرف آب سرد و گرم برای دوره است.

تمام نمودارهای نشان داده شده پویا هستند. می توانید ماوس را روی نقطه مورد نظر حرکت دهید و جزئیات و ارزش را در یک نقطه خاص مشاهده کنید.

متأسفانه، آن را بدون چند مگس در پماد نبود. در نمودار میله ای (برخلاف نمودار با خطوط پله)، وسط میله نه در وسط روز، بلکه در ساعت 00:00 است. آن ها نیمه چپ میله به جای روز قبل کشیده شده است. بنابراین نمودارهای شنبه و یکشنبه کمی به سمت چپ منطقه آبی کشیده شده اند. تا اینکه فهمیدم چگونه برنده شوم.

مشکل دیگر عدم توانایی کارکرد صحیح با فواصل ماهانه است. واقعیت این است که طول ساعت / روز / هفته ثابت است، اما طول ماه هر بار متفاوت است. InfluxDB فقط می تواند با فواصل مساوی کار کند. تا اینجای کار، مغز من برای تعیین فاصله ثابت 30 روزه کافی بوده است. بله، نمودار در طول سال کمی شناور می شود و میله ها دقیقاً با ماه ها مطابقت ندارند. اما از آنجایی که این چیز فقط به عنوان یک نمایشگر برای من جالب است، من با این مشکلی ندارم.

من حداقل دو راه حل می بینم:

  • برای امتیاز در نمودارهای ماهانه و محدود کردن خود به نمودارهای هفتگی. 52 بار هفتگی در یک سال بسیار خوب به نظر می رسند
  • خود مصرف ماهانه را به عنوان روش شماره 2 در نظر بگیرید و از گرانا فقط برای نمودارهای زیبا استفاده کنید. این یک راه حل کاملا دقیق است. حتی می توانید نمودارهای سال گذشته را برای مقایسه روی هم قرار دهید - grafana می تواند این کار را انجام دهد.

نتیجه

نمی دانم چرا، اما من عاشق این نوع نمودارها هستم. آنها نشان می دهند که زندگی در جریان است و همه چیز در حال تغییر است. دیروز زیاد بود، امروز کم است، فردا چیز دیگری خواهد بود. کار با خانوارها در موضوع مصرف باقی مانده است. اما حتی با وجود اشتهای فعلی، فقط یک رقم بزرگ و نامفهوم در صورتحساب در حال تبدیل به تصویری نسبتاً قابل درک از مصرف است.

علیرغم فعالیت تقریباً 20 ساله من به عنوان برنامه نویس، من عملاً با پایگاه داده ها تلاقی نداشتم. بنابراین، نصب یک پایگاه داده خارجی چیزی بسیار مبهم و نامفهوم به نظر می رسید. همه چیز تغییر کرده است مقاله فوق - مشخص شد که پیچ کردن یک ابزار مناسب با چند کلیک انجام می شود و با یک ابزار تخصصی، کار ترسیم کمی آسان می شود.

در عنوان به مصرف برق اشاره کردم. متاسفانه در حال حاضر نمی توانم هیچ نموداری ارائه دهم. یک متر SDM120 مرده است و دیگری باگ است که از طریق Modbus به آن دسترسی پیدا کنید. با این حال، این موضوع به هیچ وجه بر موضوع این مقاله تأثیر نمی گذارد - نمودارها به همان روشی که برای آب ساخته می شود.

در این مقاله، من آن رویکردهایی را که خودم امتحان کرده ام، آورده ام. مطمئناً راه‌های دیگری برای سازماندهی جمع‌آوری و تجسم داده‌ها وجود دارد که من در مورد آنها اطلاعی ندارم. در مورد آن در نظرات به من بگویید، من بسیار علاقه مند خواهم شد. من از انتقاد سازنده و ایده های جدید خوشحال خواهم شد. امیدوارم مطالب فوق به کسی کمک کند.

منبع: www.habr.com

اضافه کردن نظر