evcc Solar Charging Management
Expert agent for working with the evcc project - an extensible EV Charge Controller and home energy management system.
Overview
evcc is an open-source system that manages electric vehicle charging, integrates with solar systems, and provides local energy management without cloud dependencies. Built with Go backend and Vue.js frontend using a plugin-based architecture for device integrations.
Key Commands
Build & Development
`make` - Build full application (UI + Go binary)`make build` - Build Go binary only`make ui` - Build UI assets only`make install` - Install Go tools and dependencies`make install-ui` - Install Node.js dependencies`npm run dev` - Start Vue dev server (http://127.0.0.1:7071)Testing & Quality
`make test` - Run Go tests`make test-ui` - Run frontend tests`make lint` - Run Go linting (golangci-lint)`make lint-ui` - Run frontend linting`npm run playwright` - Run integration tests`npx playwright test --debug` - Debug testsDevice Integration
`evcc --template-type [type] --template [file]` - Test device templates`make docs` - Generate template documentationArchitecture
Backend (Go)
**main.go** - Entry point embedding web assets and i18n**cmd/** - CLI commands and application setup**core/** - Business logic (loadpoint.go, site.go) with modules: - **loadpoint/** - EV charging point management
- **planner/** - Smart charging algorithms
- **coordinator/** - Multi-loadpoint coordination
- **session/** - Charging session management
- **vehicle/** - Vehicle-specific logic
- **soc/** - State of charge handling
**api/** - API definitions and types**server/** - HTTP/WebSocket/MQTT/database operations**charger/**, **meter/**, **vehicle/** - Device integrations**tariff/** - Tariff integrations**plugin/** - Plugin system for device communicationFrontend (Vue.js/TypeScript)
**assets/js/** - Main Vue 3 application: - **views/** - Page components (App.vue, Config.vue, Sessions.vue)
- **components/** - Reusable components
- **composables/** - Vue utility functions
- **types/** - TypeScript interfaces
- **utils/** - Helper functions
**assets/css/** - Stylesheets with CSS Custom Properties**i18n/** - English and German translations**tests/** - Playwright integration testsGo Development Guidelines
Core Principles
1. Follow Effective Go idioms and conventions
2. Use `gofmt` for formatting, self-documenting names
3. Handle all errors explicitly with context: `fmt.Errorf("context: %w", err)`
4. Use interfaces for behavior contracts (small, focused)
5. Use `context.Context` for I/O and long-running operations
6. Prefer composition over inheritance
File Patterns
`_blueprint.go` - Templates for new device implementations`_enumer.go` - Generated enum code`*_decorators.go` - Generated decorator implementationsInterface validation: `var _ Interface = (*Type)(nil)`Error Handling
Wrap errors: `fmt.Errorf("context: %w", err)`Use `errors.As` and `errors.Is` for type checkingUse `errors.Join` or custom `joinErrors` for combiningCreate domain-specific error types (ClassError, DeviceError)Use `backoff.Permanent(err)` for non-retryable errorsImplement panic recovery with `defer` and `recover()` in scriptsTesting
Use `testing` package with `testify/assert` and `testify/require`Write table-driven tests with struct definitionsUse `gomock` for mocking; generate with `go:generate mockgen`Test both success and failure scenariosNever manually edit generated filesData Validation
Filter `NaN` and `Infinity` with `math.IsNaN()` and `math.IsInf()`Validate all numeric inputs from external sourcesUse helper functions that reject invalid valuesVue.js/TypeScript Guidelines
Component Development
1. Use Vue 3 Options API (preferred over Composition API)
2. Use `const` for component methods: `const updateType = () =>`
3. Define TypeScript interfaces for props, data, and API responses
4. Implement accessibility (tabindex, aria-label, keyboard handlers)
5. Use early returns for readability
6. Use configured Axios instance for HTTP communication
State Management
Use `reactive()` for simple global state (no Vuex/Pinia)Use global `window.app` ONLY for: - Notifications: `raise()`
- Offline status: `setOffline()`/`setOnline()`
- Clearing notifications: `clear()`
Use localStorage with reactive wrappers for persistenceUse Vue `watch()` for automatic settings synchronizationTypeScript Patterns
Define comprehensive interfaces for API responsesUse enums for constants (e.g., `THEME`, `CURRENCY`)Extend global interfaces for window object augmentationUse union types for flexible configurationsHandle type assertions with proper error handlingStyling
Use CSS Custom Properties for theming: `--evcc-green`, `--evcc-battery`Use existing custom media queries for responsive breakpointsTest with German translations (20-40% longer text)Internationalization
Use `$t()` for all user-facing stringsUpdate both `i18n/en.json` and `i18n/de.json`Use hierarchical namespace: `{section}.{component}.{purpose}`Examples: - `config.vehicle.titleAdd`
- `main.vehicleStatus.charging`
- Actions: `titleAdd`, `titleEdit`, `save`, `cancel`
Use placeholders for dynamic content: `{soc}`, `{duration}`Playwright Integration Testing
Test Structure
**Location**: `tests/*.spec.ts`**Configuration**: Test-specific `.evcc.yaml` files**Utilities**: `tests/utils.ts` for helpers, `tests/evcc.ts` for binary management**Base URL**: `http://127.0.0.1:7070`**Isolation**: Each worker uses different ports and temporary databasesRunning Tests
1. Build before testing: `make ui build` (uses binary)
2. Run tests: `npm run playwright` or `npx playwright test`
3. Debug: `npx playwright test --debug`
4. Specific test: `npx playwright test tests/config-loadpoint.spec.ts`
Selector Strategy (Priority Order)
1. **Semantic**: `getByRole("button", { name: "Add charger" })`
2. **Label**: `getByLabel("Manufacturer").selectOption("Demo charger")`
3. **Text**: `getByText("Save")`
4. **Fallback**: `getByTestId("loadpoint")` (only when necessary)
Test Patterns
Import `{ start, stop, baseUrl }` from `./evcc`Use `test.afterEach(stop)` for cleanupUse `expectModalVisible()` and `expectModalHidden()` helpersTest complete user journeys, not isolated interactionsTest configuration persistence across restartsNever use fixed timeouts; wait for elements or network idleDevice Integration
Plugin System
Device types: chargers, meters, vehicles, tariffsProtocols: Modbus, HTTP, MQTT, JavaScript, GoTemplates: `templates/definition/[type]/`Testing: `evcc --template-type [type] --template [file]`Documentation: `make docs` after template changesConfiguration
Format: YAML (default: `evcc.yaml`, or `--config`)Database: SQLite (default: `evcc.db`, or `--database`)Provide clear validation and error messagesSupport template-based device configs with defaultsImplement proper migrations and data integritySecurity & Performance
Security
Validate all user inputsSanitize data before database storageUse secure protocols (TLS) for integrationsImplement proper authentication/authorizationNever log sensitive data (passwords, tokens, personal info)Performance
Optimize database queries with indexesHandle concurrency safely with Go primitivesImplement proper caching and connection poolingAvoid blocking operations in main loopInclude comments for complex business logicExample Workflows
Adding a New Device Integration
1. Create template in `templates/definition/[type]/`
2. Implement interface in appropriate package (charger/, meter/, vehicle/)
3. Use `_blueprint.go` as starting point
4. Test with: `evcc --template-type [type] --template [file]`
5. Generate docs: `make docs`
6. Add integration tests in `tests/`
Adding a New Frontend Feature
1. Define TypeScript interfaces in `assets/js/types/`
2. Create component in `assets/js/components/`
3. Add i18n strings to `i18n/en.json` and `i18n/de.json`
4. Use semantic CSS Custom Properties for styling
5. Implement accessibility features
6. Write Playwright test in `tests/`
7. Test: `npm run dev` for development, `npm run playwright` for integration
Debugging Device Communication
1. Enable debug logging: `evcc --log debug`
2. Check device template configuration
3. Verify protocol parameters (Modbus address, HTTP endpoints)
4. Test template in isolation: `evcc --template-type [type] --template [file]`
5. Review plugin implementation for error handling
Important Constraints
Always build UI before running Playwright tests: `make ui build`Never manually edit generated files (`_enumer.go`, `*_decorators.go`)Always update both English and German i18n filesUse semantic test selectors; `data-testid` only as fallbackFilter `NaN`/`Infinity` from all external numeric inputsUse `context.Context` for all I/O operationsTest German translations for layout issues (20-40% longer)Always run `make docs` after template changes