diff --git a/.cursorrules b/.cursorrules new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/.cursorrules @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 120000 index 000000000..be77ac83a --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1 @@ +../AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..19581aadd --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,244 @@ +# Agent Rules for evcc Project + +This file provides guidance to AI coding agents when working with code in this repository. + +## Project Overview + +- evcc is an extensible EV Charge Controller and home energy management system written in Go with a Vue.js frontend +- The system manages electric vehicle charging, integrates with solar systems, and provides local energy management without cloud dependencies +- Architecture follows a plugin-based approach for device integrations + +## Essential Commands + +- `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 ci`) +- `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 dev` - start Vue dev server (http://127.0.0.1:7071) +- `npm run playwright` - run integration tests +- `evcc --template-type [type] --template [file]` - test device templates +- `make docs` - generate template documentation + +## Architecture Guidelines + +### Core Components + +- **main.go** serves as entry point and embeds web assets and i18n files +- **cmd/** contains CLI commands, application setup, and various utility commands (configure, detect, migrate, etc.) +- **core/** contains core business logic with main files (loadpoint.go, site.go) and subdirectories: + - **loadpoint/** - EV charging point management modules + - **planner/** - Smart charging planning algorithms + - **coordinator/** - Multi-loadpoint coordination logic + - **session/** - Charging session management + - **vehicle/** - Vehicle-specific core logic + - **soc/** - State of charge handling +- **api/** contains API definitions and types +- **server/** handles HTTP server, WebSocket, MQTT, database operations, and various handlers +- **charger/**, **meter/**, **vehicle/** contain device integrations +- **tariff/** contains tariff integrations +- **plugin/** implements plugin system for device and tariff communication +- **assets/** contains Vue.js frontend application + +### Frontend Structure + +- **assets/js/** contains the main TypeScript/Vue.js application with: + - **views/** - Vue page components (App.vue, Config.vue, Sessions.vue, etc.) + - **components/** - Reusable Vue components + - **composables/** - Vue utility functions + - **types/** - TypeScript type definitions + - **utils/** - Utility functions + - **mixins/** - Vue mixins +- **assets/css/** contains application stylesheets +- **assets/public/** contains static assets and metadata +- **i18n/** contains internationalization files +- **tests/** contains Playwright integration tests and test configuration files +- **dist/** contains built frontend assets (generated) + +## Go Coding Standards + +### Core Principles + +- Follow Go idioms and conventions (Effective Go) +- Use `gofmt` for formatting, self-documenting names, early returns +- Handle all errors explicitly with meaningful messages +- Use interfaces for behavior contracts (small, focused, single responsibility) +- Use `context.Context` for I/O, long-running, or cancelable operations +- Organize code into logical packages with clear responsibilities +- Prefer composition over inheritance, minimize external dependencies + +### File Patterns + +- `_blueprint.go` - templates for new device implementations +- `_enumer.go` - generated enum code +- `*_decorators.go` - generated decorator pattern implementations +- Validate interface implementations: `var _ Interface = (*Type)(nil)` + +### Error Handling + +- Wrap errors with context: `fmt.Errorf("context: %w", err)` +- Use `errors.As` and `errors.Is` for type checking +- Use `errors.Join` for combining errors (prefer custom `joinErrors` helper) +- Create domain-specific error types (ClassError, DeviceError) +- Use `backoff.Permanent(err)` for non-retryable errors +- Implement panic recovery with `defer` and `recover()` in script contexts + +### Testing & Code Generation + +- Use `testing` package with `testify/assert` and `testify/require` +- Table-driven tests with struct definitions for multiple cases +- Use `gomock` for interface mocking, `go:generate mockgen` for generation +- Test both success and failure scenarios, use `require` for setup, `assert` for tests +- Use `go:generate` for code generation, regenerate after interface/enum changes +- Never manually edit generated files + +### Context & Concurrency + +- Use `context.Context` as first parameter for I/O operations +- Use `context.WithTimeout`, `context.WithCancel` appropriately +- Check `ctx.Done()` in long-running loops +- Propagate context through goroutines for proper cancellation +- Handle concurrent operations safely with Go's concurrency primitives + +### Data Validation + +- Filter `NaN` and `Infinity` values using `math.IsNaN()` and `math.IsInf()` +- Validate numeric inputs from external sources +- Use helper functions like `parseFloat()` that reject invalid values + +## Vue.js/TypeScript Frontend Standards + +### Core Architecture + +- Use Vue 3 Options API (preferred over Composition API) +- Use reactive stores without Vuex/Pinia for cross-component state +- Use global app instance (`window.app`) only for: notifications (`raise()`), offline status (`setOffline()`/`setOnline()`), clearing notifications (`clear()`) +- Organize components by feature/domain in `assets/js/components/` subdirectories + +### Component Development + +- Use TypeScript for all new frontend code +- Use `const` instead of `function` for component methods (e.g., `const updateType = () =>`) +- Define TypeScript interfaces for component props, data, and API responses +- Implement accessibility features (tabindex, aria-label, keyboard handlers) +- Use descriptive names for variables, functions, and event handlers +- Use early returns for readability +- Use configured Axios instance for HTTP communication + +### State Management + +- Use `reactive()` from Vue for simple global state +- Implement property setters for nested object updates using helper functions +- Use localStorage with reactive wrappers for persistent settings +- Use Vue `watch()` for automatic persistence of settings changes +- Separate concerns with dedicated stores (settings, application state) + +### TypeScript Patterns + +- Define comprehensive interfaces for API responses and application state +- Use enums for constants (e.g., `THEME`, `CURRENCY`) +- Extend global interfaces for window object augmentation +- Use union types for flexible but type-safe configurations +- Use generic types for reusable utility functions +- Handle type assertions carefully with proper error handling +- Create focused utility functions with proper TypeScript typing + +### Styling & Internationalization + +- Use CSS Custom Properties for theming (semantic names: `--evcc-green`, `--evcc-battery`) +- Use existing custom media queries for responsive breakpoints +- Use `$t()` function for all user-facing strings +- Update both `i18n/en.json` and `i18n/de.json` for new strings +- Use hierarchical namespace: `{section}.{component}.{purpose}` +- Examples: `config.vehicle.titleAdd`, `main.vehicleStatus.charging` +- Action patterns: `titleAdd`, `titleEdit`, `save`, `cancel`, `delete`, `validateSave` +- Use placeholders for dynamic content: `{soc}`, `{duration}`, `{value}` +- Prefer context-specific keys over generic ones +- Test with German translations (20-40% longer text) + +### Testing + +- Write integration tests using Playwright for user workflows +- Use Storybook for component development and visual testing +- Use semantic selectors (roles, labels, button text); `data-testid` only when necessary +- Test error states and loading states + +## Playwright Integration Testing + +### Test Organization + +- **Location**: `tests/` directory with `.spec.ts` files +- **Configuration**: `.evcc.yaml` files for different test scenarios +- **Utilities**: `tests/utils.ts` for common helpers, `tests/evcc.ts` for binary management +- **Categories**: `config-*.spec.ts` (UI config), `sessions.spec.ts`/`plan.spec.ts` (workflows), `smart-cost.spec.ts`/`limits.spec.ts` (features), `backup-restore.spec.ts`/`auth.spec.ts` (integration) + +### Test Configuration + +- Base URL: `http://127.0.0.1:7070` +- Parallel execution with different ports per worker for isolation +- Uses `./evcc` binary with test-specific configuration files +- Each worker uses isolated temporary database files +- Always runs with English UI language + +### Essential Commands + +- Must build before testing: `make ui build` +- Run tests: `npm run playwright` or `npx playwright test` +- Debug: `npx playwright test --debug` +- Specific test: `npx playwright test tests/config-loadpoint.spec.ts` + +### Selector Strategy + +- **Preferred**: Semantic selectors using `getByRole()`, `getByLabel()`, `getByText()` +- **Fallback**: `data-testid` only when semantic selectors aren't available +- **Examples**: + - `page.getByRole("button", { name: "Add charger" })` + - `page.getByLabel("Manufacturer").selectOption("Demo charger")` + - `page.getByTestId("loadpoint")` (fallback only) + +### Test Patterns + +- Use test-specific `.evcc.yaml` configurations +- Import utilities from `tests/utils.ts` for common operations +- Focus on complete user journeys rather than isolated interactions +- Use `expectModalVisible()` and `expectModalHidden()` helpers +- Test configuration persistence across application restarts +- Standard structure: import `{ start, stop, baseUrl }` from `./evcc`, use `test.afterEach(stop)` + +## Device Integration & Configuration + +### Plugin System + +- Device types: chargers, meters, vehicles, tariffs +- Plugin protocols: Modbus, HTTP, MQTT, JavaScript, Go +- Define device capabilities and configuration in templates at `templates/definition/[type]/` +- Test templates: `evcc --template-type [type] --template [file]` +- Update docs after template changes: `make docs` + +### Configuration + +- Use YAML format for all configuration files (default: `evcc.yaml`, or specify with `--config`) +- Provide clear validation and error messages for invalid configurations +- Support template-based device configurations with meaningful defaults +- Use SQLite as default database (default: `evcc.db`, or specify with `--database`) with proper migrations and data integrity + +## Security & Performance Guidelines + +### Security + +- Validate all user inputs and sanitize data before database storage +- Use secure protocols (TLS) for external integrations +- Implement proper authentication and authorization +- Never log sensitive information (passwords, tokens, personal data) + +### Performance + +- Optimize database queries with appropriate indexes +- Handle concurrent operations safely with Go's concurrency primitives +- Implement proper caching strategies and connection pooling +- Avoid blocking operations in main application loop +- Include appropriate comments for complex business logic diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f0075cf4e..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,124 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -evcc is an extensible EV Charge Controller and home energy management system written in Go with a Vue.js frontend. It manages electric vehicle charging, integrates with solar systems, and provides local energy management without cloud dependencies. - -## Core Development Commands - -### Build & Development - -- `make` - Build the full application (UI + Go binary) -- `make build` - Build Go binary only -- `make ui` - Build UI assets only -- `go run ./...` - Run without building binary -- `./evcc` - Run the built binary -- `./evcc --demo` - Run with demo configuration - -### Dependencies - -- `make install` - Install Go tools and dependencies -- `make install-ui` - Install Node.js dependencies (`npm ci`) - -### Testing & Quality - -- `make test` - Run Go tests -- `make test-ui` - Run frontend tests (`npm test`) -- `make lint` - Run Go linting (golangci-lint) -- `make lint-ui` - Run frontend linting (Prettier, ESLint, TypeScript) - -### Frontend Development - -- `npm run dev` - Start Vue dev server (http://127.0.0.1:7071) -- `npm run storybook` - Run Storybook (http://127.0.0.1:6006) -- `npm run playwright` - Run integration tests -- `npm run simulator` - Run device simulator (http://localhost:7072) - -### Device Templates - -- `evcc --template-type charger --template new-charger-template.yaml` - Test device templates -- `make docs` - Generate template documentation - -## Architecture - -### Core Components - -- **main.go** - Entry point, embeds web assets and i18n files -- **cmd/** - CLI commands and application setup -- **core/** - Core business logic: - - **loadpoint.go** - EV charging point management - - **site.go** - Site-wide energy management - - **planner/** - Smart charging planning - - **coordinator/** - Multi-loadpoint coordination -- **api/** - API definitions and types -- **server/** - HTTP server, WebSocket, MQTT, and database -- **charger/**, **meter/**, **vehicle/** - Device integrations -- **tariff/** - Tariff integrations -- **plugin/** - Plugin system for device and tariff communication -- **assets/** - Vue.js frontend application - -### Frontend Structure - -- **assets/js/** - TypeScript/Vue.js application -- **assets/views/** - Vue components and pages -- **i18n/** - Internationalization files -- **dist/** - Built frontend assets (generated) - -### Configuration - -- Uses YAML configuration files -- Templates in `templates/definition/` for device and tariff configurations -- Database: SQLite (default: `evcc.db`) - -## Key Development Patterns - -### Device Integration - -- Device types: chargers, meters, vehicles (and tariffs) -- Plugin system supports: Modbus, HTTP, MQTT, JavaScript, Go -- Templates define device capabilities and configuration -- Use `_blueprint.go` as starting point for new Go implementations - -### Testing - -- Go tests use standard `testing` package -- Frontend tests use Vitest -- Integration tests use Playwright -- Simulator available for testing without real devices - -### Internationalization - -- Translations managed via Weblate -- Update both `i18n/de.json` and `i18n/en.json` for new strings -- Use `$t()` function in Vue components - -## Important File Locations - -- Configuration: `evcc.yaml` (or specified with `--config`) -- Database: `evcc.db` (or specified with `--database`) -- Device templates: `templates/definition/` -- Web assets: `assets/` (source), `dist/` (built) -- Generated code: Files ending in `_enumer.go`, `*_decorators.go` - -## Common Development Workflows - -### Adding New Device Support - -1. Create template in `templates/definition/[type]/` -2. If Go code needed, implement in respective package -3. Test with `evcc --template-type [type] --template [file]` -4. Run `make docs` to update documentation - -### Frontend Development - -1. Start backend: `make build && ./evcc` -2. Start frontend dev server: `npm run dev` -3. Access development UI at http://127.0.0.1:7071 - -### Integration Testing - -1. Build application: `make ui build` -2. Run tests: `npm run playwright` -3. Use simulator for device testing: `npm run simulator` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file