Skip to content

Commit 4e3c8d2

Browse files
Copilotdorkmo
andcommitted
Add example data injection for 112025 Viewer website preview
Co-authored-by: dorkmo <[email protected]>
1 parent 3c93373 commit 4e3c8d2

File tree

1 file changed

+130
-7
lines changed

1 file changed

+130
-7
lines changed

.github/workflows/html-render.yml

Lines changed: 130 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,28 +194,151 @@ jobs:
194194
mkdir -p /tmp/html-112025-viewer
195195
python3 << 'EOF'
196196
import re
197+
import json
198+
import time
197199
198200
ino_file = 'TankAlarm-112025-Viewer-BluesOpta/TankAlarm-112025-Viewer-BluesOpta.ino'
199201
output_dir = '/tmp/html-112025-viewer'
200202
201203
with open(ino_file, 'r', encoding='utf-8', errors='ignore') as f:
202204
content = f.read()
203205
204-
# Find the VIEWER_DASHBOARD_HTML constant
205-
html_pattern = r'static const char VIEWER_DASHBOARD_HTML\[\] PROGMEM = R"HTML\((.*?)\)HTML"'
206-
match = re.search(html_pattern, content, re.DOTALL)
206+
# Find the VIEWER_DASHBOARD_HTML constant - need to handle macro splits
207+
# The HTML is split into multiple R"HTML()HTML" sections with STR() macros in between
208+
start_pattern = r'static const char VIEWER_DASHBOARD_HTML\[\] PROGMEM = R"HTML\('
209+
start_match = re.search(start_pattern, content)
207210
208-
if match:
209-
html_content = match.group(1)
211+
if start_match:
212+
# Find the end - look for the final )HTML"; that ends the declaration
213+
start_pos = start_match.end()
214+
# Find the position after the HTML definition ends
215+
end_pattern = r'\)HTML";'
216+
remaining = content[start_pos:]
217+
218+
# Collect all parts, handling the macro splits
219+
html_parts = []
220+
current_pos = 0
221+
222+
while True:
223+
# Find next )HTML"
224+
end_match = re.search(r'\)HTML"', remaining[current_pos:])
225+
if not end_match:
226+
break
227+
228+
# Extract the HTML part
229+
html_parts.append(remaining[current_pos:current_pos + end_match.start()])
230+
231+
# Check if this is the final terminator
232+
check_pos = current_pos + end_match.end()
233+
if check_pos < len(remaining) and remaining[check_pos:check_pos+1] == ';':
234+
# This is the final terminator
235+
break
236+
237+
# Look for the next R"HTML(
238+
next_start = re.search(r'R"HTML\(', remaining[check_pos:])
239+
if next_start:
240+
# Extract the macro value in between
241+
macro_section = remaining[check_pos:check_pos + next_start.start()]
242+
# Replace STR(WEB_REFRESH_SECONDS) with 30
243+
if 'STR(WEB_REFRESH_SECONDS)' in macro_section:
244+
html_parts.append('30')
245+
current_pos = check_pos + next_start.end()
246+
else:
247+
break
248+
249+
html_content = ''.join(html_parts)
250+
251+
# Create sample data for the viewer
252+
current_time = int(time.time())
253+
sample_data = {
254+
"viewerName": "Demo Tank Alarm Viewer",
255+
"viewerUid": "dev:viewer001",
256+
"sourceServerName": "Demo Server",
257+
"sourceServerUid": "dev:server001",
258+
"generatedEpoch": current_time - 300, # 5 minutes ago
259+
"lastFetchEpoch": current_time - 120, # 2 minutes ago
260+
"nextFetchEpoch": current_time + 21480, # ~6 hours from now
261+
"refreshSeconds": 21600, # 6 hours
262+
"baseHour": 6,
263+
"tanks": [
264+
{
265+
"client": "dev:client001",
266+
"site": "North Facility",
267+
"label": "Primary",
268+
"tank": 1,
269+
"levelInches": 78.5,
270+
"percent": 85.3,
271+
"alarm": False,
272+
"lastUpdate": current_time - 180
273+
},
274+
{
275+
"client": "dev:client001",
276+
"site": "North Facility",
277+
"label": "Secondary",
278+
"tank": 2,
279+
"levelInches": 45.2,
280+
"percent": 52.1,
281+
"alarm": False,
282+
"lastUpdate": current_time - 180
283+
},
284+
{
285+
"client": "dev:client002",
286+
"site": "South Facility",
287+
"label": "Storage",
288+
"tank": 1,
289+
"levelInches": 18.3,
290+
"percent": 22.5,
291+
"alarm": True,
292+
"alarmType": "LOW",
293+
"lastUpdate": current_time - 240
294+
},
295+
{
296+
"client": "dev:client003",
297+
"site": "East Facility",
298+
"label": "Main",
299+
"tank": 1,
300+
"levelInches": 92.1,
301+
"percent": 95.8,
302+
"alarm": False,
303+
"lastUpdate": current_time - 150
304+
},
305+
{
306+
"client": "dev:client004",
307+
"site": "West Facility",
308+
"label": "Backup",
309+
"tank": 1,
310+
"levelInches": 12.7,
311+
"percent": 15.2,
312+
"alarm": True,
313+
"alarmType": "CRITICAL",
314+
"lastUpdate": current_time - 90
315+
}
316+
]
317+
}
318+
319+
# Inject the sample data into the HTML by replacing the fetchTanks call
320+
# Find the fetchTanks() call at the end of the script and replace it with data injection
321+
sample_data_json = json.dumps(sample_data)
322+
323+
# Replace the async fetchTanks call with synchronous data application
324+
html_content = html_content.replace(
325+
'fetchTanks();',
326+
f'applyTankData({sample_data_json}, null);'
327+
)
210328
211-
# Replace the STR(WEB_REFRESH_SECONDS) macro with a placeholder value
212-
html_content = re.sub(r'\)HTML" STR\(WEB_REFRESH_SECONDS\) R"HTML\(', '30', html_content)
329+
# Also remove the setInterval call to prevent attempts to fetch from non-existent API
330+
html_content = re.sub(
331+
r'setInterval\(\(\) => fetchTanks\(state\.selected\), REFRESH_SECONDS \* 1000\);',
332+
'// Auto-refresh disabled for static preview',
333+
html_content
334+
)
213335
214336
output_file = output_dir + '/dashboard.html'
215337
with open(output_file, 'w', encoding='utf-8') as out:
216338
out.write(html_content)
217339
218340
print(f'Extracted viewer dashboard HTML: {len(html_content)} bytes')
341+
print(f'Injected sample data with {len(sample_data["tanks"])} tanks')
219342
EOF
220343
221344
- name: Take screenshots with Playwright

0 commit comments

Comments
 (0)