mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-29 21:03:40 +00:00
1 line
No EOL
16 KiB
JavaScript
1 line
No EOL
16 KiB
JavaScript
"use strict";(globalThis.webpackChunkdocs_split_developer=globalThis.webpackChunkdocs_split_developer||[]).push([[3976],{2053:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"intro","title":"Developer Documentation","description":"This section contains documentation for contributors and maintainers of the Tibber Prices custom integration.","source":"@site/docs/intro.md","sourceDirName":".","slug":"/intro","permalink":"/hass.tibber_prices/developer/intro","draft":false,"unlisted":false,"editUrl":"https://github.com/jpawlowski/hass.tibber_prices/tree/main/docs/developer/docs/intro.md","tags":[],"version":"current","lastUpdatedAt":1764985026000,"frontMatter":{},"sidebar":"tutorialSidebar","next":{"title":"Architecture","permalink":"/hass.tibber_prices/developer/architecture"}}');var t=i(4848),r=i(8453);const l={},o="Developer Documentation",c={},d=[{value:"\ud83d\udcda Developer Guides",id:"-developer-guides",level:2},{value:"\ud83e\udd16 AI Documentation",id:"-ai-documentation",level:2},{value:"AI-Assisted Development",id:"ai-assisted-development",level:3},{value:"\ud83d\ude80 Quick Start for Contributors",id:"-quick-start-for-contributors",level:2},{value:"\ud83d\udee0\ufe0f Development Tools",id:"\ufe0f-development-tools",level:2},{value:"\ud83d\udce6 Project Structure",id:"-project-structure",level:2},{value:"\ud83d\udd0d Key Concepts",id:"-key-concepts",level:2},{value:"\ud83e\uddea Testing",id:"-testing",level:2},{value:"\ud83d\udcdd Documentation Standards",id:"-documentation-standards",level:2},{value:"\ud83e\udd1d Contributing",id:"-contributing",level:2},{value:"\ud83d\udcc4 License",id:"-license",level:2}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"developer-documentation",children:"Developer Documentation"})}),"\n",(0,t.jsxs)(n.p,{children:["This section contains documentation for contributors and maintainers of the ",(0,t.jsx)(n.strong,{children:"Tibber Prices custom integration"}),"."]}),"\n",(0,t.jsx)(n.admonition,{title:"Community Project",type:"info",children:(0,t.jsxs)(n.p,{children:["This is an independent, community-maintained custom integration for Home Assistant. It is ",(0,t.jsx)(n.strong,{children:"not"})," an official Tibber product and is ",(0,t.jsx)(n.strong,{children:"not"})," affiliated with Tibber AS."]})}),"\n",(0,t.jsx)(n.h2,{id:"-developer-guides",children:"\ud83d\udcda Developer Guides"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/setup",children:"Setup"})})," - DevContainer, environment setup, and dependencies"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/architecture",children:"Architecture"})})," - Code structure, patterns, and conventions"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/period-calculation-theory",children:"Period Calculation Theory"})})," - Mathematical foundations, Flex/Distance interaction, Relaxation strategy"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/timer-architecture",children:"Timer Architecture"})})," - Timer system, scheduling, coordination (3 independent timers)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/caching-strategy",children:"Caching Strategy"})})," - Cache layers, invalidation, debugging"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/testing",children:"Testing"})})," - How to run tests and write new test cases"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/release-management",children:"Release Management"})})," - Release workflow and versioning process"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/coding-guidelines",children:"Coding Guidelines"})})," - Style guide, linting, and best practices"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/refactoring-guide",children:"Refactoring Guide"})})," - How to plan and execute major refactorings"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"-ai-documentation",children:"\ud83e\udd16 AI Documentation"}),"\n",(0,t.jsxs)(n.p,{children:["The main AI/Copilot documentation is in ",(0,t.jsx)(n.a,{href:"https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md",children:(0,t.jsx)(n.code,{children:"AGENTS.md"})}),". This file serves as long-term memory for AI assistants and contains:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Detailed architectural patterns"}),"\n",(0,t.jsx)(n.li,{children:"Code quality rules and conventions"}),"\n",(0,t.jsx)(n.li,{children:"Development workflow guidance"}),"\n",(0,t.jsx)(n.li,{children:"Common pitfalls and anti-patterns"}),"\n",(0,t.jsx)(n.li,{children:"Project-specific patterns and utilities"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Important:"})," When proposing changes to patterns or conventions, always update ",(0,t.jsx)(n.a,{href:"https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md",children:(0,t.jsx)(n.code,{children:"AGENTS.md"})})," to keep AI guidance consistent."]}),"\n",(0,t.jsx)(n.h3,{id:"ai-assisted-development",children:"AI-Assisted Development"}),"\n",(0,t.jsx)(n.p,{children:"This integration is developed with extensive AI assistance (GitHub Copilot, Claude, and other AI tools). The AI handles:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Pattern Recognition"}),": Understanding and applying Home Assistant best practices"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Code Generation"}),": Implementing features with proper type hints, error handling, and documentation"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Refactoring"}),": Maintaining consistency across the codebase during structural changes"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Translation Management"}),": Keeping 5 language files synchronized"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Documentation"}),": Generating and maintaining comprehensive documentation"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Quality Assurance:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Automated linting with Ruff (120-char line length, max complexity 25)"}),"\n",(0,t.jsx)(n.li,{children:"Home Assistant's type checking and validation"}),"\n",(0,t.jsx)(n.li,{children:"Real-world testing in development environment"}),"\n",(0,t.jsx)(n.li,{children:"Code review by maintainer before merging"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Benefits:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Rapid feature development while maintaining quality"}),"\n",(0,t.jsx)(n.li,{children:"Consistent code patterns across all modules"}),"\n",(0,t.jsx)(n.li,{children:"Comprehensive documentation maintained alongside code"}),"\n",(0,t.jsx)(n.li,{children:"Quick bug fixes with proper understanding of context"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Limitations:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"AI may occasionally miss edge cases or subtle bugs"}),"\n",(0,t.jsx)(n.li,{children:"Some complex Home Assistant patterns may need human review"}),"\n",(0,t.jsx)(n.li,{children:"Translation quality depends on AI's understanding of target language"}),"\n",(0,t.jsx)(n.li,{children:"User feedback is crucial for discovering real-world issues"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["If you're working with AI tools on this project, the ",(0,t.jsx)(n.a,{href:"https://github.com/jpawlowski/hass.tibber_prices/blob/v0.20.0/AGENTS.md",children:(0,t.jsx)(n.code,{children:"AGENTS.md"})})," file provides the context and patterns that ensure consistency."]}),"\n",(0,t.jsx)(n.h2,{id:"-quick-start-for-contributors",children:"\ud83d\ude80 Quick Start for Contributors"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Fork and clone"})," the repository"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Open in DevContainer"}),' (VS Code: "Reopen in Container")']}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Run setup"}),": ",(0,t.jsx)(n.code,{children:"./scripts/setup/setup"})," (happens automatically via ",(0,t.jsx)(n.code,{children:"postCreateCommand"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Start development environment"}),": ",(0,t.jsx)(n.code,{children:"./scripts/develop"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Make your changes"})," following the ",(0,t.jsx)(n.a,{href:"/hass.tibber_prices/developer/coding-guidelines",children:"Coding Guidelines"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Run linting"}),": ",(0,t.jsx)(n.code,{children:"./scripts/lint"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Validate integration"}),": ",(0,t.jsx)(n.code,{children:"./scripts/release/hassfest"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Test your changes"})," in the running Home Assistant instance"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Commit using Conventional Commits"})," format"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Open a Pull Request"})," with clear description"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"\ufe0f-development-tools",children:"\ud83d\udee0\ufe0f Development Tools"}),"\n",(0,t.jsxs)(n.p,{children:["The project includes several helper scripts in ",(0,t.jsx)(n.code,{children:"./scripts/"}),":"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"bootstrap"})," - Initial setup of dependencies"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"develop"})," - Start Home Assistant in debug mode (auto-cleans .egg-info)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"clean"})," - Remove build artifacts and caches"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"lint"})," - Auto-fix code issues with ruff"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"lint-check"})," - Check code without modifications (CI mode)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"hassfest"})," - Validate integration structure (JSON, Python syntax, required files)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"setup"})," - Install development tools (git-cliff, @github/copilot)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"prepare-release"})," - Prepare a new release (bump version, create tag)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"generate-release-notes"})," - Generate release notes from commits"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"-project-structure",children:"\ud83d\udce6 Project Structure"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"custom_components/tibber_prices/\n\u251c\u2500\u2500 __init__.py # Integration setup\n\u251c\u2500\u2500 coordinator.py # Data update coordinator with caching\n\u251c\u2500\u2500 api.py # Tibber GraphQL API client\n\u251c\u2500\u2500 price_utils.py # Price enrichment functions\n\u251c\u2500\u2500 average_utils.py # Average calculation utilities\n\u251c\u2500\u2500 sensor/ # Sensor platform (package)\n\u2502 \u251c\u2500\u2500 __init__.py # Platform setup\n\u2502 \u251c\u2500\u2500 core.py # TibberPricesSensor class\n\u2502 \u251c\u2500\u2500 definitions.py # Entity descriptions\n\u2502 \u251c\u2500\u2500 helpers.py # Pure helper functions\n\u2502 \u2514\u2500\u2500 attributes.py # Attribute builders\n\u251c\u2500\u2500 binary_sensor.py # Binary sensor platform\n\u251c\u2500\u2500 entity_utils/ # Shared entity helpers\n\u2502 \u251c\u2500\u2500 icons.py # Icon mapping logic\n\u2502 \u251c\u2500\u2500 colors.py # Color mapping logic\n\u2502 \u2514\u2500\u2500 attributes.py # Common attribute builders\n\u251c\u2500\u2500 services.py # Custom services\n\u251c\u2500\u2500 config_flow.py # UI configuration flow\n\u251c\u2500\u2500 const.py # Constants and helpers\n\u251c\u2500\u2500 translations/ # Standard HA translations\n\u2514\u2500\u2500 custom_translations/ # Extended translations (descriptions)\n"})}),"\n",(0,t.jsx)(n.h2,{id:"-key-concepts",children:"\ud83d\udd0d Key Concepts"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"DataUpdateCoordinator Pattern:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Centralized data fetching and caching"}),"\n",(0,t.jsx)(n.li,{children:"Automatic entity updates on data changes"}),"\n",(0,t.jsxs)(n.li,{children:["Persistent storage via ",(0,t.jsx)(n.code,{children:"Store"})]}),"\n",(0,t.jsx)(n.li,{children:"Quarter-hour boundary refresh scheduling"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Price Data Enrichment:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Raw API data is enriched with statistical analysis"}),"\n",(0,t.jsx)(n.li,{children:"Trailing/leading 24h averages calculated per interval"}),"\n",(0,t.jsx)(n.li,{children:"Price differences and ratings added"}),"\n",(0,t.jsxs)(n.li,{children:["All via pure functions in ",(0,t.jsx)(n.code,{children:"price_utils.py"})]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Translation System:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Dual system: ",(0,t.jsx)(n.code,{children:"/translations/"})," (HA schema) + ",(0,t.jsx)(n.code,{children:"/custom_translations/"})," (extended)"]}),"\n",(0,t.jsx)(n.li,{children:"Both must stay in sync across all languages (de, en, nb, nl, sv)"}),"\n",(0,t.jsx)(n.li,{children:"Async loading at integration setup"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"-testing",children:"\ud83e\uddea Testing"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"# Validate integration structure\n./scripts/release/hassfest\n\n# Run all tests\npytest tests/\n\n# Run specific test file\npytest tests/test_coordinator.py\n\n# Run with coverage\npytest --cov=custom_components.tibber_prices tests/\n"})}),"\n",(0,t.jsx)(n.h2,{id:"-documentation-standards",children:"\ud83d\udcdd Documentation Standards"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"User-facing docs"})," go in ",(0,t.jsx)(n.code,{children:"docs/user/"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Developer docs"})," go in ",(0,t.jsx)(n.code,{children:"docs/development/"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"AI guidance"})," goes in ",(0,t.jsx)(n.code,{children:"AGENTS.md"})]}),"\n",(0,t.jsx)(n.li,{children:"Use clear examples and code snippets"}),"\n",(0,t.jsx)(n.li,{children:"Keep docs up-to-date with code changes"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"-contributing",children:"\ud83e\udd1d Contributing"}),"\n",(0,t.jsxs)(n.p,{children:["See ",(0,t.jsx)(n.a,{href:"https://github.com/jpawlowski/hass.tibber_prices/blob/main/CONTRIBUTING.md",children:"CONTRIBUTING.md"})," for detailed contribution guidelines, code of conduct, and pull request process."]}),"\n",(0,t.jsx)(n.h2,{id:"-license",children:"\ud83d\udcc4 License"}),"\n",(0,t.jsxs)(n.p,{children:["This project is licensed under the ",(0,t.jsx)(n.a,{href:"https://github.com/jpawlowski/hass.tibber_prices/blob/main/LICENSE",children:"Apache License 2.0"}),"."]}),"\n",(0,t.jsx)(n.hr,{}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," This documentation is for developers. End users should refer to the ",(0,t.jsx)(n.a,{href:"https://jpawlowski.github.io/hass.tibber_prices/user/",children:"User Documentation"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}}}]); |