-
Notifications
You must be signed in to change notification settings - Fork 0
/
software.py
281 lines (230 loc) · 8.99 KB
/
software.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# ------------------------------
# Import Python modules
# ------------------------------
from arduino_iot_cloud import ArduinoCloudClient, ColoredLight
import logging, sys, time, colorsys, threading, multiprocessing, serial
import digitalio, board
from serial.tools import list_ports
from luma.core.interface.serial import spi, noop
from luma.core.legacy import text, show_message
from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT
from luma.led_matrix.device import max7219
# utils.py
from utils import scrivi_testo, send_until_ok, wait_for_arduino
# ------------------------------
# Arduino Cloud configuration
# ------------------------------
sys.path.append("lib")
DEVICE_ID = b"<REPLACE WITH YOUR DEVICE ID>"
SECRET_KEY = b"<REPLACE WITH YOUR SECRET KEY>"
# Launch the Arduino Cloud client in a separate thread
def start_client():
client.start()
testo = "Buon Natale!"
booting = True
# ------------------------------
# Logging configuration
# ------------------------------
logging.basicConfig(
datefmt="%H:%M:%S",
format="%(asctime)s.%(msecs)03d %(levelname)s: %(message)s",
level=logging.DEBUG
)
# ------------------------------
# Raspberry Pi GPIO setup
# ------------------------------
## Motore stella
motore_stella = digitalio.DigitalInOut(board.D27)
motore_stella.direction = digitalio.Direction.OUTPUT
## LED strip configuration
prev_hue = prev_sat = None
colore = [0, 0, 0]
## LED matrix configuration
try:
matrix_serial = spi(port=0, device=0, gpio=noop())
matrix = max7219(matrix_serial, cascaded=8, block_orientation=-90)
except:
logging.warning("LED matrix not connected! LED matrix functions will not work!")
matrix_serial = None
matrix = None
# ------------------------------
# Arduino Serial config
# ------------------------------
def find_arduino():
ports = list_ports.comports()
for p in ports:
logging.debug(f"Serial port device detected: {p}, Manufacturer: {p.manufacturer}")
if p.manufacturer is not None and ("Arduino" in p.manufacturer or "Arduino" in p.description):
return p.device
return None
arduino_port = find_arduino()
if arduino_port is not None:
ser = serial.Serial(arduino_port, 9600)
logging.info(f"Arduino connected on port {arduino_port}!")
else:
ser = None
logging.warning("Arduino not connected! Arduino related functions will not work!")
# How data will be structured:
# [0/1, 0/1, 0-255, 0-255, 0-255, 0-100]
# [ON/OFF, Instant Change, R, G, B, Brightness]
# ------------------------------
# Callback functions
# ------------------------------
def on_coloreled_changed(client, value):
global prev_hue, prev_sat, colore, ser, booting
if not booting:
logging.info(f"LED Changed! Status is: SWI: {value.swi}, HUE: {value.hue}, SAT: {value.sat}, BRI: {value.bri} --> {hsl_to_rgb(value.hue, value.sat)}")
colore = hsl_to_rgb(value.hue, value.sat)
# If the HUE or SAT values haven't changed, don't start a new thread
if prev_hue == value.hue and prev_sat == value.sat:
return
# Log the new color and the previous HUE and SAT values
logging.debug(f"New color: {colore}, Previous HUE: {prev_hue}, Previous SAT: {prev_sat}")
prev_hue, prev_sat = value.hue, value.sat
if client["cambioIstantaneo"] and client["controlloGenerale"]:
send_until_ok(f"1, 1, {int(colore[0])}, {int(colore[1])}, {int(colore[2])}, {int(value.bri)}", ser)
elif client["controlloGenerale"]:
send_until_ok(f"1, 0, {int(colore[0])}, {int(colore[1])}, {int(colore[2])}, {int(value.bri)}", ser)
def on_cambioistantaneo_changed(client, value):
global booting
if not booting:
logging.info(f"cambioIstantaneo Changed! Status is: {value}")
def on_controllogenerale_changed(client, value):
global booting
if not booting:
logging.info(f"controlloGenerale Changed! Status is: {value}")
if value:
attiva_tutto()
else:
disattiva_tutto()
def on_motorestella_changed(client, value):
global booting
if not booting:
logging.info(f"motoreStella Changed! Status is: {value}")
if value and client["controlloGenerale"]:
attiva_motore()
else:
disattiva_motore()
def on_testomatrice_changed(client, value):
global matrice, testo, booting, matrix
if not booting:
logging.info(f"testoMatrice Changed! Status is: {value}")
old_testo = testo
testo = str(value)
if testo.strip() == "":
testo = "Buon Natale!"
if testo == "rainbow":
testo = old_testo
if client["controlloGenerale"]:
send_until_ok(f"1, 2, 0, 0, 0, 0", ser)
client["testoMatrice"] = testo
return
if matrice.is_alive():
matrice.terminate()
if client["controlloGenerale"]:
matrice = multiprocessing.Process(target=scrivi_testo, args=(testo,matrix,))
matrice.start()
# ------------------------------
# Color conversion functions
# ------------------------------
def rgb_to_hsl(r, g, b):
r, g, b = r / 255.0, g / 255.0, b / 255.0
hue, lightness, saturation = colorsys.rgb_to_hls(r, g, b)
return hue, saturation, 50
def hsl_to_rgb(hue, saturation, lightness=50):
hue, saturation, lightness = hue / 360.0, saturation / 100.0, lightness / 100.0 # normalize hue to range [0, 1]
r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation)
return int(r * 255), int(g * 255), int(b * 255)
# ------------------------------
# Multi-threading
# ------------------------------
def termina_thread_matrix():
global matrice
if matrice is not None and matrice.is_alive():
matrice.terminate()
matrice = None
regen_thread_matrix()
def regen_thread_matrix():
global matrice, testo, matrix
matrice = multiprocessing.Process(target=scrivi_testo, args=(testo,matrix))
# ------------------------------
# Controllo generale
# ------------------------------
def disattiva_tutto():
global matrice, colore, ser
termina_thread_matrix()
if ser is None:
logging.warning("Arduino not connected! Arduino functions will not work!")
else:
send_until_ok(f"0, 1, {int(colore[0])}, {int(colore[1])}, {int(colore[2])}, {int(client['coloreLED'].bri)}", ser)
spegni_matrice()
disattiva_motore()
logging.info("Motore stella disattivato!")
def attiva_tutto():
global matrice, colore, ser
if ser is None:
logging.warning("Arduino not connected! Arduino functions will not work!")
else:
send_until_ok(f"1, 1, {int(colore[0])}, {int(colore[1])}, {int(colore[2])}, {int(client['coloreLED'].bri)}", ser)
termina_thread_matrix()
matrice.start()
attiva_motore()
logging.info("Motore stella attivato!")
# ------------------------------
# Motore stella (GPIO17)
# ------------------------------
def attiva_motore():
global motore_stella
if motore_stella is None:
logging.warning("Motore stella not connected! Motore stella functions will not work!")
return
motore_stella.value = True
logging.info("Motore stella attivato!")
def disattiva_motore():
global motore_stella
if motore_stella is None:
logging.warning("Motore stella not connected! Motore stella functions will not work!")
return
motore_stella.value = False
logging.info("Motore stella disattivato!")
# ------------------------------
# LED matrix functions
# ------------------------------
# scrivi_testo is in utils.py
def spegni_matrice():
global matrix
if matrix is None:
logging.warning("LED matrix not connected! LED matrix functions will not work!")
return
termina_thread_matrix()
matrix.clear()
matrix.hide()
logging.info("LED matrix turned off!")
# ------------------------------
# Main
# ------------------------------
if __name__ == "__main__":
client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY)
regen_thread_matrix()
client.register(ColoredLight("coloreLED", on_write=on_coloreled_changed))
client.register("cambioIstantaneo", value=None, on_write=on_cambioistantaneo_changed)
client.register("controlloGenerale", value=None, on_write=on_controllogenerale_changed)
client.register("motoreStella", value=None, on_write=on_motorestella_changed)
client.register("testoMatrice", value=None, on_write=on_testomatrice_changed)
thread = threading.Thread(target=start_client)
thread.start()
time.sleep(7)
booting = False
time.sleep(0.5)
logging.info("Updating default values...")
client["cambioIstantaneo"] = False
client["controlloGenerale"] = True
client["motoreStella"] = True
testo = "Buon Natale!"
client["testoMatrice"] = testo
client["coloreLED"].hue = 108.0
client["coloreLED"].sat = 92.0
client["coloreLED"].bri = 50.0
logging.info("Default values updated!")
time.sleep(1)
attiva_tutto()