actor.py 6.12 KB
Newer Older
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#!/usr/bin/python

import json
import time
from datetime import datetime
import paho.mqtt.client as paho
import os
import numbers
import parse
from urllib.request import urlopen

broker="localhost"

mlast = {}

Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
def on_connect(client, userdata, flags, rc):
  if rc==0:
    print("MQTT connected OK. Return code", rc)
    client.subscribe("homie/i2c/1w/000006BB499E28") # Warmwasser
    client.subscribe("homie/batterie/haus/gesamt")
    client.subscribe("homie/batterie/pv/pv2")
    client.subscribe("homie/batterie/batterie/soc")
    client.subscribe("homie/lueftung/#")
    client.subscribe("homie/batterie/pv/gesamt")
    client.subscribe("homie/+/ac/leistung")
    client.subscribe("homie/fsrmaster2/+/power")
    print("MQTT: Subscribed to all topics")
  else:
    print("Bad connection. Return code=",rc)

def on_disconnect(client, userdata, rc):
  if rc != 0:
    print ("Unexpected MQTT disconnection. Will auto-reconnect")

Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
35 36 37 38 39 40 41 42 43 44
def on_message(client, userdata, message):
    global mlast
    t = datetime.now()
    t = time.mktime(t.timetuple()) + t.microsecond / 1E6
    m = message.payload.decode("utf-8")
#    print("received:",str(m), message.topic)

    # the lambda in loads is for converting the object name into a int, if appropiate
    j = json.loads(m, object_hook=lambda d: {int(k) if k.lstrip('-').isdigit() else k: v for k, v in d.items()})
#    print ("Topic:",message.topic,"JSON",j)
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
45
    if type(j) is not dict: #anpassen, falls es keine Zeitinfo hat
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
46
      j={'v':j,'time':t}
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
47 48
    if t-j['time'] > 10: # corrects the time of too much in the future
      j['time'] = t
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
49 50 51 52 53 54 55

    mlast[message.topic] = j


client= paho.Client("actor")

client.on_message=on_message
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
56 57
client.on_connect = on_connect
client.on_disconnect = on_disconnect
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
58 59 60 61 62 63

print("connecting to broker ",broker)
client.connect(broker)
client.loop_start() #start loop to process received messages in separate thread
print ("MQTT Loop started.")

Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
64
# Test, ob die angegebenen MQTT-Variablen: vorhanden sind und Zahlenwerte haben und nicht zu alt sind
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
65 66 67 68 69 70
# Aufruf: if checkValuesOK(['homie/fsrmaster2/stromz2/power','homie/fsrmaster2/stromz0/power']):
def checkValuesOK(alist):
  r = True
  global mlast
  for v in alist:
    w = mlast.get(v)
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
71
    if w and isinstance(w['v'], numbers.Real) and time.time()-w['time'] < 60*5:
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
72 73 74 75 76
      pass
    else:
      r = False
  return r

Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
77 78
#0:400W, 1:700W, 2:700W
Heizstaebe = [{'P':0,'time':0,'SenderID':77135873,'Pmax':400}, {'P':0,'time':0,'SenderID':77135874,'Pmax':700}, {'P':0,'time':0,'SenderID':77135875,'Pmax':700}]
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
79
while True:
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
  SummeAktHeizleistung=0
  for i in range(len(Heizstaebe)):
    if time.time()-Heizstaebe[i]['time'] > 30: Heizstaebe[i]['P']=0
    SummeAktHeizleistung += Heizstaebe[i]['P']

  if checkValuesOK(['homie/i2c/1w/000006BB499E28', 'homie/fsrmaster2/stromz0/power', 'homie/batterie/batterie/soc', 'homie/batterie/pv/gesamt']):
    print ("SummeAktHeizleistung:",SummeAktHeizleistung,"SOC",mlast['homie/batterie/batterie/soc']['v'],"PV:",mlast['homie/batterie/pv/gesamt']['v'],"Z0:",mlast['homie/fsrmaster2/stromz0/power']['v'],"Wassertemp ("+str(mlast['homie/i2c/1w/000006BB499E28']['v'])+"): ",end='')
    if mlast['homie/i2c/1w/000006BB499E28']['v'] <= 60:
      if mlast['homie/batterie/batterie/soc']['v']==100 or mlast['homie/batterie/pv/gesamt']['v']>4000:
        print("Heizen! ", end='')
        PVLeistung = mlast['homie/batterie/pv/gesamt']['v']
        VerbleibendeLeistung = -1*mlast['homie/fsrmaster2/stromz0/power']['v']+SummeAktHeizleistung
        if mlast['homie/i2c/1w/000006BB499E28']['v'] >59:
          if mlast['homie/i2c/1w/000006BB499E28']['v'] >=60:
            VerbleibendeLeistung=150 if VerbleibendeLeistung>150 else VerbleibendeLeistung
          elif mlast['homie/i2c/1w/000006BB499E28']['v'] >59.75:
            VerbleibendeLeistung=200 if VerbleibendeLeistung>200 else VerbleibendeLeistung
          else:
            VerbleibendeLeistung=750 if VerbleibendeLeistung>750 else VerbleibendeLeistung
          print("Heizleistung begrenzt auf:",VerbleibendeLeistung)
        print("Verteilen:", VerbleibendeLeistung, end='')
        if PVLeistung < VerbleibendeLeistung: VerbleibendeLeistung = PVLeistung # Abfrage zur Vermeidung, dass auf kurze Leistungsspitzen reagiert wird
        if VerbleibendeLeistung > 0:
          for i in range(1,len(Heizstaebe)): #Switch on FSR14-2x
            if VerbleibendeLeistung>Heizstaebe[i]['Pmax']:
              client.publish("homie/fsr-ww-control/wwHeizstab/relais/stab"+str(i+1)+"/set", 1)
#              html = urlopen("http://dom/changeStatus.php?newQ=-1&ActiveTab=&SenderID="+str(Heizstaebe[i]['SenderID'])+"&Data=100", timeout = 1)
              Heizstaebe[i]['P']=700
              VerbleibendeLeistung -= Heizstaebe[i]['P']
              Heizstaebe[i]['time']=time.time()
              #print (html.read())
          for i in range(1): #Switch on FUD14
            if VerbleibendeLeistung>40:
              HeizProzent = round(VerbleibendeLeistung / 4) if VerbleibendeLeistung < 400 else 100
              client.publish("homie/fsr-ww-control/wwHeizstab/dimmer/stab1/set", HeizProzent/100)
#              html = urlopen("http://dom/changeStatus.php?newQ=-1&ActiveTab=&SenderID="+str(Heizstaebe[i]['SenderID'])+"&Data="+str(HeizProzent), timeout = 1)
              Heizstaebe[i]['P']=HeizProzent*4
              VerbleibendeLeistung -= Heizstaebe[i]['P']
              Heizstaebe[i]['time']=time.time()
              print("HeizProzent",HeizProzent)
          print("VerbleibendeLeistung",VerbleibendeLeistung)
        else:
          print("Aber nicht genug Sonnenpower vorhanden.")
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
123
      else:
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
124
        print("Batterie entweder nicht voll oder P(PV)<4kW.")
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
125 126 127 128 129 130 131 132 133
    else:
      print("nicht weiter heizen, heiß genug.")

  if checkValuesOK(['homie/fsrmaster2/stromz0/power','homie/batterie/pv/gesamt']):
    client.publish("homie/check/haus/diff", mlast['homie/batterie/pv/gesamt']["v"]+mlast['homie/fsrmaster2/stromz0/power']["v"])

  if checkValuesOK(['homie/pv1/ac/leistung','homie/pv3/ac/leistung','homie/pv4/ac/leistung']):
    client.publish("homie/check/pv/power", mlast['homie/pv1/ac/leistung']["v"] +mlast['homie/pv3/ac/leistung']["v"] +mlast['homie/pv4/ac/leistung']["v"])

Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
134
  time.sleep(5)
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
135 136 137 138

#client.loop_forever()

client.disconnect()
Peter-Bernd Otte's avatar
Peter-Bernd Otte committed
139
client.loop_stop()