From 9f5db086c923f173d23f64cef37c7501d79aacd5 Mon Sep 17 00:00:00 2001 From: IchaAulia Date: Thu, 25 Jul 2024 13:22:48 +0700 Subject: [PATCH] upload kode program --- Kode program alat/finish3.py | 283 +++++++++++++++++++++++++++++++++++ Kode program alat/logo.png | Bin 0 -> 3760 bytes Kode program alat/zerogui.py | 64 ++++++++ 3 files changed, 347 insertions(+) create mode 100644 Kode program alat/finish3.py create mode 100644 Kode program alat/logo.png create mode 100644 Kode program alat/zerogui.py diff --git a/Kode program alat/finish3.py b/Kode program alat/finish3.py new file mode 100644 index 0000000..8029337 --- /dev/null +++ b/Kode program alat/finish3.py @@ -0,0 +1,283 @@ +import tkinter as tk +from PIL import Image, ImageTk +import RPi.GPIO as GPIO +import paho.mqtt.client as mqtt +import time +from datetime import datetime +import pickle +import os + +# Inisialisasi GPIO +GPIO.setmode(GPIO.BCM) +relay_pins = [20, 21, 16, 5, 13, 6, 26, 19] + +# Setel semua pin relay sebagai output dan atur ke LOW (matikan relay) +for pin in relay_pins: + GPIO.setup(pin, GPIO.OUT) + GPIO.output(pin, GPIO.LOW) + +# Nama file pickle untuk menyimpan jadwal mode RT +pickle_file_RT = "schedule_RT.pkl" +# Nama file pickle untuk menyimpan jadwal mode OT +pickle_file_OT = "schedule_OT.pkl" + +# Fungsi untuk menyimpan jadwal ke file pickle untuk mode RT +def save_schedule_RT(schedule): + with open(pickle_file_RT, 'wb') as file: + pickle.dump(schedule, file) + print("Jadwal Mode RT disimpan:", schedule) + # Kirim jadwal ke MQTT + client.publish("Room/saved_schedule_RT", str(schedule)) + +# Fungsi untuk memuat jadwal dari file pickle untuk mode RT +def load_schedule_RT(): + if os.path.exists(pickle_file_RT): + with open(pickle_file_RT, 'rb') as file: + schedule = pickle.load(file) + print("Jadwal Mode RT dimuat:", schedule) + return schedule + return None + +# Fungsi untuk menyimpan jadwal ke file pickle untuk mode OT +def save_schedule_OT(schedule): + with open(pickle_file_OT, 'wb') as file: + pickle.dump(schedule, file) + print("Jadwal Mode OT disimpan:", schedule) + # Kirim jadwal ke MQTT + client.publish("Room/saved_schedule_OT", str(schedule)) + +# Fungsi untuk memuat jadwal dari file pickle untuk mode OT +def load_schedule_OT(): + if os.path.exists(pickle_file_OT): + with open(pickle_file_OT, 'rb') as file: + schedule = pickle.load(file) + print("Jadwal Mode OT dimuat:", schedule) + return schedule + return None + +# Fungsi untuk mengubah status relay +def toggle_relay(pin, manual=True): + if not schedule_enabled or not manual: # Hanya jika penjadwalan dinonaktifkan atau jika dipanggil dari penjadwalan + if GPIO.input(pin) == GPIO.LOW: + GPIO.output(pin, GPIO.HIGH) + client.publish(f"Room/lamp{relay_pins.index(pin) + 1}", '1') # Kirim status relay ON ke MQTT + return "ON" + else: + GPIO.output(pin, GPIO.LOW) + client.publish(f"Room/lamp{relay_pins.index(pin) + 1}", '0') # Kirim status relay OFF ke MQTT + return "OFF" + +# Fungsi untuk keluar dan membersihkan GPIO +def on_closing(): + GPIO.cleanup() + root.destroy() + +# Fungsi untuk mengendalikan relay dan mengubah warna tombol +def toggle_button(button, pin): + if not schedule_enabled: # Hanya jika penjadwalan dinonaktifkan + new_state = toggle_relay(pin) + button.config(bg="#1E88E5" if new_state == "ON" else "#90CAF9") + +# Fungsi untuk memperbarui tombol berdasarkan status relay +def update_button(button, state): + button.config(bg="#3F51B5" if state == "ON" else "red") + +# Fungsi callback ketika koneksi ke broker berhasil +def on_connect(client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + # Subscribe ke topik untuk setiap lampu dan penjadwalan + client.subscribe("Room/lamp_schedule") + for i in range(8): + client.subscribe("Room/lamp" + str(i + 1)) + client.subscribe("Room/jadwal") + client.subscribe("Room/schedule_status") + +# Fungsi callback ketika pesan diterima dari broker +def on_message(client, userdata, msg): + global schedule_RT, schedule_OT, schedule_enabled + print(msg.topic + " " + str(msg.payload)) + if msg.topic == "Room/jadwal": + # Parsing pesan jadwal + schedule_info = str(msg.payload.decode("utf-8")) + mode = schedule_info[0:2] + on_time = schedule_info[2:6] + off_time = schedule_info[6:10] + relay_states = schedule_info[10:18] + schedule_date = schedule_info[18:] + + print("Pesan diterima:", schedule_info) + print("Mode:", mode) + print("Waktu ON:", on_time) + print("Waktu OFF:", off_time) + print("Relay States:", relay_states) + print("Tanggal Jadwal:", schedule_date) + + if mode == "OT": + schedule_OT = { + 'mode': mode, + 'on_time': on_time, + 'off_time': off_time, + 'relay_states': relay_states, + 'schedule_date': schedule_date + } + # Simpan jadwal mode OT ke file pickle + save_schedule_OT(schedule_OT) + elif mode == "RT": + schedule_RT = { + 'mode': mode, + 'on_time': on_time, + 'off_time': off_time, + 'relay_states': relay_states, + 'schedule_date': schedule_date + } + # Simpan jadwal mode RT ke file pickle + save_schedule_RT(schedule_RT) + elif msg.topic == "Room/schedule_status": + schedule_status = str(msg.payload.decode("utf-8")) + if schedule_status == "ON": + schedule_enabled = True + elif schedule_status == "OFF": + schedule_enabled = False + schedule_button.config(text="Schedule ON" if schedule_enabled else "Schedule OFF") + else: + if not schedule_enabled: + lamp_index = int(msg.topic.split("/")[-1][4:]) - 1 + # Hidupkan atau matikan relay sesuai dengan pesan yang diterima + if msg.payload == b'1': + GPIO.output(relay_pins[lamp_index], GPIO.HIGH) + print("Relay " + str(lamp_index + 1) + " ON") + client.publish("Icha/relay_status", "A") + update_button(buttons[lamp_index], "ON") + elif msg.payload == b'0': + GPIO.output(relay_pins[lamp_index], GPIO.LOW) + print("Relay " + str(lamp_index + 1) + " OFF") + client.publish("Icha/relay_status", "B") + update_button(buttons[lamp_index], "OFF") + +# Fungsi untuk menggabungkan jadwal OT dan RT dan menentukan status relay +def apply_combined_schedule(schedule_RT, schedule_OT): + current_time = datetime.now().strftime("%H%M") + current_date = datetime.now().strftime("%d%m%Y") + current_day = datetime.now().strftime("%w") + + relay_status = [GPIO.LOW] * 8 + + # Mode OT + if schedule_OT and schedule_OT['schedule_date'] == current_date: + on_time_OT = schedule_OT['on_time'] + off_time_OT = schedule_OT['off_time'] + relay_states_OT = schedule_OT['relay_states'] + + if on_time_OT <= current_time < off_time_OT: + for i in range(8): + if relay_states_OT[i] == "1": + relay_status[i] = GPIO.HIGH + else: + relay_status[i] = GPIO.LOW + + # Mode RT + if schedule_RT and schedule_RT['schedule_date'][int(current_day)-1] == current_day: + on_time_RT = schedule_RT['on_time'] + off_time_RT = schedule_RT['off_time'] + relay_states_RT = schedule_RT['relay_states'] + + if on_time_RT <= current_time < off_time_RT: + for i in range(8): + if relay_states_RT[i] == "1": + relay_status[i] = GPIO.HIGH + + for i in range(8): + GPIO.output(relay_pins[i], relay_status[i]) + update_button(buttons[i], "ON" if relay_status[i] == GPIO.HIGH else "OFF") + client.publish(f"Room/lamp{i+1}", '1' if relay_status[i] == GPIO.HIGH else '0') + +# Membuat GUI dengan Tkinter +root = tk.Tk() +root.title("8 Relay Control") +root.configure(bg="white") +root.geometry("480x320") + +frame = tk.Frame(root, bg="white") +frame.pack(pady=20) + +# Tambahkan gambar/logo di atas +try: + logo_image = Image.open("logo.png") + logo_image = logo_image.resize((50, 60)) + logo_photo = ImageTk.PhotoImage(logo_image) + label_logo = tk.Label(frame, image=logo_photo, borderwidth=0, bg="white") + label_logo.image = logo_photo + label_logo.grid(row=0, column=0, columnspan=1, padx=5, pady=5) +except Exception as e: + print(f"Error loading logo image: {e}") + +# Tambahkan label untuk menampilkan informasi suhu di sebelah kanan atas +label_temp = tk.Label(frame, text="Suhu Ruangan: 25°C", font=("Montserrat", 10), bg="white", fg="#3F51B5") +label_temp.grid(row=0, column=2, columnspan=2, padx=5, pady=15) + +# Memuat gambar untuk tombol-tombol +button_images = [] +for i in range(8): + try: + img = Image.open(f"button_image{i+1}.png") + img = img.resize((50, 50)) + img = ImageTk.PhotoImage(img) + button_images.append(img) + except Exception as e: + print(f"Error loading image {i+1}: {e}") + button_images.append(None) + +# Membuat tombol untuk setiap relay (dengan gambar) +buttons = [] +for i in range(2): + for j in range(4): + pin = i * 4 + j + img = button_images[pin] + if img: + btn = tk.Button(frame, image=img, bg="#90CAF9", width=60, height=60, borderwidth=0) + else: + btn = tk.Button(frame, text=f"Relay {pin+1}", bg="red", width=8, height=4, borderwidth=0) + btn.grid(row=i+1, column=j, padx=5, pady=5) + btn.config(command=lambda b=btn, p=relay_pins[pin]: toggle_button(b, p)) + buttons.append(btn) + +# Tombol untuk mengaktifkan dan menonaktifkan mode penjadwalan +schedule_enabled = False + +def toggle_schedule(): + global schedule_enabled + schedule_enabled = not schedule_enabled + schedule_button.config(text="Schedule ON", bg="#90CAF9" if schedule_enabled else "Schedule OFF", bg="red") + client.publish("Room/schedule_status", "ON" if schedule_enabled else "OFF") + +schedule_button = tk.Button(frame, text="Schedule OFF", bg="#90CAF9", width=15, height=2, borderwidth=0, command=toggle_schedule) +schedule_button.grid(row=3, column=0, columnspan=4, padx=5, pady=5) + +# Event handler saat window ditutup +root.protocol("WM_DELETE_WINDOW", on_closing) + +# Inisialisasi client MQTT +client = mqtt.Client() +client.on_connect = on_connect +client.on_message = on_message +client.connect("broker.mqtt.cool", 1883, 60) + +# Muat jadwal mode RT dan OT dari file pickle jika ada +schedule_RT = load_schedule_RT() +schedule_OT = load_schedule_OT() + +# Loop utama untuk MQTT dan Tkinter +def mqtt_loop(): + client.loop_start() + +def schedule_loop(): + if schedule_enabled: + apply_combined_schedule(schedule_RT, schedule_OT) + root.after(10000, schedule_loop) # Periksa setiap 10 detik + +root.after(100, mqtt_loop) +root.after(10000, schedule_loop) +root.mainloop() + +# Cleanup GPIO ketika program berhenti +GPIO.cleanup() diff --git a/Kode program alat/logo.png b/Kode program alat/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e653ab0bd95ea2e53d20fb09b6430b8e1d46850e GIT binary patch literal 3760 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