Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Varmestyring med bayesian sensor


stigvi

Anbefalte innlegg

Tenkte å beskrive min løsning på varmestyring. Når en får mange nok parametre å ta hensyn til så kan ordinær tilstandsstyring bli ganske kompleks. Styring av varme gjøres ofte basert på status om en er hjemme, strømpris, tid på døgn, temperatur, dører eller vinduer åpne, ønske om å skru på varme når en snart er hjemme (for å slippe å komme hjem til kaldt hus) osv. I tillegg ønsker en forskjellig styring på de forskjellige varmekildene.

Alt dette gjorde at jeg så mørkt på å lage logikk som skal styre dette. Så jeg endte opp med å bruke noen bayesiske sensorer. Da koker det ned til å enkelt beskrive hvor mye jeg ønsker at varmen skal slås på i de forskjellige tilstandene isolert sett.

Bayesisk sensor brukes vanligvis i hjemmeautomasjon til å avgjøre om en er hjemme eller ikke basert på forskjellige innsignaler. Den bayesiske sensoren i Home Assistant er binær, dvs at den har en tilstand som er av eller på (eller hjemme og borte). Mine varmekilder har 3 tilstander jeg ønsket å styre (borte, økonomi eller komfort som hver har sine temperaturer en ønsker å oppnå). Home Assistant sin bayesisk sensor har en attributt som angir kalkulert sannsynlighet og denne bruker jeg til å styre varmen. Er sannsynligheten for at jeg ønsker varme mindre enn 10% så settes varmekilden i "borte" modus. Er sannsynligheten mellom 10% og 50% så settes de i økonomi og ved mer enn 50% så settes de i komfortmodus.

Dette løses ved å hente ut sannsynligheten med dette:

 

- platform: template
    sensors:
      varmekabel_probability:
        friendly_name: "Varmekabel sannsynlighet"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('binary_sensor.varmekabler', 'probability') }}"

og følgende automatisering

 

- id: varmekabler_eco
  alias: Setter varmekabler i øko
  trigger:
  - entity_id: sensor.varmekabel_probability
    platform: numeric_state
    above: 0.1
    below: 0.5
    for:
      seconds: 20
  action:
  - alias: ''
    data:
      entity_id:
      - climate.bad_u_etg
      - climate.bad_1_etg
      - climate.gang_u_etg
      - climate.vaskerom
      preset_mode: eco
    service: climate.set_preset_mode

Jeg har lagt inn 20 sekund forsinkelse her fordi ovnene liker ikke å bli mast på for ofte. Forsinkelsen kunne vært kortere som f.eks. 2s. Varme i garasjen har en forsinkelse på 2 minutt slik at kortvarig bruk av garasjeport ikke fører til endring på ovnen der.


Så til selve den bayesiske sensoren:

 

binary_sensor:
    - platform: bayesian
      name: 'Varmekabler'
      prior: 0.35
      probability_threshold: 0.5
      #device_class: presence
      observations:
        - entity_id: input_boolean.travel_enabled
          prob_given_true: 0.001
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.noen_er_hjemme
          prob_given_true: 0.7
          platform: 'state'
          to_state: 'on'
        - entity_id: input_boolean.sleeptime
          prob_given_true: 0.32
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.soonsleeptime
          prob_given_true: 0.32
          platform: 'state'
          to_state: 'on'
        - entity_id: input_boolean.soonhome
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.preheat_day
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.preheat_night
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.extended_preheat
          prob_given_true: 0.6
          platform: 'state'
          to_state: 'on'
        - prob_given_true: 0.6
          platform: 'template'
          value_template: >-
            {{ float(states('sensor.electricity_price_orstad'))
            < (float(state_attr('sensor.electricity_price_orstad', 'max_price'))
            - float(state_attr('sensor.electricity_price_orstad', 'min_price'))) * 0.3
            + float(state_attr('sensor.electricity_price_orstad', 'min_price')) }}
        - prob_given_true: 0.4
          platform: 'template'
          value_template: >-
            {{ float(states('sensor.electricity_price_orstad'))
            > (float(state_attr('sensor.electricity_price_orstad', 'max_price'))
            - float(state_attr('sensor.electricity_price_orstad', 'min_price'))) * 0.95
            + float(state_attr('sensor.electricity_price_orstad', 'min_price')) }}

Jeg starter med å si at normal tilstand er 35% som betyr økonomimodus på varmekildene. På en bayesisk sensor er det slik at innganger som bidrar med mer enn 50% gjør at sannsynligheten for på/hjemme/sann/varme/osv går opp. Innganger som bidrar med mindre enn 50% gjør at den totale sannsynligheten går ned. Så når jeg har en bryter som sier jeg er på ferie og setter sannsynligheten til 0.001 så går sannsynligheten for at jeg ønsker varme så kraftig ned at ingen andre innganger klarer å få den over 10% som var grensen for bortemodus. Resten av inngangene er vel stort sett selvforklarende. Varmen settes i de forkjellige modusene ut i fra om jeg er hjemme, om det er sovetid osv. Nederst har jeg satt opp ønsket mitt ut i fra strømpris lav eller høy.


To andre bayesiske sensorer hos meg ser slik ut:
 

- platform: bayesian
      name: 'Panelovner garasje'
      prior: 0.35
      probability_threshold: 0.5
      #device_class: presence
      observations:
        - entity_id: binary_sensor.garasjeport
          prob_given_true: 0.001
          platform: 'state'
          to_state: 'on'
        - entity_id: input_boolean.garage_comfort
          prob_given_true: 0.7
          platform: 'state'
          to_state: 'on'

    - platform: bayesian
      name: 'Panelovner tvstue'
      prior: 0.35
      probability_threshold: 0.5
      #device_class: presence
      observations:
        - entity_id: input_boolean.travel_enabled
          prob_given_true: 0.001
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.noen_er_hjemme
          prob_given_true: 0.7
          platform: 'state'
          to_state: 'on'
        - entity_id: input_boolean.sleeptime
          prob_given_true: 0.32
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.soonsleeptime
          prob_given_true: 0.32
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.preheat_day
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'
        - entity_id: input_boolean.soonhome
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'
        - entity_id: binary_sensor.heatlimit_morning
          prob_given_true: 0.4
          platform: 'state'
          to_state: 'on'

Den for garasje er svært enkel og styres kun ut i fra 2 innganger. Panelovnene inneholder mer, men i motsetning til varmekablene så er ikke strømpris med som en inngang på disse. Men strømpris kunne fint vært med, men da med sannsynlighet som lå nærmere 50% i forhold til det varmekablene har. Dess lenger fra midtpunktet på 50% en inngang bidrar med, dess mer påvirkes utgangen.

Det som kompliseres er å finne riktige sannsynligheter på inngangene. For å gjøre denne jobben lettere, laget jeg et excel regneark der jeg kan simulere hvor mye hver inngang påvirker utgangen. Kan gjerne dele dette regnearket .....

Så det var min løsning. Sikkert ikke veldig unikt, men jeg tror at dette i det minste kan være til bittelitt nytte for de som eventuelt er i startgropa for å sette opp et system.

  • Like 4
Lenke til kommentar
Del på andre sider

Det var en interessant tilnærming! Ikke vanskelig å implementere, men gir fort hakket mer "smarthet".

 

Er sannsynlighetene dine noe du har tippet selv? (de ser ikke akkurat beregnet ut)?

EDIT: Må lese hele posten nøye.

 

15 minutter siden, stigvi skrev:

Kan gjerne dele dette regnearket .....

Ja takk! Det hadde vært spennende! :) 

Lenke til kommentar
Del på andre sider

41 minutter siden, stigvi skrev:

Så det var min løsning. Sikkert ikke veldig unikt, men jeg tror at dette i det minste kan være til bittelitt nytte for de som eventuelt er i startgropa for å sette opp et system.

Spennende løsning. Gi gjerne tilbakemelding på hvordan det fungerer i levende live etter litt tid.

Lenke til kommentar
Del på andre sider

I mitt system bruker jeg innganger til styringen som f.eks. dette

- entity_id: binary_sensor.preheat_day
          prob_given_true: 0.66
          platform: 'state'
          to_state: 'on'

preheat_day er en sensor som fører til at varmen slås på automatisk før vi er hjemme. Den er kun tidsstyrt og jeg tar den (og de andre) med her for eksempelets skyld
 

binary_sensor:
    - platform: template
      sensors:
        worktime:
          entity_id: sensor.time_online
          value_template: >-
            {{ now().hour*3600+now().minute*60 + 2400 >= (state_attr("input_datetime.worktime_start", "timestamp") | int)
              and now().hour*3600+now().minute*60 - 1200 < (state_attr("input_datetime.worktime_end", "timestamp") | int)
              and states("binary_sensor.workday_sensor") == "on"}}
        soonsleeptime:
          entity_id: sensor.time_online
          value_template: >-
            {{ (now().hour*3600+now().minute*60 + 60*(states("input_number.heatingtime") | int) >=      (state_attr("input_datetime.normal_bedtime", "timestamp") | int)
                or now().hour < 4)
                    and now().strftime("%w") != "5"
                    and now().strftime("%w") != "6"
                    and states("input_boolean.sleeptime") == "off" }}
        preheat_day:
          entity_id: sensor.time_online
          value_template: >-
            {{ now().hour*3600+now().minute*60 + 60*(states("input_number.heatingtime") | int) >= (state_attr("input_datetime.worktime_end", "timestamp") | int)
              and now().hour*3600+now().minute*60 - 3600 < (state_attr("input_datetime.worktime_end", "timestamp") | int)
              and states("binary_sensor.workday_sensor") == "on" }}
        preheat_night:
          entity_id: sensor.time_online
          value_template: >-
            {{ (now().hour*3600+now().minute*60 + 120*(states("input_number.heatingtime") | int) >= (state_attr("input_datetime.wakeuptime", "timestamp") | int)
              and now().hour*3600+now().minute*60 - 600 < (state_attr("input_datetime.wakeuptime", "timestamp") | int)
              and states("binary_sensor.workday_sensor") == "on")
              or
              (now().hour >= 6
              and now().hour < 9
              and states("binary_sensor.workday_sensor") == "off") }}
        heatlimit_morning:
          entity_id: sensor.time_online
          value_template: >-
            {{ now().hour*3600+now().minute*60 + 900 >= (state_attr("input_datetime.wakeuptime", "timestamp") | int)
                and now().hour*3600+now().minute*60 < (state_attr("input_datetime.worktime_start", "timestamp") | int)
                and states("binary_sensor.workday_sensor") == "on" }}
        extended_preheat:
          entity_id: sensor.time_online
          value_template: >-
            {{ (now().hour*3600+now().minute*60 + 120*(states("input_number.heatingtime") | int) >= (state_attr("input_datetime.worktime_end", "timestamp") | int)
              and now().hour*3600+now().minute*60 + 60*(states("input_number.heatingtime") | int) < (state_attr("input_datetime.worktime_end", "timestamp") | int)
              and states("binary_sensor.workday_sensor") == "on")
              or
              (now().hour*3600+now().minute*60 + 180*(states("input_number.heatingtime") | int) >= (state_attr("input_datetime.wakeuptime", "timestamp") | int)
              and now().hour*3600+now().minute*60 + 120*(states("input_number.heatingtime") | int) < (state_attr("input_datetime.wakeuptime", "timestamp") | int)
              and states("binary_sensor.workday_sensor") == "on") 
              or
              (now().hour >= 5
              and now().hour < 6
              and states("binary_sensor.workday_sensor") == "off") }}

Og da har jeg synliggjort en svakhet med Home Assistant. Beregning av tidspunkter og i det hele tatt, styring basert på tidspunkt, blir fort komplisert og uoversiktlig. Men jeg har i det minste klart å separere de forskjellige delene godt. Jeg trenger ikke rote med en kompleks varmestyringslogikk for å endre på tidstyringen når jeg setter forskjellige sensorer av eller på og deretter bruker sensoren som inngang til den bayesiske sensoren

Lenke til kommentar
Del på andre sider

1 minutt siden, Moskus skrev:

Oppfølgingsspørsmål: Dette er jo i praksis kun statistikk og sannsynlighetsberegning, men har du @stigvi en følelse av hvor godt du treffer?

Har du plottet sannsynligheten for borte/økonomi/komfort over døgnet?

Jeg følger jo med ? Det dreier seg om å sette riktige sannsynligheter på inngangene. Slik at en inngang ikke bidrar for lite til å ha noen virkning eller bidrar for mye og overstyrer andre innganger. Sånn sett er simulering med regnearket et must. Nå treffer det 100% prosent hos meg, men av og til stusser jeg på hvorfor varmen står på når den kanskje skulle vært av fordi jeg har glemt at strømpris er en faktor.

Lenke til kommentar
Del på andre sider

9 minutter siden, Moskus skrev:

Er skalaen 0-1 eller er det faktisk 0.35% sjanse for at varmekabelen skal gå på?

(Høres ut som en enhetsfeil... ;) )

Er en feil, ja. Det skal være 35%

(Har ikke funnet en god måte å skalere sensorer på i forbindelse med visning i brukergrensesnittet)

  • Like 1
Lenke til kommentar
Del på andre sider

image.png.28f0b0ecdb84db97d5ffae69f7e63dd1.png

 

Det er egentlig ganske enkel matematikk bak dette. Hver kolonne (B til G) er like og hvis en vil ha flere "innganger" så er det bare å legge til videre etter G. Prior på B må legges inn manuelt og er samme som prior konfigurasjonen på bayesian sensor. Prior på C hentes fra probability på B, altså foregående.

Så det en endrer er B7 og rad 8. Utgang er G12 hvis en bruker alle 6 kolonnene.

Bayesian.xlsx

  • Like 1
Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.