
בכל פעם שאני מקבל תשלום עבור חשמל ומים, אני תוהה - האם המשפחה שלי באמת צורכת כל כך הרבה? ובכן, כן, יש רצפה מחוממת ודוד בחדר האמבטיה, אבל הם לא עובדים ככבאים כל הזמן. נראה שגם אנחנו חוסכים במים (למרות שאנחנו גם אוהבים להתיז בשירותים). לפני כמה שנים אני כבר и לבית חכם, אבל זה המקום שבו הדברים נתקעו. הידיים הגיעו לניתוח הצריכה רק עכשיו, שלמעשה בו עוסקת המאמר הזה.
לאחרונה עברתי ל-Home Assistant כמערכת הבית החכם שלי. אחת הסיבות הייתה רק היכולת לארגן איסוף של כמות גדולה של נתונים עם אפשרות לבנייה נוחה של סוגים שונים של גרפים.
המידע המתואר במאמר זה אינו חדש, כל הדברים הללו תחת רטבים שונים כבר תוארו באינטרנט. אבל כל מאמר, ככלל, מתאר רק גישה או היבט אחד. נאלצתי להשוות את כל הגישות הללו ולבחור את המתאימה ביותר בעצמי. המאמר עדיין לא מספק מידע ממצה על איסוף נתונים, אבל הוא סוג של סיכום של איך עשיתי את זה. אז ביקורת בונה והצעות לשיפור יתקבלו בברכה.
הצהרת הבעיה
לכן, המטרה של התרגיל היום היא לקבל גרפים יפים של צריכת מים וחשמל:
- כל שעה למשך יומיים
- מדי יום במשך שבועיים
- (אופציונלי) שבועי וחודשי
יש בזה כמה קשיים:
- רכיבי התרשים הסטנדרטיים נוטים להיות גרועים למדי. במקרה הטוב, אתה יכול לבנות גרף קו לפי נקודות.
אם תחפשו היטב, תוכלו למצוא רכיבי צד שלישי שמרחיבים את היכולות של התרשים הסטנדרטי. לעוזרת בית, עקרונית, רכיב טוב ויפה , אבל זה גם מוגבל במקצת:
- קשה להגדיר את הפרמטרים של תרשים העמודות במרווחים גדולים (רוחב הבר נקבע בשברירי שעה, כלומר מרווחים של יותר משעה ייקבעו במספרים שברים)
- לא ניתן להוסיף ישויות שונות לגרף אחד (לדוגמה, טמפרטורה ולחות, או לשלב גרף עמודות עם קו)
- לא רק שעוזרת הבית משתמשת כברירת מחדל במסד הנתונים הפרימיטיבי ביותר של 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
למעשה, באלגוריתם זה טמונה הבעיה של גישה זו. כפי שכבר ציינתי, עבור כל ערך נכנס (קריאת המונה הנוכחית עבור כל ליטר הבא), נוצר 1kb של רשומה במסד הנתונים. כל מד שירות מייצר גם ערך חדש, שמתווסף גם הוא לבסיס. אם אני רוצה לאסוף קריאות שעתיות/יומיות/שבועיות/חודשיות, כן, עבור מספר מגדלי מים, ואפילו להוסיף חבילה של מונים חשמליים, זה יהיה הרבה נתונים. ובכן, ליתר דיוק, אין הרבה נתונים, אבל מכיוון שעוזרת הבית כותבת המון מידע מיותר למסד הנתונים, גודל המאגר יגדל בצעדי ענק. אני אפילו חושש להעריך את גודל הבסיס לתרשימים שבועיים וחודשיים.
בנוסף, מד השירות עצמו אינו פותר את הבעיה. עלילת מד השירות היא פונקציה הגדלה מונוטונית שמתאפסת ל-0 בכל שעה. צריך גם לוח צריכה ידידותי למשתמש, כמה ליטרים נאכלו במהלך התקופה. רכיב ההיסטוריה-גרף הסטנדרטי אינו עושה זאת, אך רכיב המיני-גרף-כרטיס החיצוני יכול לעזור לנו.
זה קוד הכרטיס עבור 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 מציגה XNUMX ליטר, אם כי בגרף השיניים מעט גבוה יותר לאותה תקופה מאותו חיישן אנו רואים צריכה של XNUMX ליטר. או באג, או שהידיים עקומות. אבל אני עדיין לא מבין למה הנתונים בצד ימין נשברו - הצריכה שם הייתה תקינה, מה שנראה גם מהגרף המשובש.
באופן כללי, לא הצלחתי להשיג את הסבירות של גישה זו - הגרף כמעט תמיד מראה איזושהי כפירה.
קוד דומה לחיישן שעות היום.
- 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 מוגדר ל-interval, והפרמטר points_per_hour שולט על הכל. וזו בעיה נוספת עם הרכיב הזה - points_per_hour עובד היטב על תרשימים של שעה או פחות, אבל באופן מגעיל במרווחים גדולים יותר. אז כדי לקבל עמודה אחת ביום אחד, הייתי צריך להזין את הערך 1/24=0.04166666. אני לא מדבר על תרשימים שבועיים וחודשיים.
גישה 2
בעודי עדיין להבין את העוזרת הביתית, נתקלתי בסרטון הזה:

החבר אוסף נתוני צריכה מכמה סוגים של שקעי Xiaomi. המשימה שלו קצת יותר פשוטה - רק להציג את ערך הצריכה להיום, אתמול ולחודש. אין צורך בתרשימים.
בואו נעזוב בצד את הוויכוחים על האינטגרציה הידנית של ערכי כוח מיידיים - כבר כתבתי על "הדיוק" של גישה זו לעיל. לא ברור מדוע לא השתמש בערכי הצריכה המצטברים, שכבר נאספים על ידי אותו שקע. לדעתי, שילוב בתוך פיסת הברזל יעבוד טוב יותר.
מהסרטון, ניקח את הרעיון של ספירה ידנית של צריכה למשך תקופה. עבור גבר, רק הערכים של היום ושל אתמול נחשבים, אבל נלך רחוק יותר וננסה לצייר גרף. מהות השיטה המוצעת במקרה שלי היא כדלקמן.
ניצור ערך_בתחילת_השעה משתנה, שבו נכתוב את קריאות המונה הנוכחיות
לפי הטיימר בסוף השעה (או בתחילת השעה הבאה), אנו מחשבים את ההפרש בין הקריאה הנוכחית לזו שנשמרה בתחילת השעה. ההפרש הזה יהיה הצריכה לשעה הנוכחית - נשמור את הערך לחיישן, ובעתיד נבנה גרף על בסיס ערך זה.
אתה גם צריך "לאפס" את המשתנה 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 במסד הנתונים של עוזר הבית
- השאילתה תבוצע כל שעה (זמן (1h))
- השאילתה תשלוף את כל הנתונים מ-meading'a homeassistant.autogen.l (ליטר), כולל קריאות של מים קרים וחמים
- הנתונים המצטברים יקובצו לפי entity_id, שייצור ערכים נפרדים למים קרים וחמים.
- מכיוון שמונה הליטרים הוא רצף מונוטוני העולה בכל שעה, תצטרך לקחת את הערך המקסימלי, כך שהצבירה תתבצע על ידי הפונקציה max(value)
- הערך החדש ייכתב ל-homeassistant.month.water_meter_hour כאשר חודש הוא שם פוליסת השמירה עם תקופת שמירה של חודש. יתרה מכך, נתונים על מים קרים וחמים יפוזרו לרשומות נפרדות עם ה-entity_id המתאים והערך בשדה הערך
בלילה או כשאין איש בבית, אין צריכת מים, ובהתאם לכך אין שיאים חדשים גם ב-homeassistant.autogen.l. כדי למנוע ערכים חסרים בשאילתות רגילות, אתה יכול להשתמש במילוי (הקודם). זה יאלץ את InfluxDB להשתמש בערך השעה האחרונה.
למרבה הצער, לשאילתה מתמשכת יש ייחוד: הטריק למילוי (הקודם) לא עובד ורשומות פשוט לא נוצרות. יתר על כן, מדובר בסוג של בעיה בלתי פתירה, אשר . נטפל בבעיה הזו בהמשך, ונאפשר למילוי (הקודם) בשאילתה רציפה להיות שם - זה לא מפריע.
בוא נבדוק מה קרה (כמובן, אתה צריך לחכות כמה שעות):
> 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 שעות - ערכי ה-7 בבוקר בפלט InfluxDB תואמים לערכי השעה 10:2 בתרשימים למעלה. שים לב גם שבין 5 ל-XNUMX בבוקר פשוט אין רשומות - זו עצם התכונה של שאילתה רציפה.
כפי שאתה יכול לראות, הערך המצטבר הוא גם רצף מונוטוני הולך וגדל, רק הערכים הם פחות תכופים - פעם בשעה. אבל זו לא בעיה - נוכל לכתוב שאילתה נוספת שתחלץ את הנתונים הנכונים לתרשים.
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' עבור היום האחרון (שעה >= now() -24h).
- כפי שציינתי, ייתכן שחלק מהערכים חסרים ברצף homeassistant.month.water_meter_hour. אנו ניצור מחדש נתונים אלה על ידי הפעלת השאילתה עם GROUP BY time(1h). הפעם, fill(הקודם) יעבוד כמו שצריך, וייצור את הנתונים החסרים (הפונקציה תקבל את הערך הקודם)
- הדבר החשוב ביותר בשאילתה זו הוא פונקציית ההבדל, שתחשב את ההפרש בין ציוני השעות. כשלעצמו, זה לא עובד ודורש פונקציית צבירה. תן לזה להיות max() ששימש קודם.
תוצאת הביצוע נראית כך
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 יוסבר להלן. ישנן עוד כמה אפשרויות תצוגה למטה, אבל הן לא כל כך מעניינות.

כדי להוסיף את הגרף המתקבל לעוזרת הבית, עליך:
- צא ממצב עריכת התרשים. מסיבה כלשהי, הגדרות שיתוף התרשים הנכונות מוצעות רק מדף לוח המחוונים
- לחץ על המשולש ליד שם התרשים, בחר שיתוף מהתפריט
- בחלון שנפתח, עבור ללשונית הטמעה
- בטל את הסימון של טווח הזמן הנוכחי - אנו נגדיר את טווח הזמן באמצעות 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"
שימו לב שטווח הזמן (היומיים האחרונים) מוגדר כאן, ולא בהגדרות לוח המחוונים.
התרשים נראה כך. לא השתמשתי במים חמים ביומיים האחרונים, אז רק גרף של מים קרים מצויר.

לא החלטתי בעצמי איזה תרשים אני הכי אוהב, קו צעד או ברים אמיתיים. לכן, אני פשוט אתן דוגמה ללוח זמנים לצריכה יומית, רק הפעם בברים. שאילתות בנויות באותו אופן כפי שתואר לעיל. אפשרויות התצוגה הן:

התרשים הזה נראה כך:

אז בקשר לפרמטר Stack. בגרף זה, סרגל מים קרים מצויר על גבי סרגל חמים. הגובה הכולל מתאים לצריכה הכוללת של מים קרים וחמים לתקופה.
כל הגרפים המוצגים הם דינמיים. ניתן להעביר את העכבר מעל נקודת העניין ולראות את הפרטים והערך בנקודה מסוימת.
למרבה הצער, זה לא היה בלי כמה זבובים במשחה. בתרשים עמודות (בניגוד לגרף עם קווי צעד), אמצע הפס אינו באמצע היום, אלא בשעה 00:00. הָהֵן. החצי השמאלי של הסרגל מצויר במקום היום הקודם. אז התרשימים לשבת וראשון מצוירים מעט משמאל לאזור הכחלחל. עד שהבנתי איך לזכות בו.
בעיה נוספת היא חוסר היכולת לעבוד בצורה נכונה עם מרווחים חודשיים. העובדה היא שאורך השעה / יום / שבוע קבוע, אך אורך החודש שונה בכל פעם. InfluxDB יכול לעבוד רק במרווחים שווים. עד כה, המוח שלי הספיק להגדיר מרווח קבוע של 30 יום. כן, הגרף ירחף מעט במהלך השנה והפסים לא יתאימו בדיוק לחודשים. אבל מכיוון שהדבר הזה מעניין אותי רק בתור מד תצוגה, אני בסדר עם זה.
אני רואה לפחות שני פתרונות:
- כדי להבקיע בתרשימים חודשיים ולהגביל את עצמך לשבועיים. 52 בארים שבועיים בשנה נראים די טוב
- קחו בחשבון את הצריכה החודשית עצמה כשיטה מס' 2, והשתמשו בגראפנה רק לגרפים יפים. זה פתרון די מדויק. אתה יכול אפילו לכסות תרשימים של השנה האחרונה לשם השוואה - גראפנה יכולה לעשות את זה.
מסקנה
אני לא יודע למה, אבל אני אוהב תרשימים מהסוג הזה. הם מראים שהחיים בעיצומם והכל משתנה. אתמול היה הרבה, היום יש מעט, מחר יהיה משהו אחר. נותר לעבוד עם משקי בית על נושא הצריכה. אבל גם עם התיאבון הנוכחי, רק נתון גדול ובלתי מובן בהצעת החוק כבר הופך לתמונה די מובנת של צריכה.
למרות כמעט 20 שנות הקריירה שלי כמתכנת, למעשה לא הצטלבתי עם מסדי נתונים. לכן, התקנת מסד נתונים חיצוני נראתה כמו משהו כל כך מופרך ובלתי מובן. הכל השתנה - התברר שהברגה של כלי מתאים מתבצעת בכמה לחיצות, ובאמצעות כלי מיוחד, משימת התווים הופכת לקצת יותר קלה.
בכותרת הזכרתי את צריכת החשמל. לצערי, כרגע אני לא יכול לספק שום גרף. מטר SDM120 אחד מת, והשני עמוס כשניגש אליו דרך Modbus. עם זאת, זה לא משפיע על נושא המאמר הזה בשום צורה - הגרפים ייבנו באותו אופן כמו עבור מים.
במאמר זה נתתי את הגישות שניסיתי בעצמי. אין ספק שיש עוד כמה דרכים לארגן איסוף והדמיה של נתונים שאני לא יודע עליהם. ספרו לי על זה בתגובות, אני מאוד אתעניין. אשמח לביקורת בונה ורעיונות חדשים. אני מקווה שהחומר לעיל יעזור גם למישהו.
מקור: www.habr.com
