Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant
Κάθε φορά που λαμβάνω πληρωμή για ρεύμα και νερό, αναρωτιέμαι - η οικογένειά μου καταναλώνει πραγματικά τόσο πολύ; Λοιπόν, ναι, υπάρχει ένα θερμαινόμενο δάπεδο και ένας λέβητας στο μπάνιο, αλλά δεν λειτουργούν ως πυροσβέστες όλη την ώρα. Φαίνεται επίσης να εξοικονομούμε νερό (αν και μας αρέσει επίσης το πιτσίλισμα στο μπάνιο). Πριν από μερικά χρόνια ήδη συνδεδεμένοι μετρητές νερού и ηλεκτρικής ενέργειας σε ένα έξυπνο σπίτι, αλλά εδώ κόλλησαν τα πράγματα. Τα χέρια έφτασαν στην ανάλυση της κατανάλωσης μόλις τώρα, για την οποία, στην πραγματικότητα, αναφέρεται αυτό το άρθρο.

Πρόσφατα άλλαξα στο Home Assistant ως το έξυπνο οικιακό μου σύστημα. Ένας από τους λόγους ήταν απλώς η δυνατότητα οργάνωσης της συλλογής μεγάλου όγκου δεδομένων με τη δυνατότητα εύκολης κατασκευής διαφόρων ειδών γραφημάτων.

Οι πληροφορίες που περιγράφονται σε αυτό το άρθρο δεν είναι νέες, όλα αυτά τα πράγματα κάτω από διαφορετικές σάλτσες έχουν ήδη περιγραφεί στο Διαδίκτυο. Αλλά κάθε άρθρο, κατά κανόνα, περιγράφει μόνο μία προσέγγιση ή πτυχή. Έπρεπε να συγκρίνω όλες αυτές τις προσεγγίσεις και να επιλέξω την καταλληλότερη. Το άρθρο εξακολουθεί να μην παρέχει εξαντλητικές πληροφορίες σχετικά με τη συλλογή δεδομένων, αλλά είναι ένα είδος περίληψης του πώς το έκανα. Επομένως, η εποικοδομητική κριτική και οι προτάσεις για βελτίωση είναι ευπρόσδεκτες.

Δήλωση προβλήματος

Έτσι, ο στόχος της σημερινής άσκησης είναι να ληφθούν όμορφα γραφήματα κατανάλωσης νερού και ηλεκτρικής ενέργειας:

  • Ωριαία για 2 ημέρες
  • Καθημερινά για 2 εβδομάδες
  • (προαιρετικά) εβδομαδιαία και μηνιαία

Υπάρχουν κάποιες δυσκολίες σε αυτό:

  • Τα τυπικά στοιχεία γραφήματος τείνουν να είναι αρκετά φτωχά. Στην καλύτερη περίπτωση, μπορείτε να δημιουργήσετε ένα γραμμικό γράφημα ανά σημεία.

    Εάν κάνετε καλή αναζήτηση, μπορείτε να βρείτε στοιχεία τρίτων που επεκτείνουν τις δυνατότητες του τυπικού γραφήματος. Για τον βοηθό στο σπίτι, κατ 'αρχήν, ένα καλό και όμορφο στοιχείο μίνι κάρτα γραφικών, αλλά είναι επίσης κάπως περιορισμένο:

    • Είναι δύσκολο να ρυθμίσετε τις παραμέτρους του ραβδωτού γραφήματος σε μεγάλα διαστήματα (το πλάτος της ράβδου ορίζεται σε κλάσματα της ώρας, πράγμα που σημαίνει ότι τα διαστήματα μεγαλύτερα από μία ώρα θα οριστούν σε κλασματικούς αριθμούς)
    • Δεν μπορείτε να προσθέσετε διαφορετικές οντότητες σε ένα γράφημα (για παράδειγμα, θερμοκρασία και υγρασία ή να συνδυάσετε ένα γράφημα ράβδων με μια γραμμή)
  • Όχι μόνο ο οικιακός βοηθός χρησιμοποιεί την πιο πρωτόγονη βάση δεδομένων SQLite από προεπιλογή (και εγώ, ο τεχνίτης, δεν κατάλαβα την εγκατάσταση της MySQL ή της Postgres), τα δεδομένα δεν αποθηκεύονται με τον βέλτιστο τρόπο. Έτσι, για παράδειγμα, με κάθε αλλαγή καθεμιάς ακόμη και της μικρότερης ψηφιακής παραμέτρου μιας παραμέτρου, ένα τεράστιο json σε μέγεθος περίπου ένα kilobyte γράφεται στη βάση δεδομένων
    {"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 MB καθημερινά. Σε μια εβδομάδα, το σύστημα μετά βίας θα πεταχτεί και θα γυρίσει και σε ένα μήνα η μονάδα flash θα πεθάνει (στην περίπτωση μιας τυπικής εγκατάστασης οικιακού βοηθού στο raspberry PI) και δεν μπορεί να γίνει λόγος για αποθήκευση δεδομένων για έναν ολόκληρο χρόνο .

  • Εάν είστε τυχεροί, ο ίδιος ο μετρητής σας μπορεί να μετρήσει την κατανάλωση. Μπορείτε να επικοινωνήσετε με τον μετρητή ανά πάσα στιγμή και να ρωτήσετε τι ώρα είναι η συσσωρευμένη τιμή κατανάλωσης. Κατά κανόνα, όλοι οι μετρητές ηλεκτρικής ενέργειας που διαθέτουν ψηφιακή διεπαφή (RS232/RS485/Modbus/Zigbee) παρέχουν μια τέτοια ευκαιρία.

    Ακόμη χειρότερα, εάν η συσκευή μπορεί απλώς να μετρήσει κάποια στιγμιαία παράμετρο (για παράδειγμα, στιγμιαία ισχύ ή ρεύμα) ή απλώς να παράγει παλμούς κάθε Χ βατώρες ή λίτρα. Τότε πρέπει να σκεφτείτε πώς και με τι να το ενσωματώσετε και πού να συσσωρεύσετε αξία. Υπάρχει κίνδυνος να χάσετε την επόμενη αναφορά για οποιονδήποτε λόγο και η ακρίβεια του συστήματος στο σύνολό του εγείρει ερωτήματα. Μπορείτε, φυσικά, να τα εμπιστευτείτε όλα αυτά σε ένα έξυπνο οικιακό σύστημα όπως το home assistant, αλλά κανείς δεν έχει ακυρώσει το σημείο σχετικά με τον αριθμό των καταχωρήσεων στη βάση δεδομένων και οι αισθητήρες δημοσκόπησης περισσότερες από μία φορές το δευτερόλεπτο δεν θα λειτουργούν (περιορισμός του αρχιτεκτονική βοηθός σπιτιού).

Προσέγγιση 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, οι οποίοι συγκεντρώνουν ωριαίες και ημερήσιες μετρήσεις, μηδενίζοντάς τις μετά από μια περίοδο. Εδώ είναι ένα γράφημα της ωριαίας μπαταρίας για μισή ημέρα.

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Ο ωριαίος και ημερήσιος κώδικας γραφήματος για το 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 kb μιας εγγραφής στη βάση δεδομένων. Κάθε βοηθητικός μετρητής δημιουργεί επίσης μια νέα τιμή, η οποία προστίθεται επίσης στη βάση. Αν θέλω να συλλέξω ωριαίες/ημερήσιες/εβδομαδιαίες/μηνιαίες μετρήσεις, ναι, για πολλούς ανυψωτήρες νερού, και ακόμη και να προσθέσω ένα πακέτο ηλεκτρικούς μετρητές, αυτά θα είναι πολλά δεδομένα. Λοιπόν, πιο συγκεκριμένα, δεν υπάρχουν πολλά δεδομένα, αλλά εφόσον ο οικιακός βοηθός γράφει μια δέσμη περιττών πληροφοριών στη βάση δεδομένων, το μέγεθος της βάσης δεδομένων θα αυξηθεί αλματωδώς. Φοβάμαι ακόμη και να υπολογίσω το μέγεθος της βάσης για εβδομαδιαία και μηνιαία γραφήματα.

Επιπλέον, ο ίδιος ο μετρητής χρησιμότητας δεν λύνει το πρόβλημα. Η γραφική παράσταση του μετρητή χρησιμότητας είναι μια μονότονα αυξανόμενη συνάρτηση που επανέρχεται στο 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 είναι να λαμβάνετε τη μέγιστη τιμή μέσα σε κάθε ώρα. Αυτή η παράμετρος είναι που μετατρέπει το γράφημα του πριονωτή σε ράβδους.

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Μην δίνετε προσοχή στη σειρά των στηλών στα αριστερά - αυτή είναι η τυπική συμπεριφορά του στοιχείου εάν δεν υπάρχουν δεδομένα. Αλλά δεν υπήρχαν δεδομένα - ενεργοποίησα μόνο τη συλλογή δεδομένων χρησιμοποιώντας τον βοηθητικό μετρητή πριν από μερικές ώρες μόνο για χάρη αυτού του άρθρου (θα περιγράψω την τρέχουσα προσέγγισή μου λίγο πιο κάτω).

Σε αυτήν την εικόνα, ήθελα να δείξω ότι μερικές φορές η εμφάνιση δεδομένων λειτουργεί και οι ράβδοι αντικατοπτρίζουν πραγματικά τις σωστές τιμές. Αλλά δεν είναι μόνο αυτό. Για κάποιο λόγο, η επισημασμένη στήλη για την περίοδο από τις 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 έχει οριστεί σε interval και η παράμετρος points_per_hour διέπει τα πάντα. Και αυτό είναι ένα άλλο πρόβλημα με αυτό το στοιχείο - το points_per_hour λειτουργεί καλά σε γραφήματα μιας ώρας ή λιγότερο, αλλά αηδιαστικά σε μεγαλύτερα διαστήματα. Για να πάρω λοιπόν μια στήλη σε μια μέρα, έπρεπε να βάλω την τιμή 1/24=0.04166666. Δεν μιλάω για εβδομαδιαία και μηνιαία διαγράμματα.

Προσέγγιση 2

Ενώ εξακολουθούσα να καταλαβαίνω τον οικιακό βοηθό, έπεσα πάνω σε αυτό το βίντεο:


Ο σύντροφος συλλέγει δεδομένα κατανάλωσης από διάφορους τύπους υποδοχών Xiaomi. Το έργο του είναι λίγο πιο απλό - απλώς εμφανίστε την αξία της κατανάλωσης για σήμερα, χθες και για τον μήνα. Δεν απαιτούνται γραφήματα.

Ας αφήσουμε κατά μέρος τα επιχειρήματα σχετικά με τη χειροκίνητη ενσωμάτωση των στιγμιαίων τιμών ισχύος - έγραψα ήδη για την "ακρίβεια" αυτής της προσέγγισης παραπάνω. Δεν είναι σαφές γιατί δεν χρησιμοποίησε τις συσσωρευμένες αξίες κατανάλωσης, οι οποίες συλλέγονται ήδη από το ίδιο κατάστημα. Κατά τη γνώμη μου, η ενσωμάτωση μέσα στο κομμάτι σιδήρου θα λειτουργήσει καλύτερα.

Από το βίντεο, θα πάρουμε την ιδέα της μη αυτόματης μέτρησης της κατανάλωσης για μια περίοδο. Για έναν άνδρα, λαμβάνονται υπόψη μόνο οι αξίες για το σήμερα και το χθες, αλλά θα προχωρήσουμε παρακάτω και θα προσπαθήσουμε να σχεδιάσουμε ένα γράφημα. Η ουσία της προτεινόμενης μεθόδου στην περίπτωσή μου είναι η εξής.

Θα δημιουργήσουμε μια μεταβλητή 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

Μοιάζει με αυτό:

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Κατ 'αρχήν, αυτό είναι ήδη αυτό που χρειάζεστε. Το πλεονέκτημα αυτής της μεθόδου είναι ότι τα δεδομένα παράγονται μία φορά ανά διάστημα. Εκείνοι. συνολικά 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 ώρα))
  • Το ερώτημα θα βγάλει όλα τα δεδομένα από τη μέτρηση'a homeassistant.autogen.l (λίτρα), συμπεριλαμβανομένων των μετρήσεων κρύου και ζεστού νερού
  • Τα συγκεντρωτικά δεδομένα θα ομαδοποιηθούν κατά entity_id, το οποίο θα δημιουργήσει ξεχωριστές τιμές για το κρύο και το ζεστό νερό.
  • Δεδομένου ότι ο μετρητής των λίτρων είναι μια μονότονα αυξανόμενη ακολουθία μέσα σε κάθε ώρα, θα πρέπει να λάβετε τη μέγιστη τιμή, επομένως η συγκέντρωση θα πραγματοποιηθεί από τη συνάρτηση max(value)
  • Η νέα τιμή θα γραφτεί στο homeassistant.month.water_meter_hour όπου month είναι το όνομα της πολιτικής διατήρησης με περίοδο διατήρησης ενός μήνα. Επιπλέον, τα δεδομένα για το κρύο και το ζεστό νερό θα διασκορπιστούν σε ξεχωριστές εγγραφές με το αντίστοιχο entity_id και την τιμή στο πεδίο value

Τη νύχτα ή όταν δεν είναι κανείς στο σπίτι, δεν υπάρχει κατανάλωση νερού και κατά συνέπεια δεν υπάρχουν νέα ρεκόρ ούτε στο homeassistant.autogen.l. Για να αποφύγετε τις τιμές που λείπουν σε κανονικά ερωτήματα, μπορείτε να χρησιμοποιήσετε το fill(previous). Αυτό θα αναγκάσει το InfluxDB να χρησιμοποιήσει την τιμή της προηγούμενης ώρας.

Δυστυχώς, το συνεχές ερώτημα έχει μια ιδιαιτερότητα: το τέχνασμα συμπλήρωσης(προηγούμενο) δεν λειτουργεί και οι εγγραφές απλώς δεν δημιουργούνται. Επιπλέον, πρόκειται για κάποιο είδος ανυπέρβλητου προβλήματος, το οποίο συζητείται για περισσότερο από ένα χρόνο. Θα ασχοληθούμε με αυτό το πρόβλημα αργότερα και αφήστε το fill(previous) στο συνεχές ερώτημα να υπάρχει - δεν παρεμβαίνει.

Ας ελέγξουμε τι συνέβη (φυσικά, πρέπει να περιμένετε μερικές ώρες):

> 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 το πρωί απλά δεν υπάρχουν εγγραφές - αυτό είναι το χαρακτηριστικό της συνεχούς αναζήτησης.

Όπως μπορείτε να δείτε, η συγκεντρωτική τιμή είναι επίσης μια μονότονα αυξανόμενη ακολουθία, μόνο που οι καταχωρήσεις είναι λιγότερο συχνές - μία φορά την ώρα. Αλλά αυτό δεν είναι πρόβλημα - μπορούμε να γράψουμε ένα άλλο ερώτημα που θα εξαγάγει τα σωστά δεδομένα για το γράφημα.

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. Θα αναδημιουργήσουμε αυτά τα δεδομένα εκτελώντας το ερώτημα με GROUP BY time(1h). Αυτή τη φορά, το 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, ανοίξτε έναν υπάρχοντα (ή δημιουργήστε έναν νέο) πίνακα εργαλείων, δημιουργήστε έναν νέο πίνακα. Οι ρυθμίσεις του γραφήματος θα είναι οι εξής.

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Θα εμφανίσω δεδομένα κρύου και ζεστού νερού στο ίδιο γράφημα. Το αίτημα είναι ακριβώς το ίδιο με αυτό που περιέγραψα παραπάνω.

Οι παράμετροι της οθόνης ρυθμίζονται ως εξής. Για μένα θα είναι ένα γράφημα με γραμμές (γραμμές), που πηγαίνει σε βήματα (σκάλες). Η παράμετρος Stack θα εξηγηθεί παρακάτω. Υπάρχουν μερικές ακόμη επιλογές εμφάνισης παρακάτω, αλλά δεν είναι τόσο ενδιαφέρουσες.

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Για να προσθέσετε το γράφημα που προκύπτει στον οικιακό βοηθό, πρέπει:

  • βγείτε από τη λειτουργία επεξεργασίας γραφήματος. Για κάποιο λόγο, οι σωστές ρυθμίσεις κοινής χρήσης γραφήματος προσφέρονται μόνο από τη σελίδα του πίνακα ελέγχου
  • Κάντε κλικ στο τρίγωνο δίπλα στο όνομα του γραφήματος, επιλέξτε κοινή χρήση από το μενού
  • Στο παράθυρο που ανοίγει, μεταβείτε στην καρτέλα ενσωμάτωσης
  • Καταργήστε την επιλογή του τρέχοντος εύρους χρόνου - θα ορίσουμε το χρονικό εύρος μέσω 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 ημέρες, οπότε σχεδιάζεται μόνο ένα γράφημα κρύου νερού.

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Δεν έχω αποφασίσει μόνος μου ποιο γράφημα μου αρέσει περισσότερο, μια γραμμή βημάτων ή πραγματικές μπάρες. Επομένως, θα δώσω απλώς ένα παράδειγμα ημερήσιου προγράμματος κατανάλωσης, μόνο αυτή τη φορά σε μπαρ. Τα ερωτήματα δημιουργούνται με τον ίδιο τρόπο που περιγράφηκε παραπάνω. Οι επιλογές εμφάνισης είναι:

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Αυτό το γράφημα μοιάζει με αυτό:

Έξυπνο σπίτι: Καταγραφή της κατανάλωσης νερού και ηλεκτρικής ενέργειας στο Home Assistant

Λοιπόν, σχετικά με την παράμετρο Stack. Σε αυτό το γράφημα, μια μπάρα κρύου νερού σχεδιάζεται πάνω από μια ζεστή ράβδο. Το συνολικό ύψος αντιστοιχεί στη συνολική κατανάλωση κρύου και ζεστού νερού για την περίοδο.

Όλα τα γραφήματα που εμφανίζονται είναι δυναμικά. Μπορείτε να μετακινήσετε το ποντίκι πάνω από το σημείο ενδιαφέροντος και να δείτε τις λεπτομέρειες και την τιμή σε ένα συγκεκριμένο σημείο.

Δυστυχώς, δεν ήταν χωρίς μια-δυο μύγα στην αλοιφή. Σε ένα γράφημα ράβδων (σε αντίθεση με το γράφημα με τις βηματικές γραμμές), η μέση της ράβδου δεν είναι στη μέση της ημέρας, αλλά στις 00:00. Εκείνοι. το αριστερό μισό της ράβδου τραβιέται στη θέση της προηγούμενης ημέρας. Έτσι τα διαγράμματα για το Σάββατο και την Κυριακή είναι σχεδιασμένα λίγο αριστερά από τη γαλαζωπή ζώνη. Μέχρι που κατάλαβα πώς να το κερδίσω.

Ένα άλλο πρόβλημα είναι η αδυναμία να λειτουργήσει σωστά με μηνιαία διαστήματα. Το γεγονός είναι ότι η διάρκεια της ώρας / ημέρας / εβδομάδας είναι σταθερή, αλλά η διάρκεια του μήνα είναι διαφορετική κάθε φορά. Το InfluxDB μπορεί να λειτουργήσει μόνο με ίσα διαστήματα. Μέχρι στιγμής, το μυαλό μου ήταν αρκετό για να ορίσει ένα σταθερό διάστημα 30 ημερών. Ναι, το γράφημα θα επιπλέει λίγο κατά τη διάρκεια του έτους και οι ράβδοι δεν θα αντιστοιχούν ακριβώς στους μήνες. Αλλά επειδή αυτό το πράγμα είναι ενδιαφέρον για μένα μόνο ως μετρητής οθόνης, είμαι εντάξει με αυτό.

Βλέπω τουλάχιστον δύο λύσεις:

  • Να σκοράρεις σε μηνιαία γραφήματα και να περιοριστείς σε εβδομαδιαία. 52 εβδομαδιαία μπαρ σε ένα χρόνο φαίνονται αρκετά καλά
  • Θεωρήστε την ίδια τη μηνιαία κατανάλωση ως μέθοδο Νο. 2 και χρησιμοποιήστε τη γραφάνα μόνο για όμορφα γραφήματα. Είναι μια αρκετά ακριβής λύση. Μπορείτε ακόμη και να επικαλύψετε γραφήματα για το προηγούμενο έτος για σύγκριση - η grafana μπορεί να το κάνει αυτό.

Συμπέρασμα

Δεν ξέρω γιατί, αλλά μου αρέσουν αυτού του είδους τα charts. Δείχνουν ότι η ζωή είναι σε πλήρη εξέλιξη και όλα αλλάζουν. Χθες ήταν πολλά, σήμερα είναι λίγα, αύριο θα υπάρξει κάτι άλλο. Απομένει να εργαστούμε με τα νοικοκυριά στο θέμα της κατανάλωσης. Αλλά ακόμη και με τις τρέχουσες ορέξεις, μόνο ένα μεγάλο και ακατανόητο νούμερο στο λογαριασμό μετατρέπεται ήδη σε μια αρκετά κατανοητή εικόνα της κατανάλωσης.

Παρά την σχεδόν 20ετή καριέρα μου ως προγραμματιστής, ουσιαστικά δεν διασταυρώθηκα με βάσεις δεδομένων. Επομένως, η εγκατάσταση μιας εξωτερικής βάσης δεδομένων φαινόταν σαν κάτι τόσο παράλογο και ακατανόητο. Τα πάντα έχουν αλλάξει το παραπάνω άρθρο - αποδείχθηκε ότι το βίδωμα ενός κατάλληλου εργαλείου γίνεται με μερικά κλικ και με ένα εξειδικευμένο εργαλείο, το έργο της γραφικής παράστασης γίνεται λίγο πιο εύκολο.

Στον τίτλο ανέφερα την κατανάλωση ρεύματος. Δυστυχώς, αυτή τη στιγμή δεν μπορώ να δώσω κανένα γράφημα. Ένας μετρητής SDM120 είναι νεκρός και ο άλλος είναι buggy όταν προσεγγίζεται μέσω Modbus. Ωστόσο, αυτό δεν επηρεάζει με κανέναν τρόπο το θέμα αυτού του άρθρου - τα γραφήματα θα κατασκευαστούν με τον ίδιο τρόπο όπως και για το νερό.

Σε αυτό το άρθρο, έχω δώσει εκείνες τις προσεγγίσεις που έχω δοκιμάσει ο ίδιος. Σίγουρα υπάρχουν κάποιοι άλλοι τρόποι οργάνωσης της συλλογής και οπτικοποίησης δεδομένων που δεν γνωρίζω. Πείτε μου για αυτό στα σχόλια, θα με ενδιαφέρει πολύ. Θα χαρώ για εποικοδομητική κριτική και νέες ιδέες. Ελπίζω το παραπάνω υλικό να βοηθήσει και κάποιον.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο