#!/usr/bin/python # # Copyright 2021 HiveMQ GmbH # #_________________________________________________ MOD KLL 12.8.2022 #_________________________________________________ rev 2 13.8.2022 make JSON #_________________________________________________ rev 3 emulate a smart PowerSupply what #_________________________________________________ sends AC V A W and get remote DC Volt setpoint and On Off #_________________________________________________ rev 3.1 doc style, timer AC_Volt = 233.5 #_________________________________ Power Supply setting DC_Volt = 15.0 #__________________________________ == MQTT node red dashboard setpoint 0 .. 15 DC_OHM = 1.0 DC_Amp = 0.0 #___________________________________ = DC Volt / DC OHM * ( 0 || 1 ) PS On Off DC_Watt = 0.0 #___________________________________ = DC Volt * DC Amp PS_eff = 1.15 #___________________________________ for back calculation AC PS_run = 1.0 #___________________________________ == or 0.0 from MQTT node red dashboard AC_Watt = 0.0 #___________________________________ = DC Watt * 1.15 ( about PS_efficiency ) AC_Amp = 0.0 #___________________________________ = AC Watt / AC Volt count = 0 #_______________________________________ dynamic content counter DEBUG = False #___________________________________ print and use 10 sec reporting repsec = 60.0 #0 #____________________________________ report ever 10 min AC V A W via KLL/rpi2/getvals replast = 0.0 #_________________________________________________ and listen to MQTT KLL/rpi2/setvals : dashboard setpoints OnOff and DC Volt changes import time import json import sys, getopt import paho.mqtt.client as paho client = paho.Client() from paho import mqtt import credentials #______________________________ pack connection data at external file #_________________________________________________ setting callbacks for different events to see if it works, print the message etc. def on_connect(client, userdata, flags, rc, properties=None): print("CONNACK received with code %s." % rc) def on_disconnect(client, userdata,rc=0): print("DisConnected result code "+str(rc)) client.loop_stop() #_________________________________________________ with this callback you can see if your publish was successful def on_publish(client, userdata, mid, properties=None): print("send: " + str(mid)) #_________________________________________________ print which topic was subscribed to def on_subscribe(client, userdata, mid, granted_qos, properties=None): print("Subscribed: " + str(mid) + " " + str(granted_qos)) #_________________________________________________ print message, useful for checking if it was successful def on_message(client, userdata, msg): global DC_Volt, PS_run print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload)) #_____________________________________________ KLL/RPI2/setvals 1 b'{"userVolt": 7 }' #_____________________________________________ KLL/RPI2/setvals 1 b'{"userPower":0}' setvals = json.loads(msg.payload) # string to JSON if ( b'"userVolt"' in msg.payload ): DC_Volt = setvals["userVolt"] # JSON to PYTHON or key error if ( b'"userPower"' in msg.payload ): PS_run = setvals["userPower"] if DEBUG: print(DC_Volt, PS_run) def calcPS(): #___________________________________ electric simulation calc backwards from DC Volt to AC consumption global count global DC_Volt, DC_OHM, DC_Amp, DC_Watt, AC_Volt, AC_Amp, AC_Watt, PS_eff, PS_run DC_Amp = DC_Volt * PS_run / DC_OHM DC_Watt = DC_Volt * DC_Amp AC_Watt = DC_Watt * PS_eff AC_Amp = AC_Watt / AC_Volt #if DEBUG: print( PS_run, DC_Volt, DC_Amp, DC_Watt, AC_Volt, AC_Amp, AC_Watt ) mJSON = "{ \"rec\":"+str(count) mJSON += ",\"power\":{" mJSON += "\"Volt\":"+"{:.2f}".format(AC_Volt) mJSON += ",\"Amp\":"+"{:.2f}".format(AC_Amp) mJSON += ",\"Watt\":"+"{:.2f}".format(AC_Watt) mJSON += " } }" if DEBUG: print("__send_"+mJSON ) #_________ print full mqtt send payload else: print(count) #____________________ or just the counter, disable if not like pass return mJSON def send(): #_____________________________________ timer check & MQTT send global count, repsec, replast, DEBUG nowsec = time.time() #________________________ float as seconds, where 0 = epoch is January 1, 1970, 00:00:00 (UTC) if ( nowsec - repsec > replast ): #___________ timer end send MQTT mJSON = calcPS() client.publish(credentials.mtopic, payload=mJSON, qos=1) count+=1 replast = nowsec #________________________ remember that sendtime #print('loop',nowsec,repsec,replast) client.loop(.1) #_____________________________ allow mqtt in... time.sleep(1.0) #_____________________________ 1 sec check, now very responsive def cmdlinecheck(argv): global DEBUG try: opts, args = getopt.getopt(argv,"hvi:o:",["ifile=","ofile="]) except getopt.GetoptError: print('.py -v -h') sys.exit(2) for opt, arg in opts: if opt == '-h': print('commandline option: .py -v') sys.exit() if opt == '-v': DEBUG = True print('enable print and fast reporting') def main(argv): global count, repsec, replast, client, DEBUG cmdlinecheck(argv) client = paho.Client(client_id="", userdata=None, protocol=paho.MQTTv311) # MQTT version 5, for 3.1.1: MQTTv311, 3.1: MQTTv31 client.on_connect = on_connect client.on_disconnect = on_disconnect client.tls_set(tls_version=mqtt.client.ssl.PROTOCOL_TLS) #____________ enable TLS for secure connection client.username_pw_set(credentials.mqtt_user,credentials.mqtt_pwd) #__ set username and password client.connect(credentials.clusterURL, 8883) #________________________ connect to HiveMQ Cloud on port 8883 (default for MQTT) #_____________________________________________________________________ setting callbacks, use separate functions like above for better visibility client.on_subscribe = on_subscribe client.on_message = on_message #client.on_publish = on_publish client.subscribe(credentials.stopic, qos=1) #_________________________ subscribe to remote commands #client.publish("KLL/RPI2/getvals", payload="my_data", qos=1) #_______ a single publish, this can also be done in loops, etc. #_____________________________________________________________________ loop_forever for simplicity, here you need to stop the loop manually #client.loop_forever() #client.loop_start() #client.loop_stop() #repsec = 60.0 if DEBUG: repsec = 10.0 print("repsec",repsec) while True: send() #_________________________________________________ use [ctrl][c] if __name__ == "__main__": main(sys.argv[1:])