Skip to content

Commit 2e76865

Browse files
authored
Merge pull request #2 from FoamyGuy/ws_server_example
websocket server example
2 parents 40bd717 + 1f303ec commit 2e76865

File tree

7 files changed

+560
-3
lines changed

7 files changed

+560
-3
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
I, the copyright holder of this work, release this work into the public domain. This applies worldwide.
2+
In some countries this may not be legally possible; if so:
3+
I grant anyone the right to use this work for any purpose, without any conditions, unless such conditions are required by law.

adafruit_opt4048.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ def __init__(self, i2c_bus, address=_OPT4048_DEFAULT_ADDR):
323323
def init(self):
324324
"""Initialize the sensor and verify the device ID"""
325325
# Check device ID
326-
print(f"id: {hex(self._device_id)}")
327326
if self._device_id != _OPT4048_CHIP_ID:
328327
raise RuntimeError("Failed to find an OPT4048 sensor - check your wiring!")
329328

@@ -593,7 +592,6 @@ def threshold_low(self):
593592
# Read the exponent and mantissa from the threshold low register
594593
exponent = self._threshold_low_exponent
595594
mantissa = self._threshold_low_mantissa
596-
print(f"exponent: {exponent} mantissa: {mantissa}")
597595
# Calculate ADC code value by applying the exponent as a bit shift
598596
# ADD 8 to the exponent as per datasheet equations 12-13
599597
return mantissa << (8 + exponent)
@@ -697,7 +695,6 @@ def all_channels(self):
697695

698696
# Combine MSB and LSB to form the 20-bit mantissa
699697
mant = (msb << 8) | lsb
700-
# print(f"ch: {ch} exp: {exp} msb: {msb} lsb: {lsb} counter: {counter} crc: {crc} mant: {mant}") # noqa: E501
701698
# Calculate CRC
702699
# Initialize CRC variables
703700
x0 = 0 # CRC bit 0

examples/opt4048_websocket.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim C for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
from asyncio import create_task, gather, run
5+
from asyncio import sleep as async_sleep
6+
7+
import board
8+
import socketpool
9+
import wifi
10+
from adafruit_httpserver import GET, FileResponse, Request, Response, Server, Websocket
11+
12+
from adafruit_opt4048 import OPT4048, ConversionTime, Mode, Range
13+
14+
pool = socketpool.SocketPool(wifi.radio)
15+
server = Server(pool, debug=True, root_path="opt4048_ws_static")
16+
17+
websocket: Websocket = None
18+
19+
READ_INTERVAL = 0.1 # seconds
20+
21+
i2c = board.I2C() # uses board.SCL and board.SDA
22+
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
23+
sensor = OPT4048(i2c)
24+
25+
sensor.range = Range.AUTO
26+
sensor.conversion_time = ConversionTime.TIME_100MS
27+
sensor.mode = Mode.CONTINUOUS
28+
29+
30+
@server.route("/connect-websocket", GET)
31+
def connect_client(request: Request):
32+
global websocket # noqa: PLW0603, global use
33+
34+
if websocket is not None:
35+
websocket.close() # Close any existing connection
36+
37+
websocket = Websocket(request)
38+
39+
return websocket
40+
41+
42+
server.start(str(wifi.radio.ipv4_address))
43+
44+
45+
async def handle_http_requests():
46+
while True:
47+
server.poll()
48+
49+
await async_sleep(0)
50+
51+
52+
async def send_color_data_ws():
53+
while True:
54+
if websocket is not None:
55+
try:
56+
x, y, lux = sensor.cie
57+
out_msg = "---CIE Data---\n"
58+
out_msg += f"CIE x: {x}\n"
59+
out_msg += f"CIE y: {y}\n"
60+
out_msg += f"Lux: {lux}\n"
61+
out_msg += f"Color Temperature: {sensor.calculate_color_temperature(x, y)} K\n"
62+
out_msg += "-------------\n"
63+
64+
websocket.send_message(out_msg, fail_silently=True)
65+
except RuntimeError:
66+
# error reading sensor
67+
pass
68+
69+
await async_sleep(READ_INTERVAL)
70+
71+
72+
async def main():
73+
await gather(
74+
create_task(handle_http_requests()),
75+
create_task(send_color_data_ws()),
76+
)
77+
78+
79+
run(main())
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2009 BenRG
2+
// SPDX-License-Identifier: LicenseRef-Wikipedia-Public-Domain

examples/opt4048_ws_static/index.html

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
<!--
2+
SPDX-FileCopyrightText: Copyright (c) 2025 Tim C for Adafruit Industries
3+
SPDX-License-Identifier: MIT
4+
-->
5+
<!DOCTYPE html>
6+
<html lang="en">
7+
<head>
8+
<meta charset="UTF-8">
9+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
10+
<title>OPT4048 CIE Color Plotter</title>
11+
<style>
12+
body {
13+
font-family: Arial, sans-serif;
14+
max-width: 100%;
15+
margin: 0 auto;
16+
padding: 8px;
17+
height: 100vh;
18+
display: flex;
19+
flex-direction: column;
20+
}
21+
.container {
22+
display: flex;
23+
flex-wrap: wrap;
24+
gap: 10px;
25+
justify-content: center;
26+
flex: 1;
27+
}
28+
.controls {
29+
flex: 1;
30+
min-width: 230px;
31+
max-width: 100%;
32+
display: flex;
33+
flex-direction: column;
34+
overflow: hidden;
35+
}
36+
.visualization {
37+
flex: 2;
38+
min-width: 280px;
39+
max-width: 100%;
40+
display: flex;
41+
flex-direction: column;
42+
}
43+
#cie-diagram {
44+
position: relative;
45+
width: 100%;
46+
max-width: 450px;
47+
margin: 0 auto 10px auto;
48+
flex: 1;
49+
display: flex;
50+
align-items: center;
51+
justify-content: center;
52+
}
53+
#cie-diagram img {
54+
width: 100%;
55+
max-height: 100%;
56+
object-fit: contain;
57+
display: block;
58+
}
59+
#data-point {
60+
position: absolute;
61+
width: 16px;
62+
height: 16px;
63+
background-color: white;
64+
border-radius: 50%;
65+
border: 3px solid black;
66+
transform: translate(-50%, -50%);
67+
pointer-events: none;
68+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.9);
69+
z-index: 10;
70+
}
71+
#color-sample {
72+
width: 30px;
73+
height: 30px;
74+
border: 1px solid #ccc;
75+
margin: 0 auto;
76+
border-radius: 50%;
77+
}
78+
#serial-log {
79+
flex: 1;
80+
min-height: 80px;
81+
max-height: 150px;
82+
overflow-y: auto;
83+
background-color: #f5f5f5;
84+
padding: 8px;
85+
border: 1px solid #ddd;
86+
font-family: monospace;
87+
font-size: 12px;
88+
margin-bottom: 5px;
89+
}
90+
button {
91+
padding: 8px 12px;
92+
margin: 4px 4px 4px 0;
93+
background-color: #4CAF50;
94+
color: white;
95+
border: none;
96+
border-radius: 4px;
97+
cursor: pointer;
98+
font-size: 14px;
99+
}
100+
button:hover {
101+
background-color: #45a049;
102+
}
103+
button:disabled {
104+
background-color: #cccccc;
105+
cursor: not-allowed;
106+
}
107+
.data-display {
108+
display: flex;
109+
flex-wrap: wrap;
110+
justify-content: center;
111+
gap: 8px;
112+
margin-top: 10px;
113+
}
114+
.data-box {
115+
flex: 1;
116+
min-width: 100px;
117+
margin: 0;
118+
padding: 10px;
119+
background-color: #f9f9f9;
120+
border: 1px solid #ddd;
121+
border-radius: 4px;
122+
text-align: center;
123+
}
124+
.data-box h3 {
125+
margin: 0 0 5px 0;
126+
font-size: 14px;
127+
}
128+
.data-value {
129+
font-size: 18px;
130+
font-weight: bold;
131+
}
132+
133+
/* Responsive adjustments for very small screens */
134+
@media (max-height: 600px) {
135+
h1 { font-size: 20px !important; margin: 5px 0 !important; }
136+
h2 { font-size: 16px; margin: 8px 0 5px 0; }
137+
p { font-size: 12px !important; margin: 5px 0 !important; }
138+
.data-box { padding: 5px; }
139+
.data-box h3 { font-size: 12px; margin: 0 0 3px 0; }
140+
.data-value { font-size: 14px; }
141+
#serial-log { min-height: 60px; max-height: 100px; }
142+
button { padding: 6px 10px; font-size: 12px; }
143+
}
144+
</style>
145+
</head>
146+
<body>
147+
148+
149+
<div class="container">
150+
<div class="controls">
151+
<h2 style="margin: 10px 0; font-size: 24px;">OPT4048 CIE Color Plotter</h2>
152+
<p style="margin: 8px 0; font-size: 14px;">Connect your Arduino with OPT4048 sensor to visualize color measurements on a CIE diagram.</p>
153+
154+
<button id="clear-button">Clear Log</button>
155+
<button id="test-plot-button" style="display: none;">Test Plot Point</button>
156+
157+
<h2>Connection Status</h2>
158+
<p id="status">Not connected</p>
159+
160+
<h2 style="margin-bottom: 5px;">Serial Monitor</h2>
161+
<div id="serial-log"></div>
162+
</div>
163+
164+
<div class="visualization">
165+
<h2 style="margin: 10px 0; font-size: 24px;">CIE 1931 Chromaticity Diagram</h2>
166+
<div id="cie-diagram">
167+
<img src="cie1931_diagram.svg" alt="CIE 1931 Chromaticity Diagram">
168+
<div id="data-point" style="display: none;"></div>
169+
<!-- Debug info: will show exact location of measured color -->
170+
<div id="debug-coordinates" style="position: absolute; bottom: 3px; right: 3px; font-size: 10px; background: rgba(255,255,255,0.7); padding: 2px; border: 1px solid #ccc; display: block;"></div>
171+
</div>
172+
173+
<div class="data-display">
174+
<div class="data-box">
175+
<h3>CIE x</h3>
176+
<div id="cie-x" class="data-value">-</div>
177+
</div>
178+
<div class="data-box">
179+
<h3>CIE y</h3>
180+
<div id="cie-y" class="data-value">-</div>
181+
</div>
182+
<div class="data-box">
183+
<h3>Lux</h3>
184+
<div id="lux" class="data-value">-</div>
185+
</div>
186+
<div class="data-box">
187+
<h3>CCT (K)</h3>
188+
<div id="cct" class="data-value">-</div>
189+
</div>
190+
</div>
191+
192+
<div class="data-box">
193+
<h3>Color Approximation</h3>
194+
<div id="color-sample"></div>
195+
<small>(Note: This is a rough approximation)</small>
196+
</div>
197+
</div>
198+
</div>
199+
200+
<script src="script.js"></script>
201+
</body>
202+
</html>

0 commit comments

Comments
 (0)