-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add room type templates for timer presets #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add pre-configured timer templates for 7 common room types to eliminate manual configuration trial-and-error. Templates: - Bedroom (long occupancy, minimal motion) - Bathroom (quick visits, steam affects sensors) - Home Office (desk work, minimal movement) - Kitchen (intermittent motion during cooking) - Living Room (TV watching, relaxed activities) - Hallway/Corridor (fast transit, short occupancy) - Storage/Garage (quick item retrieval) Features: - Template selection in pairing flow (first step with explanation) - Template dropdown in device settings (pre-fills timer values) - No template name storage (only timer values persisted) - Dropdown auto-resets after application - Full i18n support (en, nl, de, no, sv) - Comprehensive unit tests (35 new tests, all passing) - Detailed user documentation Implementation: - lib/RoomTemplates.ts: TypeScript constants with type-safe interfaces - Settings handler in device.ts applies templates and resets dropdown - Pairing handler in driver.ts applies templates during device creation - HTML pairing page displays templates with timer value previews - Settings dropdown in driver.settings.compose.json Technical details: - Template values from GitHub issue #59 specifications - Settings page uses Homey's onSettings lifecycle (no custom frontend JS) - Pairing flow adds select_room_type as first step - All validation checks pass (build, lint, tests, Homey validate) Closes #59
Code Review FindingsI've completed a comprehensive review of PR #60. Below are the four most critical findings that should be addressed: 🔴 CRITICAL: Duplicated Template Data (Confidence: 95%)Location: Issue: The room template data is hardcoded in the HTML file's JavaScript, creating a duplicate of the data already defined in Impact:
Suggested Fix:
Example (Option 3): // In driver.ts
session.setHandler('get_room_templates', async () => {
return getAllTemplates().map(t => ({
id: t.id,
name: t.name.en, // Or use locale
description: t.description.en,
timerValues: t.timerValues
}));
});Then fetch in HTML: function onHomeyReady(Homey) {
Homey.emit('get_room_templates', null, (err, templates) => {
if (!err) {
ROOM_TEMPLATES = templates;
renderTemplates();
}
});
}🟠 IMPORTANT: Potential Settings Race Condition (Confidence: 88%)Location: Issue: The Current Code: await this.setSettings({
t_enter: timers.t_enter,
t_clear: timers.t_clear,
stalePirMinutes: timers.stalePirMinutes,
staleDoorMinutes: timers.staleDoorMinutes,
room_template_selector: '', // Reset dropdown
});
return; // Settings change will trigger another onSettings callSuggested Fix: // At the start of onSettings
if (event.changedKeys.includes('room_template_selector') &&
event.newSettings.room_template_selector === '') {
// Skip if selector was just reset to empty
return;
}Or use a flag to track if this is a programmatic update: private isApplyingTemplate = false;
async onSettings(event) {
if (this.isApplyingTemplate) {
this.isApplyingTemplate = false;
return;
}
if (event.changedKeys.includes('room_template_selector')) {
const templateId = event.newSettings.room_template_selector as string;
if (templateId && templateId !== '') {
const timers = getTemplateTimers(templateId);
if (timers) {
this.isApplyingTemplate = true;
await this.setSettings({ ...timers, room_template_selector: '' });
return;
}
}
}
// ... rest of handler
}🟠 IMPORTANT: Missing Error Handling in Pairing HTML (Confidence: 85%)Location: Issue: The pairing page assumes Current Code: if (typeof Homey !== 'undefined') {
onHomeyReady(Homey);
}Suggested Fix: function initializePage() {
if (typeof Homey === 'undefined') {
// Show error message to user
document.body.innerHTML =
'<div style="padding: 20px; color: red;">' +
'<h2>Error: Homey SDK not loaded</h2>' +
'<p>Please try restarting the pairing process.</p>' +
'</div>';
console.error('Homey SDK not available');
return;
}
try {
onHomeyReady(Homey);
} catch (error) {
console.error('Failed to initialize pairing page:', error);
// Show error to user
}
}
// Use DOMContentLoaded to ensure page is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializePage);
} else {
initializePage();
}🟡 MINOR: Deprecated Method Usage (Confidence: 82%)Location: Issue: Uses deprecated Current Code: id: `wiab-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,Suggested Fix: id: `wiab-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
// or
id: `wiab-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,Merge Recommendation: ✅ Approve with Minor FixesOverall Assessment: Strengths:
Required Fixes Before Merge:
Optional Improvements: Recommendation: Once the critical and important findings are resolved, this PR will be ready to merge. Excellent work on the comprehensive implementation and testing! 🎉 |
Comprehensive PR Review - Final AssessmentI've completed a multi-agent review of PR #60 covering code quality, test coverage, documentation accuracy, error handling, and type design. Manual testing confirms the feature works, but several critical issues must be addressed before merge. 🔴 CRITICAL ISSUES (Must Fix)1. Documentation Claims Non-Existent Features
|
- Replace deprecated substr() with substring() in device ID generation - Fix documentation errors claiming non-existent runtime template feature - Add comprehensive error handling to pairing HTML (emit callbacks, Homey API availability check) - Add input validation for template timer values in driver All Priority 1 issues from PR review resolved. All tests pass.
✅ Priority 1 Fixes CompletedAll critical issues from the review have been addressed and pushed to this PR branch: Fixed Issues:
Test Results:Commit:
Ready for re-review! All Priority 1 items resolved. Priority 2 items (integration tests, template data deduplication) can be follow-up PRs if needed. |
Priority 2 improvements based on PR review: 1. Driver Integration Tests (21 tests) - Created MockPairSession test helper for pairing flow testing - Added comprehensive tests for all pairing handlers - Added end-to-end pairing flow validation - Added Driver mock to Homey SDK mock 2. Enhanced Error Messages - get_motion_devices: specific error messages for API unavailable, timeout, and permission issues - get_contact_devices: same specific error handling - get_room_templates: clear error message with restart guidance - Better user guidance for troubleshooting pairing failures 3. Template Deduplication - Removed hardcoded template array from select_room_type.html - Added get_room_templates handler to dynamically serve templates - Templates now defined once in RoomTemplates.ts (single source of truth) - Added error handling and user feedback for template loading failures All tests passing (149/149). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Final PR Review - PR #60: Room Type TemplatesI've conducted a comprehensive review using 5 specialized agents analyzing code quality, test coverage, documentation, error handling, and type design. Here are the findings: ✅ Verification of Previous FixesAll Priority 1 and Priority 2 issues from the previous review have been properly addressed: Priority 1 Fixes ✅
Priority 2 Fixes ✅
🚨 BLOCKING ISSUE - Must Fix Before MergeIssue #1: ESLint Errors - Function Type UsageSeverity: CRITICAL (Blocks CI pipeline) Problem: MockPairSession uses banned Fix Required: Impact: CI will fail until fixed (per CLAUDE.md pre-commit checklist)
|
| Component | Tests | Coverage Quality | Critical Gaps |
|---|---|---|---|
| RoomTemplates module | 50+ | Excellent ✅ | None |
| Integration flows | 2 | Excellent ✅ | None |
| select_room_type validation | 6 | Excellent ✅ | Minor |
| get_room_templates | 2 | Good | Error handling untested |
| Enhanced error messages | 0 | None |
Critical feature untested |
| Device creation | 3 | Good | Boundary values |
Total: 149 tests passing, 70%+ coverage maintained
🎯 Type Design Analysis
Overall Rating: 5.5/10 - Functional but lacks invariant enforcement
Strengths:
- Clear documentation with units and purpose
- Comprehensive testing validates invariants
- Good use of readonly modifiers
Improvements Recommended (non-blocking):
- Add
TIMER_CONSTRAINTSconstant for validation ranges (reduce duplication) - Add
RoomTemplateIdunion type for type-safe template lookups - Make
TimerValuesreadonly to prevent mutation - Move
isValidTimerValues()to RoomTemplates.ts (single source of truth)
⚡ Other Findings
Jest Force Exit Warning
Tests show "A worker process has failed to exit gracefully" - likely a test resource leak. Not blocking but should be investigated.
Positive Observations 👍
- Excellent JSDoc documentation throughout
- Comprehensive input validation with range checking
- Well-structured test architecture (MockPairSession)
- Proper internationalization support (5 languages)
- Clean separation of concerns (data, logic, UI)
- Good error context in log messages
🎯 Merge Recommendation
Status: CONDITIONAL APPROVE - 1 Blocking Issue
Before Merge (MUST FIX):
- ✅ Fix ESLint errors in
tests/unit/driver.test.ts(replaceFunctiontype)
Strongly Recommended Before Merge:
2.
3.
Can Be Addressed in Follow-up PR:
- Silent validation failure handling
- Error ID constants
- Catch block specificity
- Type design improvements
Summary
This is a well-implemented feature with thorough testing of core functionality. The code quality is high and follows CLAUDE.md guidelines. However:
- One blocking issue (lint errors) must be fixed for CI to pass
- Two high-priority issues (error handling tests, documentation) should be addressed for production quality
- Medium-priority improvements can be deferred to follow-up work
Once the ESLint error is fixed, this PR is technically ready to merge. Addressing the error handling tests and documentation would raise it from "good" to "excellent" quality.
Recommended Action: Fix the lint error, then decide whether to merge or address high-priority issues first based on release timeline.
Fixed ESLint error in MockPairSession test helper: - Replaced banned `Function` type with properly typed function signature - Used `any` return type for getHandler (appropriate for test mocks) - Added ESLint disable comments for intentional `any` usage - All 149 tests passing, linting clean Resolves blocking issue identified in PR review. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
This commit resolves all high and medium priority issues identified in the comprehensive PR review, improving code quality, error handling, and test coverage. ## High Priority Fixes ### 1. Documentation Accuracy (docs/ROOM_TEMPLATES.md:285-286) - Fixed incorrect FAQ claiming templates can be reapplied - Clarified templates are only available during initial pairing - Updated answer to reflect actual behavior ### 2. Error ID Constants (constants/errorIds.ts) - Created PairingErrorId enum with 4 error codes - TEMPLATES_LOAD_FAILED = 'PAIRING_001' - MOTION_DEVICES_FETCH_FAILED = 'PAIRING_002' - CONTACT_DEVICES_FETCH_FAILED = 'PAIRING_003' - INVALID_TIMER_VALUES = 'PAIRING_004' - Updated all driver handlers to use constants instead of hardcoded strings ### 3. Error Handling Tests (tests/unit/driver.test.ts) - Added 7 new error handling tests for pairing handlers - Tests for get_motion_devices error scenarios (4 tests) - Homey API not available - Timeout errors - Permission denied - Unexpected errors - Tests for get_contact_devices error scenarios (3 tests) - All tests verify error IDs and friendly user messages ## Medium Priority Fixes ### 4. Silent Validation Failure (driver.ts:183-185) - Changed select_room_type handler to throw instead of returning error object - Prevents confusing UX where invalid templates appear accepted - Updated HTML to remove success check (now properly throws on validation failure) - Updated 4 existing tests to expect throws instead of return values ### 5. Overly Broad Catch Blocks (driver.ts:201-229, 236-264) - Refactored get_motion_devices and get_contact_devices handlers - Now only catches expected, user-actionable errors - Re-throws unexpected errors with full context for debugging - Prevents hiding programming errors behind generic messages - Specific handling for: - "Homey API not available" → initialization message - "timeout" → network connection message - "permission" → app permissions message - Unexpected errors → logged and re-thrown ## Test Results - All 156 tests passing (added 7 new error handling tests) - TypeScript builds successfully - ESLint passes with no errors - 70%+ test coverage maintained ## Impact - Better error tracking via centralized error IDs - Improved user experience with context-specific error messages - More robust error handling that doesn't hide unexpected errors - Comprehensive test coverage for error scenarios - Accurate documentation that matches actual behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
✅ Final PR Review - PR #60: Room Type Templates (All Fixes Applied)I've conducted a final comprehensive review using 3 specialized agents after all fixes were applied. This review verifies that all previous issues have been resolved and the PR is production-ready. 🎯 Verification of All Fixes✅ BLOCKING ISSUE - FixedESLint Errors (
✅ HIGH PRIORITY ISSUES - All Fixed
✅ MEDIUM PRIORITY ISSUES - All Fixed
📊 Quality Metrics
Test Coverage Breakdown
🏆 Exceptional Quality Highlights1. Error Handling ExcellenceStructured Error IDs: // All errors use centralized constants
this.error(`[${PairingErrorId.MOTION_DEVICES_FETCH_FAILED}] HomeyAPI not available`, error);User-Actionable Messages:
Specific Error Catching: // Only catches expected errors
if (error.message === 'Homey API not available') { ... }
if (error.message.includes('timeout')) { ... }
if (error.message.includes('permission')) { ... }
// Re-throws unexpected errors for debugging
this.error(`[PAIRING_002] Unexpected error:`, error);
throw error;2. Comprehensive Test CoverageError Scenario Tests:
Validation Tests:
3. Code QualityConsistency:
Maintainability:
🔍 Agent Findings SummaryCode Reviewer AgentVerdict: ✅ APPROVE FOR MERGE
Test Coverage AnalyzerVerdict: ✅ PRODUCTION-READY
Error Handling AuditorVerdict: ✅ PRODUCTION READY
📝 Remaining Observations (Not Blocking)
Both are cosmetic issues that don't affect PR quality or merge readiness. 🎯 Final RecommendationAPPROVED - READY TO MERGE ✅This PR demonstrates exceptional attention to quality: Why This PR Excels:
Impact:
This PR sets a high standard for error handling and test coverage in the codebase. The implementation is robust, well-tested, and ready for production use. Merge with confidence. 🚀 |
Summary
Add pre-configured timer templates for 7 common room types, eliminating manual configuration trial-and-error.
Implements GitHub issue #59.
Features
Template Values (from issue #59 spec)
Implementation Details
Architecture
Key Decisions
Files Changed
Created:
lib/RoomTemplates.ts- Template data and helper functionsdrivers/wiab-device/pair/select_room_type.html- Pairing step HTMLtests/unit/RoomTemplates.test.ts- 35 unit tests (all passing)docs/ROOM_TEMPLATES.md- Comprehensive user documentationModified:
drivers/wiab-device/device.ts- Settings handler for template applicationdrivers/wiab-device/driver.ts- Pairing handler for template applicationdrivers/wiab-device/driver.settings.compose.json- Template dropdowndrivers/wiab-device/driver.compose.json- Pairing flow with new stepTesting
Test Plan
Manual Testing
Pairing flow:
Settings page:
Skip functionality:
User Experience
Benefits
Migration Notes
Documentation
docs/ROOM_TEMPLATES.mdCloses
Closes #59
Ready for review! All acceptance criteria from issue #59 met: