Skip to content

Commit

Permalink
Add support for removing bulbs, saving general settings.
Browse files Browse the repository at this point in the history
  • Loading branch information
dewgenenny committed Dec 3, 2023
1 parent 8c60df9 commit 9589649
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 115 deletions.
7 changes: 5 additions & 2 deletions screensync/screen_sync/bulb_control/magichome_bulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class FluxLedBulbControl:

def __init__(self, ip_address, placement, rate_limiter):
self.bulb = WifiLedBulb(ip_address)
self.bulb = WifiLedBulb(ip_address, timeout=1)
self.rate_limiter = rate_limiter
self.last_color = None
self.placement = placement
Expand All @@ -28,4 +28,7 @@ def set_color(self, r, g, b):
self.last_color = new_color # Store the new color

def connect(self):
self.bulb.connect()
try:
self.bulb.connect(retry=1)
except:
print("Bulb " + self.type + " - " + self.ip + "Unavailable")
2 changes: 1 addition & 1 deletion screensync/screen_sync/bulb_control/tuya_bulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(self, device_id, local_key, ip, rate_limiter, placement):


def connect(self):
self.bulb = tinytuya.BulbDevice(self.device_id, self.ip, self.local_key, persist=True)
self.bulb = tinytuya.BulbDevice(self.device_id, self.ip, self.local_key, persist=True, connection_timeout=1, connection_retry_limit=3, connection_retry_delay=1)
self.bulb.set_version(3.3)
self.bulb.set_socketRetryLimit(1)
self.bulb.set_socketTimeout(1)
Expand Down
41 changes: 25 additions & 16 deletions screensync/screen_sync/bulb_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,33 @@ def create_bulbs(self):
rate_limiter = RateLimiter(frequency) # Instantiate RateLimiter
placement = bulb_config.get('placement', 'center')
if bulb_config['type'] == 'MagicHome':
bulb = FluxLedBulbControl(bulb_config['ip_address'], placement, rate_limiter)
bulbs.append(bulb)
try:
bulb = FluxLedBulbControl(bulb_config['ip_address'], placement, rate_limiter)
bulbs.append(bulb)
except:
print("Error adding " + bulb.type + " bulb with IP " + bulb_config['ip_address'] )
elif bulb_type == 'Tuya':
bulb = TuyaBulbControl(bulb_config['device_id'], bulb_config['local_key'], bulb_config['ip_address'], rate_limiter, placement)
bulbs.append(bulb)
try:
bulb = TuyaBulbControl(bulb_config['device_id'], bulb_config['local_key'], bulb_config['ip_address'], rate_limiter, placement)
bulbs.append(bulb)
except:
print("Error adding " + bulb.type + " bulb with IP " + bulb_config['ip_address'] )
elif bulb_type == 'MQTT':
bulb = ZigbeeBulbControl(
mqtt_broker=mqtt_settings['broker'],
port=mqtt_settings['port'],
username=mqtt_settings['username'],
password=mqtt_settings['password'],
topic=bulb_config['topic'],
rate_limiter=rate_limiter,
placement=placement
)
bulb.turn_on()
bulb.connect()
bulbs.append(bulb)
try:
bulb = ZigbeeBulbControl(
mqtt_broker=mqtt_settings['broker'],
port=mqtt_settings['port'],
username=mqtt_settings['username'],
password=mqtt_settings['password'],
topic=bulb_config['topic'],
rate_limiter=rate_limiter,
placement=placement
)
bulb.turn_on()
bulb.connect()
bulbs.append(bulb)
except:
print("Error adding " + bulb.type + " bulb with MQTT broker " + mqtt_broker )
pass
# Add more conditions for other bulb types

Expand Down
10 changes: 7 additions & 3 deletions screensync/screen_sync/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def create_default_config(self):
"""Creates a default configuration file."""
# Add default sections and settings
self.config['General'] = {
'screen_capture_size': '100, 100',
'saturation_factor': '1.5'
}
self.config['MQTT'] = {
Expand Down Expand Up @@ -63,7 +62,7 @@ def get_general_settings(self):
"""Retrieves general settings from the config."""
general = self.config['General']
return {
'screen_capture_size': tuple(map(int, general.get('screen_capture_size', '100, 100').split(','))),
# 'screen_capture_size': tuple(map(int, general.get('screen_capture_size', '100, 100').split(','))),
'saturation_factor': general.getfloat('saturation_factor', 1.5)
}

Expand Down Expand Up @@ -168,7 +167,7 @@ def _add_tuya_bulb(self, device_id, local_key, ip_address, placement):
def _add_magichome_bulb(self, ip_address, placement):
"""Adds a new Tuya bulb configuration."""
tuya_bulb_count = len([s for s in self.config.sections() if s.startswith('BulbTuya')])
section_name = f'BulbTuya{tuya_bulb_count + 1}'
section_name = f'BulbMagicHome{tuya_bulb_count + 1}'

self.config[section_name] = {
'ip_address': ip_address,
Expand All @@ -190,6 +189,11 @@ def set_update_frequency(self, bulb_type, frequency):
self.config[section]['update_frequency'] = str(frequency)
self.save_config()

def remove_bulb(self, config_section):
if config_section in self.config.sections():
self.config.remove_section(config_section)
self.save_config()


# Example Usage
if __name__ == "__main__":
Expand Down
14 changes: 14 additions & 0 deletions screensync/screen_sync/ui/remove_bulb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# remove_bulb.py

import tkinter as tk
from tkinter import messagebox

def create_remove_bulb_button(bulb_window, config_manager, config_section, refresh_callback):
def remove_bulb():
if messagebox.askyesno("Remove Bulb", "Are you sure you want to remove this bulb?"):
config_manager.remove_bulb(config_section)
refresh_callback()
bulb_window.destroy()

remove_button = tk.Button(bulb_window, text="Remove", command=remove_bulb, bg='red', fg='white')
return remove_button
158 changes: 70 additions & 88 deletions screensync/ui.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import tkinter as tk
from tkinter import PhotoImage
from tkinter import Toplevel, Label, Entry, Button, Listbox,LabelFrame, END
from tkinter import ttk
from tkinter import PhotoImage, Toplevel, Label, Entry, Button, Listbox,LabelFrame, ttk, messagebox, END
from PIL import Image, ImageTk
import PIL
from platformdirs import *
import os
from screensync.screen_sync.ui.add_bulb import create_add_bulb_window
from screensync.screen_sync.ui.remove_bulb import create_remove_bulb_button

import pkg_resources

appname = 'ScreenSync_v2'
Expand All @@ -31,7 +31,7 @@ def main():

# Check if config directory exists and if not create
os.makedirs(user_data_dir(appname, appauthor), exist_ok=True)
print(user_data_dir(appname, appauthor) + '/config.ini')
#print(user_data_dir(appname, appauthor) + '/config.ini')
# Initialize necessary objects
config_manager = ConfigManager(user_data_dir(appname, appauthor) + '/config.ini')

Expand Down Expand Up @@ -125,11 +125,11 @@ def on_closing(root, coordinator):
def reinitialize_bulbs():
global config_manager
config_manager = ConfigManager('./config.ini')
global bulbs # If bulbs are defined globally
global bulbs
bulbs = bulb_factory.create_bulbs() # Recreate bulbs with new settings
global coordinator
coordinator = Coordinator(bulbs, color_processing)
print(bulbs)



def shooter_clicked(shooter_button, coordinator):
Expand Down Expand Up @@ -164,55 +164,23 @@ def open_general_settings(config_manager):
saturation_var = tk.StringVar(value=general_settings.get('saturation_factor', '1.5'))
Entry(general_settings_window, textvariable=saturation_var).grid(row=0, column=1)

# Screen Capture Size Setting
Label(general_settings_window, text="Screen Capture Size:").grid(row=1, column=0, sticky='e')
capture_size_var = tk.StringVar(value=general_settings.get('screen_capture_size', '100, 100'))
Entry(general_settings_window, textvariable=capture_size_var).grid(row=1, column=1)
# # Screen Capture Size Setting
# Label(general_settings_window, text="Screen Capture Size:").grid(row=1, column=0, sticky='e')
# capture_size_var = tk.StringVar(value=general_settings.get('screen_capture_size', '100, 100'))
# Entry(general_settings_window, textvariable=capture_size_var).grid(row=1, column=1)

# Save Button
save_button = Button(general_settings_window, text="Save",
command=lambda: save_general_settings(saturation_var, capture_size_var))
save_button.grid(row=2, column=0, columnspan=2)


def open_settings_window(root, coordinator, config_manager , bulb_factory):

def refresh_bulb_list():
bulbs_listbox.delete(0, tk.END) # Clear the existing list
bulbs = config_manager.get_bulbs() # Retrieve updated list of bulbs
for bulb in bulbs:
bulbs_listbox.insert(tk.END, f"{bulb['config_id']} - {bulb['device_id']} - {bulb['placement']}")
reinitialize_bulbs()
def create_settings_frame(parent, title, settings, entries_dict):
frame = tk.LabelFrame(parent, text=title, bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
frame.pack(padx=10, pady=10, fill='x')

settings_window = tk.Toplevel(root)
settings_window.title("Settings")
settings_window.geometry("400x700") # Adjust the size as needed
settings_window.configure(bg='#404957')
settings_window.resizable(False, False)

# General settings frame
general_settings_frame = tk.LabelFrame(settings_window, text="General", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
general_settings_frame.pack(padx=10, pady=10, fill='x')
# MQTT settings frame
mqtt_settings_frame = tk.LabelFrame(settings_window, text="MQTT Server", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
mqtt_settings_frame.pack(padx=10, pady=10, fill='x')
# Tuya settings frame
tuya_settings_frame = tk.LabelFrame(settings_window, text="Tuya Specific", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
tuya_settings_frame.pack(padx=10, pady=10, fill='x')
# MQTT settings frame
mqtt_specific_settings_frame = tk.LabelFrame(settings_window, text="MQTT Specific", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
mqtt_specific_settings_frame.pack(padx=10, pady=10, fill='x')
# MagicHome settings frame
magichome_specific_settings_frame = tk.LabelFrame(settings_window, text="MagicHome Specific", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
magichome_specific_settings_frame.pack(padx=10, pady=10, fill='x')

add_new_frame = tk.LabelFrame(settings_window, text="Add New Bulb", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
add_new_frame.pack(padx=10, pady=10, fill='x')

# Retrieve general settings and create a label and entry for each setting
general_settings = config_manager.get_general_settings()
for setting, value in general_settings.items():
row = tk.Frame(general_settings_frame, bg='#404957')
for setting, value in settings.items():
row = tk.Frame(frame, bg='#404957')
row.pack(side='top', fill='x', padx=5, pady=5)

label = tk.Label(row, text=setting.replace('_', ' ').title() + ":", bg='#404957', fg='white')
Expand All @@ -221,58 +189,68 @@ def refresh_bulb_list():
entry = tk.Entry(row, bg='white', fg='black')
entry.pack(side='right', expand=True, fill='x')
entry.insert(0, value)
entries_dict[setting] = entry

mqtt_settings = config_manager.get_mqtt_settings()

for setting, value in mqtt_settings.items():
row = tk.Frame(mqtt_settings_frame, bg='#404957')
row.pack(side='top', fill='x', padx=5, pady=5)

label = tk.Label(row, text=setting.replace('_', ' ').title() + ":", bg='#404957', fg='white')
label.pack(side='left')
return frame

entry = tk.Entry(row, bg='white', fg='black')
entry.pack(side='right', expand=True, fill='x')
entry.insert(0, value)
def open_settings_window(root, coordinator, config_manager , bulb_factory):

tuya_settings = config_manager.get_config_by_section("TuyaSettings")

for setting, value in tuya_settings.items():
row = tk.Frame(tuya_settings_frame, bg='#404957')
row.pack(side='top', fill='x', padx=5, pady=5)
# This dictionary will hold the entry widgets for settings
settings_entries = {
'General': {},
'MQTT': {},
'TuyaSettings': {},
'MQTTSettings': {},
'MagicHomeSettings': {}
}

label = tk.Label(row, text=setting.replace('_', ' ').title() + ":", bg='#404957', fg='white')
label.pack(side='left')
def save_settings():
# Iterate over each settings section and update the configuration
for section, entries in settings_entries.items():
for setting, entry in entries.items():
config_manager.config[section][setting] = entry.get()

entry = tk.Entry(row, bg='white', fg='black')
entry.pack(side='right', expand=True, fill='x')
entry.insert(0, value)
# Save the updated configuration to the file
config_manager.save_config()

mqtt_specific_settings = config_manager.get_config_by_section("MQTTSettings")
# Refresh the bulbs and UI if necessary
refresh_bulb_list()

for setting, value in mqtt_specific_settings.items():
row = tk.Frame(mqtt_specific_settings_frame, bg='#404957')
row.pack(side='top', fill='x', padx=5, pady=5)
# Provide feedback that settings have been saved
messagebox.showinfo("Settings", "Settings have been saved successfully.")

label = tk.Label(row, text=setting.replace('_', ' ').title() + ":", bg='#404957', fg='white')
label.pack(side='left')

entry = tk.Entry(row, bg='white', fg='black')
entry.pack(side='right', expand=True, fill='x')
entry.insert(0, value)
def refresh_bulb_list():
bulbs_listbox.delete(0, tk.END) # Clear the existing list
bulbs = config_manager.get_bulbs() # Retrieve updated list of bulbs
for bulb in bulbs:
bulbs_listbox.insert(tk.END, f"{bulb['config_id']} - {bulb['device_id']} - {bulb['placement']}")
reinitialize_bulbs()

magichome_specific_settings = config_manager.get_config_by_section("MagicHomeSettings")
settings_window = tk.Toplevel(root)
settings_window.title("Settings")
settings_window.geometry("400x700") # Adjust the size as needed
settings_window.configure(bg='#404957')
settings_window.resizable(False, False)

for setting, value in magichome_specific_settings.items():
row = tk.Frame(magichome_specific_settings_frame, bg='#404957')
row.pack(side='top', fill='x', padx=5, pady=5)
# General settings frame
general_settings_frame = create_settings_frame(settings_window, "General", config_manager.get_general_settings(), settings_entries['General'])
# MQTT settings frame
mqtt_settings_frame = create_settings_frame(settings_window, "MQTT Server", config_manager.get_mqtt_settings(), settings_entries['MQTT'])
# Tuya settings frame
tuya_settings_frame = create_settings_frame(settings_window, "Tuya Specific", config_manager.get_config_by_section("TuyaSettings"), settings_entries['TuyaSettings'])
# MQTT specific settings frame
mqtt_specific_settings_frame = create_settings_frame(settings_window, "MQTT Specific", config_manager.get_config_by_section("MQTTSettings"), settings_entries['MQTTSettings'])
# MagicHome settings frame
magichome_specific_settings_frame = create_settings_frame(settings_window, "MagicHome Specific", config_manager.get_config_by_section("MagicHomeSettings"), settings_entries['MagicHomeSettings'])

label = tk.Label(row, text=setting.replace('_', ' ').title() + ":", bg='#404957', fg='white')
label.pack(side='left')
# Add "Save Settings" Button
save_button = tk.Button(settings_window, text="Save Settings", command=save_settings, bg='green', fg='white')
save_button.pack(side='bottom', pady=10)

entry = tk.Entry(row, bg='white', fg='black')
entry.pack(side='right', expand=True, fill='x')
entry.insert(0, value)
add_new_frame = tk.LabelFrame(settings_window, text="Add New Bulb", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
add_new_frame.pack(padx=10, pady=10, fill='x')

# Bulbs listbox with a scrollbar
bulbs_frame = tk.LabelFrame(settings_window, text="Bulbs", bg='#404957', fg='white', font=("TkDefaultFont", 12, "bold"))
Expand Down Expand Up @@ -301,7 +279,7 @@ def refresh_bulb_list():

def on_bulb_select(event):
selected_bulb = bulbs_listbox.get(bulbs_listbox.curselection())
open_bulb_settings(root, coordinator,config_manager, bulb_factory, selected_bulb.split(' - ')[0]) # Assuming device_id is after '-'
open_bulb_settings(root, coordinator,config_manager, bulb_factory,refresh_bulb_list, selected_bulb.split(' - ')[0]) # Assuming device_id is after '-'

bulbs_listbox.bind('<<ListboxSelect>>', on_bulb_select)

Expand All @@ -323,7 +301,9 @@ def center_window_on_screen(window):



def open_bulb_settings(root, coordinator, config_manager, bulb_factory, config_section):
def open_bulb_settings(root, coordinator, config_manager, bulb_factory,refresh_bulb_list, config_section):


bulb_window = Toplevel(root)
bulb_window.title(f"Settings for Bulb: {config_section}")
bulb_window.configure(bg='#404957')
Expand Down Expand Up @@ -357,7 +337,9 @@ def save_bulb_settings():
# Save Button
save_button = Button(bulb_window, text="Save", command=save_bulb_settings)
save_button.pack(pady=10)

# Create and place the Remove Button
remove_button = create_remove_bulb_button(bulb_window, config_manager, config_section, refresh_bulb_list)
remove_button.pack(pady=(0, 10)) # Adjust padding as needed
# Place focus on the window (optional)
bulb_window.focus_force()

Expand Down
10 changes: 5 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from setuptools import setup, find_packages

setup(
name='ScreenSync', # Replace with your package name
version='0.0.1', # Initial version
author='Tom George', # Replace with your name
author_email='[email protected]', # Replace with your email
description='A Python tool for synchronizing screen colors with smart bulbs.', # Short description
name='ScreenSync',
version='0.0.2',
author='Tom George',
author_email='[email protected]',
description='A Python tool for synchronizing screen colors with smart bulbs.',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
url='https://github.com/dewgenenny/ScreenSync',
Expand Down

0 comments on commit 9589649

Please sign in to comment.