ekstremedia / laravel-netatmo-weather
A Laravel package for integrating Netatmo Weather Station API with your Laravel application
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Language:Blade
pkg:composer/ekstremedia/laravel-netatmo-weather
Requires
- php: ^8.2
- illuminate/database: ^11.0|^12.0
- illuminate/http: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.17
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
This package is auto-updated.
Last update: 2025-11-07 22:28:30 UTC
README
A Laravel package for integrating Netatmo Weather Station API with your Laravel application. This package provides an easy-to-use interface for authenticating with Netatmo, fetching weather data, and storing it in your database.
Features
- OAuth2 authentication with Netatmo API
- Automatic token refresh
- Fetch and store weather station data
- Support for multiple weather stations per user
- Device selection - Manage multiple Netatmo devices with manual device selection for each configuration
- Module lifecycle management - Automatic archiving of disconnected/removed modules with manual deletion
- Public sharing - Share weather data publicly with customizable per-station access
- Built-in database models and migrations
- Encrypted storage of sensitive credentials
- Configurable caching of weather data
- Full UI scaffolding (optional)
Requirements
- PHP 8.2 or higher
- Laravel 11.0 or 12.0
- A Netatmo Weather Station
- Netatmo API credentials (Client ID and Client Secret)
Installation
1. Install the package via Composer
composer require ekstremedia/laravel-netatmo-weather
2. Publish the configuration file
php artisan vendor:publish --tag=config --provider="Ekstremedia\NetatmoWeather\NetatmoWeatherServiceProvider"
3. Publish the public assets (optional, if using the included UI)
php artisan vendor:publish --tag=public --provider="Ekstremedia\NetatmoWeather\NetatmoWeatherServiceProvider"
4. Run the migrations
php artisan migrate
Configuration
1. Get Netatmo API Credentials
- Go to Netatmo Developer Portal
- Create an app or use an existing one
- Copy your Client ID and Client Secret
2. Configure your environment
Add the following to your .env file:
NETATMO_AUTH_URL=https://api.netatmo.com/oauth2/authorize NETATMO_TOKEN_URL=https://api.netatmo.com/oauth2/token NETATMO_API_URL=https://api.netatmo.com/api # Optional: Customize the User model # NETATMO_USER_MODEL=App\Models\User
3. Configure the package
The configuration file config/netatmo-weather.php contains:
return [ 'name' => 'Laravel Netatmo Weather', // The User model that will be used to associate with Netatmo stations 'user_model' => env('NETATMO_USER_MODEL', 'App\Models\User'), // Netatmo API URLs 'netatmo_auth_url' => env('NETATMO_AUTH_URL', 'https://api.netatmo.com/oauth2/authorize'), 'netatmo_token_url' => env('NETATMO_TOKEN_URL', 'https://api.netatmo.com/oauth2/token'), 'netatmo_api_url' => env('NETATMO_API_URL', 'https://api.netatmo.com/api'), ];
Usage
Using the Service
use Ekstremedia\NetatmoWeather\Services\NetatmoService; use Ekstremedia\NetatmoWeather\Models\NetatmoStation; // Get the service instance $netatmoService = app(NetatmoService::class); // Find a weather station $weatherStation = NetatmoStation::first(); // Fetch data from Netatmo API // This will automatically cache data for 10 minutes $data = $netatmoService->getStationData($weatherStation);
Using the Models
use Ekstremedia\NetatmoWeather\Models\NetatmoStation; use Ekstremedia\NetatmoWeather\Models\NetatmoModule; use Ekstremedia\NetatmoWeather\Models\NetatmoToken; // Get all weather stations $stations = NetatmoStation::all(); // Get a station with its modules $station = NetatmoStation::with('modules')->first(); // Check if token is valid if ($station->token->hasValidToken()) { echo "Token is valid!"; } // Manually refresh token $station->token->refreshToken(); // Access module data foreach ($station->modules as $module) { echo "Module: {$module->module_name}\n"; echo "Type: {$module->type}\n"; echo "Battery: {$module->battery_percent}%\n"; }
Using the UI (Optional)
If you want to use the included UI scaffolding, the package provides routes and controllers:
// In your routes/web.php or through the package routes // The following routes are automatically registered: Route::get('/netatmo', [NetatmoStationController::class, 'index'])->name('netatmo.index'); Route::get('/netatmo/create', [NetatmoStationController::class, 'create'])->name('netatmo.create'); Route::post('/netatmo', [NetatmoStationController::class, 'store'])->name('netatmo.store'); Route::get('/netatmo/{weatherstation}', [NetatmoStationController::class, 'show'])->name('netatmo.show'); Route::get('/netatmo/{weatherstation}/edit', [NetatmoStationController::class, 'edit'])->name('netatmo.edit'); Route::put('/netatmo/{weatherstation}', [NetatmoStationController::class, 'update'])->name('netatmo.update'); Route::delete('/netatmo/{weatherstation}', [NetatmoStationController::class, 'destroy'])->name('netatmo.destroy');
Visit /netatmo in your browser to manage your weather stations.
Public Sharing
The package supports public sharing of weather station data. Each station can be individually configured for public access:
Enabling Public Access
Via the UI:
- Navigate to your weather station detail page
- Use the toggle switch in the "Public Access" section
- Copy the generated public URL to share
Or in the edit form:
- Check the "Make this station publicly accessible" checkbox when creating or editing a station
Programmatically:
$station = NetatmoStation::find($id); $station->update(['is_public' => true]);
Public Route
Once enabled, your weather station data will be accessible at:
/netatmo/public/{station-uuid}
This route:
- Does not require authentication
- Shows a clean, minimal view with only weather widgets
- Returns 404 if the station is not marked as public
- Returns 503 if data is temporarily unavailable
Security
- Only stations explicitly marked as
is_public = trueare accessible - OAuth tokens and credentials are never exposed
- Station owners maintain full control over public access
- Public URLs use UUIDs for non-sequential identification
Device Selection
If your Netatmo account has access to multiple weather stations, the package will prompt you to select which physical device each configuration should display data from.
Multiple Weather Stations: Two Approaches
Option 1: Shared Access (Recommended)
- Have others share their weather stations with your Netatmo account
- Use your single account credentials for all configurations
- Use device selection to choose which physical station each configuration displays
- Simpler management, single authentication
Option 2: Separate Credentials (Fully Independent)
- Each station configuration uses completely different Netatmo account credentials
- Each station authenticates separately with its own account
- Each station fetches data using its own OAuth token
- Each station is 100% isolated - no shared state
- Useful when:
- Sharing is not possible or desired
- You want complete independence between stations
- Different people manage different weather stations
- You need to display weather from multiple Netatmo accounts
Setting Up Shared Access (Option 1)
To display weather stations owned by others (family, friends, other locations):
-
Have the station owner share access:
- They log into the Netatmo mobile app
- Go to Settings → Manage my Home
- Add you as a guest/user with access to their weather station
-
Your account now sees multiple devices:
- After sharing, your Netatmo account has access to both stations
- When you authenticate a configuration, you'll see all available devices
- Select which physical device each configuration should display
-
Example Setup:
- Configuration "My Home" → Select your weather station
- Configuration "Parents' House" → Select parents' weather station
- Both use your credentials, different device_id values
Setting Up Separate Credentials (Option 2)
To use completely independent Netatmo accounts for different stations:
-
Get API credentials for each Netatmo account:
- Account A (yours): Go to https://dev.netatmo.com/ → Create App → Get Client ID + Secret
- Account B (parents'): They do the same → Get their Client ID + Secret
-
Create station configurations with different credentials:
- Create Station 1: Use Account A credentials
- Create Station 2: Use Account B credentials
- Each station stores its credentials separately (encrypted)
-
Authenticate each station independently:
- Visit
/netatmo/authenticate/{station-1}→ Login with Account A - Visit
/netatmo/authenticate/{station-2}→ Login with Account B - Each gets its own OAuth token
- Visit
-
Each station operates independently:
- Station 1 fetches data using Account A's token
- Station 2 fetches data using Account B's token
- No shared state, complete isolation
Visual Indicators:
- The UI shows masked Client ID for each station (e.g.,
66c3d88a••••) - Different Client IDs confirm different accounts are being used
- Token status is tracked separately per station
How It Works
- Single Device: If you only have one weather station, the device is automatically selected
- Multiple Devices: When you have multiple weather stations (owned or shared), you'll be redirected to a device selection page after authentication
- Manual Selection: Choose which Netatmo device this configuration should use from a list showing:
- Station name
- Number of modules
- Device ID (MAC address)
Changing Device Selection
You can change which device a configuration uses at any time by visiting:
/netatmo/{station}/select-device
This is useful if you want to:
- Reassign a configuration to a different physical device
- Fix incorrect device assignments
- Manage multiple locations with similar setups
Technical Details
- Device IDs are Netatmo MAC addresses (e.g.,
70:ee:50:5e:db:30) - The same physical device can be used by multiple configurations
- Different configurations can display data from different devices
- Device selection is stored in the
device_idcolumn
Module Lifecycle Management
The package automatically tracks which modules are active and archives modules that are no longer detected by the Netatmo API.
How It Works
- Active Modules: Modules currently detected in the Netatmo API response are marked as active and displayed normally
- Automatic Archiving: When a module is no longer in the API response (removed, dead battery, lost connection), it's automatically marked as inactive
- Archived Section: Inactive modules appear in a collapsible "Archived Modules" section on the station detail page
- Manual Deletion: You can permanently delete archived modules if they're no longer needed
Common Scenarios
Lost Module:
- Battery dies on outdoor module
- Next data refresh marks it as inactive
- Module appears in Archived Modules section
- Replace battery → module automatically reactivates on next refresh
Removed Module:
- You remove a rain gauge from your station
- Module is automatically archived
- You can delete it permanently from the archived section
Different Station Configurations:
- Your home has outdoor + wind modules
- Your cabin has only the main module
- Each configuration only shows its own active modules
Benefits
- No stale data displayed from disconnected modules
- Historical data preserved for inactive modules
- Clean interface showing only current setup
- Easy cleanup of permanently removed modules
Authentication Flow
- Create a weather station record with your Client ID, Client Secret, and Redirect URI
- Navigate to the authentication route:
/netatmo/{station}/authenticate - You'll be redirected to Netatmo to authorize the app
- After authorization, you'll be redirected back with access tokens
- If your Netatmo account has multiple weather stations, you'll be prompted to select which device this configuration should use
- The package automatically stores and refreshes tokens as needed
Data Structure
NetatmoStation
id- Primary keyuuid- UUID for public routinguser_id- Associated userstation_name- Name of the stationdevice_id- Netatmo device MAC address (selected during setup if multiple devices exist, or auto-populated if only one device)is_public- Boolean flag for public access (default: false)client_id- Encrypted Netatmo Client IDclient_secret- Encrypted Netatmo Client Secretredirect_uri- OAuth redirect URIwebhook_uri- Webhook URI (optional)
NetatmoModule
Stores data for each module (base station and add-on modules):
- Module identification (module_id, module_name, type)
- Battery status
- Connection status (wifi_status, rf_status, reachable)
- Dashboard data (stored as JSON)
is_active- Boolean flag indicating if module is currently detected (default: true)
NetatmoToken
access_token- Current access tokenrefresh_token- Refresh tokenexpires_at- Token expiration timestamp
Supported Module Types
NAMain- Main indoor moduleNAModule1- Outdoor moduleNAModule2- Wind gaugeNAModule3- Rain gaugeNAModule4- Additional indoor module
Caching
The package automatically caches weather data for 10 minutes to reduce API calls. You can modify this behavior in the NetatmoService class.
Security
- Client ID and Client Secret are automatically encrypted in the database
- Tokens are securely stored and automatically refreshed
- All API communications use HTTPS
Testing
The package includes comprehensive test coverage using Pest PHP:
# Run all tests composer test # Run tests with coverage report composer test-coverage # Run specific test suite vendor/bin/pest --testsuite Unit vendor/bin/pest --testsuite Feature # Run tests in parallel vendor/bin/pest --parallel # Check code style composer format vendor/bin/pint --test
Test Coverage
Unit Tests (14 tests):
- Model functionality (NetatmoStation, NetatmoToken, NetatmoModule)
- Encryption and UUID generation
- Relationships and cascade deletes
- Token validation and expiration
- JSON field casting
Feature Tests (13 tests):
- CRUD operations for weather stations
- Authentication flow and redirects
- API integration with HTTP mocking
- Data caching (10-minute strategy)
- Module updates without duplication
Why Pest?
Pest provides a more elegant and expressive testing syntax:
it('can create a netatmo station', function () { $station = NetatmoStation::create([...]); expect($station->uuid)->not->toBeNull(); });
CI/CD
The package uses GitHub Actions for continuous integration:
- Tests against PHP 8.2 & 8.3
- Tests against Laravel 11.x & 12.x
- Uses Pest for elegant test execution
- Code style checks with Laravel Pint
- Runs on every push and pull request
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This package is open-sourced software licensed under the MIT license.
Credits
Support
If you discover any security-related issues, please email terje@nesthus.no instead of using the issue tracker.