from machine import Pin, PWM, I2C
from umqtt.simple import MQTTClient
import ujson
import network
import utime as time
import dht
from led_pwm import LED
import ssd1306
from device_traits import *
from Settings import machine
exampleLines = [
"Power=1",
"Boiler1_Temp=93,3",
"Boiler2_Temp=103,3",
"Boiler1_Active=1",
"Boiler2_Active=0",
"Boiler1_Pressure=4,3",
"Boiler2_setTemp=125",
"Boiler1_setTemp=95"
]
cloudData = ""
# Device Setup
DEVICE_ID = "Device_SolarTurtle"
# WiFi Setup
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASSWORD = ""
# MQTT Setup
MQTT_BROKER = "5e7ba37033dc4c11a8e7bfdf17ff921a.s1.eu.hivemq.cloud"
MQTT_CLIENT = DEVICE_ID
MQTT_TELEMETRY_TOPIC = 'iot/device/{0}/telemetry'.format(DEVICE_ID)
MQTT_CONTROL_TOPIC = 'iot/device/{0}/control'.format(DEVICE_ID)
MQTT_MASTER_TELEMETRY_TOPIC = 'iot/telemetry'.format(DEVICE_ID)
MQTT_MASTER_CONTROL_TOPIC = 'iot/control'.format(DEVICE_ID)
# DHT Sensor Setup
DHT_PIN = Pin(15)
dht_sensor = dht.DHT22(DHT_PIN)
# LED/LAMP Setup
RED_LED = LED(12)
BLUE_LED = LED(13)
FLASH_LED = Pin(2, Pin.OUT)
# OLED Pins
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
# Turn On LED
RED_LED.on()
BLUE_LED.off()
# Methods
def evaluateSerialLine(line):
# Auswertung einer durch UART empfangenen Line, welche mit \n abschließt
# print(line)
line = line.replace("\n", "")
# Nur wenn es ein Variablennamen und einen Wert gibt, dann wird der Befehl akzeptiert
if "=" in line:
[befehl, value] = line.split("=", 1)
# Prüfe ob es ein _ im Befehl gibt
if "_" in befehl:
[boiler, variable] = befehl.split("_", 1)
#print(boiler + ": " + variable + " = " + value)
updateBoilerVariable(boiler, variable, value)
else:
# Maschinenvariable
updateMachineVariable(befehl, value)
def updateMachineVariable(variable, value):
if variable == "Power":
machine.isOn = bool(int(value))
elif variable == "Connected":
machine.isConnected = bool(int(value))
def updateBoilerVariable(boiler, variable, value):
# Referenz auf den Boiler setzen
selectedBoiler = machine.boiler1 if boiler == "Boiler1" else machine.boiler2
# Komma im Value ersetzen
value = value.replace(",", ".")
# Wert der richtigen Variable hinzufügen
if variable == "Temp":
selectedBoiler.temperature = float(value)
elif variable == "Active":
selectedBoiler.isOn = bool(int(value))
elif variable == "Pressure":
selectedBoiler.pressure = float(value)
elif variable == "setTemp":
selectedBoiler.setTemperature(float(value))
def did_recieve_callback(topic, message):
print("\n Function: did_recieve_callback")
print('\n\nData Recieved! \ntopic = {0}, message = {1}'.format(topic, message))
if topic == MQTT_CONTROL_TOPIC.encode():
#Get the command message from json command.
command_message = ujson.loads(message.decode())["command"]
if command_message == "lamp/red/on":
RED_LED.on()
send_machine_status()
elif command_message == "lamp/red/off":
RED_LED.off()
send_machine_status()
elif command_message == "lamp/blue/on":
BLUE_LED.on()
send_machine_status()
elif command_message == "lamp/blue/off":
BLUE_LED.off()
send_machine_status()
elif command_message == "lamp/on":
RED_LED.on()
BLUE_LED.on()
send_machine_status()
elif command_message == "lamp/off":
RED_LED.off()
BLUE_LED.off()
send_machine_status()
elif command_message == "status":
mqtt_client_publish(MQTT_TELEMETRY_TOPIC, get_sensor_json_data())
send_machine_status()
elif len(command_message.split('/')) == 4 and command_message.split('/')[2] == "brightness":
# "lamp/red/brightness/34"
brightness_commands = command_message.split('/')
brightness_value = float(brightness_commands[3])
if(brightness_commands[1] == "red"):
RED_LED.set_brightness(brightness_value)
if(brightness_commands[1] == "blue"):
BLUE_LED.set_brightness(brightness_value)
send_machine_status()
else:
return
# MQTT_MASTER_CONTROL_TOPIC is used for Google Home Integration.
if topic == MQTT_MASTER_CONTROL_TOPIC.encode():
#Get the command message from json command.
received_message = ujson.loads(message.decode())
should_acknowledge = {}
command_data = {}
if 'type' in received_message:
if received_message['type'] == "command":
if "data" in received_message and DEVICE_ID in received_message["data"]:
print(received_message)
command_data = received_message["data"]
should_acknowledge = received_message["acknowledge"]
process_commands(command_data[DEVICE_ID], should_acknowledge)
else:
print("Message is not for this device")
elif received_message['type'] == "ping" and received_message['id'] == DEVICE_ID:
print("PING Message Received")
else:
print("Message not of type COMMAND or PING")
else:
print("Message type invalid, do not process.")
def mqtt_connect():
print("Connecting to MQTT broker ...", end="")
mqtt_client = MQTTClient(MQTT_CLIENT, MQTT_BROKER, user="iotmasterclass", password="MasterClass9090", ssl=True, ssl_params={'server_hostname':MQTT_BROKER})
mqtt_client.set_callback(did_recieve_callback)
mqtt_client.connect()
print("Connected.")
mqtt_client.subscribe(MQTT_CONTROL_TOPIC)
# subscribe to master topics for Google Home Control
mqtt_client.subscribe(MQTT_MASTER_CONTROL_TOPIC)
return mqtt_client
def create_control_json_data(command, command_id):
#import ujson
data = ujson.dumps({
"device_id": DEVICE_ID,
"command_id": command_id,
"command": command
})
return data
def get_sensor_json_data():
data = ujson.dumps({
"device_id": DEVICE_ID,
"temp": dht_sensor.temperature(),
"type": "COFFEE_MAKER"
})
return data
def get_all_parts_settings():
global machineMode, temperatureSetpointCelsius
data = {
"device_id": DEVICE_ID,
"machineState": machine.isOn,
"machineMode": machineMode,
"temp": dht_sensor.temperature(),
"setTemp": temperatureSetpointCelsius,
}
global parts_settings
parts_settings = data
return data
def create_master_json_data():
data = ujson.dumps(get_all_parts_settings())
return data
def mqtt_client_publish(topic, data):
try:
print("\nUpdating MQTT Broker...")
mqtt_client.publish(topic, data)
print(data)
except:
print("MQTT client may not be initialized.")
def send_machine_status():
data = ujson.dumps({
"device_id": DEVICE_ID,
"machineState": machine.isOn,
"machineMode": machine.mode,
"type": "COFFEE_MAKER"
})
mqtt_client_publish(MQTT_TELEMETRY_TOPIC, data)
def send_ack_data(data):
mqtt_client_publish(MQTT_MASTER_TELEMETRY_TOPIC, data)
def process_commands(commands, acknowledge):
if acknowledge:
data = ujson.dumps({
"gatewayId": DEVICE_ID,
"data": commands,
})
send_ack_data( data)
for command in commands:
part = command["deviceId"].split("::")[1]
command_actions = command["commands"]
print('\n Command Actions: {0}'.format(command_actions))
if part == "coffee001":
if 'on' in command_actions:
machine.isOn = command_actions["on"]
RED_LED.set_value(machine.isOn)
print('\n Maschinenstatus: {0}'.format(machine.isOn))
if 'setTemperature' in command_actions:
machine.boiler1.setTemperature(command_actions["setTemperature"])
print('\n Neue setTemp: {0}'.format(machine.boiler1.temperature))
if 'currentModeSettings' in command_actions:
commCommandActions = command_actions["currentModeSettings"]
if 'boilermodus' in commCommandActions:
machine.mode = commCommandActions["boilermodus"]
print('\n Neue Einstellung: {0}'.format(machine.mode))
def oled_Update():
oled.fill(0)
oled.show()
oled.text('CUR TMP: '+ str(round(machine.boiler1.temperature, 1)), 0, 0)
oled.text('SET TMP: '+ str(round(machine.boiler1.setTemp, 1)), 0, 10)
oled.text('Power: '+ str(machine.isOn), 0, 30)
oled.text("Set: " + str(machine.mode), 0, 40)
oled.show()
def mqtt_ping():
data = ujson.dumps({
"device_id": machine.name,
"id": machine.name,
"type": "ping",
"devices": []
})
mqtt_client_publish(MQTT_MASTER_CONTROL_TOPIC, data)
# Application Logic
# Connect to WiFi
wifi_client = network.WLAN(network.STA_IF)
wifi_client.active(True)
print("Connecting device to WiFi")
wifi_client.connect(WIFI_SSID, WIFI_PASSWORD)
# Wait until WiFi is Connected
while not wifi_client.isconnected():
print("Connecting")
time.sleep(0.1)
print("WiFi Connected!")
print(wifi_client.ifconfig())
# Connect to MQTT
mqtt_client = mqtt_connect()
# RED_LED.off()
# BLUE_LED.off()
#mqtt_client_publish(MQTT_CONTROL_TOPIC, create_control_json_data('lamp/off', 'DEVICE-RESET-00'))
# read dht_sensor and register device.
dht_sensor.measure()
time.sleep(0.2)
# Set default settings
print("Registriere Default Settings")
mqtt_client_publish(MQTT_MASTER_CONTROL_TOPIC, machine.createGoogleCloudData("register_settings"))
oled_Update()
pause_time = 1500000
start_time = time.ticks_ms()
sleep_time = pause_time
for example in exampleLines:
evaluateSerialLine(example)
machine.printStatus()
while True:
mqtt_client.check_msg()
print(". ", end="")
try:
FLASH_LED.on()
dht_sensor.measure()
time.sleep(0.2)
FLASH_LED.off()
except:
pass
# Speichere neuen Sensorwert, falls es einen gibt
machine.boiler1.temperature = dht_sensor.temperature()
# Steuere die rote LED an, falls die Maschine läuft
RED_LED.set_value(machine.isOn)
if cloudData != machine.createGoogleCloudData("update_settings"):
print("Speichere neue Daten in der Google Cloud.")
cloudData = machine.createGoogleCloudData("update_settings")[:]
#print(cloudData)
mqtt_client_publish(MQTT_MASTER_CONTROL_TOPIC, cloudData)
oled_Update()
time.sleep(0.1)
sleep_time = sleep_time - (time.ticks_ms() - start_time)
if sleep_time < 1:
start_time = time.ticks_ms()
sleep_time = pause_time
mqtt_ping()