A solar-powered IoT and machine-learning system that monitors water quality in real time and recommends suitable aquaculture species for fishponds.
- Backend: PHP 8.3+ · Laravel 11 · Laravel Reverb (real-time)
- Frontend: Livewire 3 · Tailwind CSS · Alpine.js · Vite
- Charts: ApexCharts · Chart.js
- Testing: Pest
- Database: SQLite / MySQL / PostgreSQL
- IoT: ESP32 / Arduino (sensor nodes)
- Background
- Features
- Requirements
- Install
- Usage
- Dev-start helper
- API / Architecture
- Testing
- Contributing
- License
- GitHub Repository
- Architecture Diagram
- Water Quality Config
- Sensor Data Controller
- User Model
- Livewire ML Client
- LICENSE
Agwasuri helps small-scale aquaculture operators, researchers, and municipal officers collect, visualize, and act on pond water-quality data. It combines solar-powered sensor ingestion (ESP32/Arduino devices), real-time broadcasts (Laravel Reverb), and a lightweight ML service to recommend suitable fish species and reduce stock loss.
Goals:
- Improve decision-making for pond management
- Provide reproducible data for research and evaluation
- Demonstrate a complete IoT → web → ML pipeline for aquaculture
- Solar-powered sensor nodes for off-grid pond deployments
- Real-time ingestion of temperature, pH, dissolved oxygen, and salinity
- Live charts and dashboards (Livewire + Tailwind)
- AI-driven fish-species recommendations (external ML service)
- Web endpoint for sensor data ingestion:
POST /store-water-quality-data - Broadcasts new measurements on channel
water-quality-data-created
- PHP 8.3+
- Composer
- Node.js 18+
- npm
- SQLite (recommended for quick local setup) or MySQL/PostgreSQL for production
- PowerShell (Windows) or bash (macOS/Linux)
Follow these steps to get a development instance running. The PowerShell examples assume you're on Windows; for macOS/Linux use the POSIX equivalents shown.
- Clone and install dependencies
git clone https://github.com/transcenddev/agwasuri.git
cd agwasuri
composer install
npm install- Copy environment and generate app key
copy .env.example .env
php artisan key:generateOn POSIX systems:
cp .env.example .env
php artisan key:generate- Configure the database in
.env(SQLite quickstart)
DB_CONNECTION=sqlite
DB_DATABASE=database/database.sqliteCreate the SQLite file if it doesn't exist:
if (-not (Test-Path database\database.sqlite)) { New-Item database/database.sqlite -ItemType File }- Run migrations, seeders and install optional packages
php artisan migrate --seed
php artisan reverb:install
php artisan livewire-charts:install- (Optional) Create or reset the admin account
pwsh ./scripts/create-admin.ps1Start the full development stack (recommended):
composer run devThis runs the web server, Reverb (real-time) and Vite concurrently. Alternatively, start pieces manually:
php artisan serve --host=0.0.0.0 --port=8000
php artisan reverb:start
npm run devOpen the app at http://127.0.0.1:8000.
Sensor ingestion endpoint (sample):
- URL:
POST http://127.0.0.1:8000/store-water-quality-data - Headers:
Authorization: Bearer <API_KEY>,Content-Type: application/json
Example curl request:
curl -X POST http://127.0.0.1:8000/store-water-quality-data \\
-H "Authorization: Bearer <API_KEY>" \\
-H "Content-Type: application/json" \\
-d '{"user_id":1,"recorded_at":"2025-11-06 12:00:00","temperature":28.5,"ph_level":7.2,"dissolved_oxygen":6.8,"salinity":15.3}'Real-time event channel: water-quality-data-created (event App\\Events\\WaterQualityCreated).
Use the included cross-platform helper scripts to simplify starting and resetting local environments:
npm run dev-start- Default: runs non-destructive migrations/seeds and starts the dev stack.
- Destructive reset:
npm run dev-start -- --fresh(POSIX) ornpm run dev-start -- -Fresh(PowerShell) — this drops and rebuilds the DB after confirmation.
See scripts/ for platform-specific behaviour.
A brief overview of the main components and important files:
- Routes: routes/web.php - registers
POST /store-water-quality-dataand site routes - Controller: app/Http/Controllers/Api/WaterQualityDataController.php - validates requests, authenticates via
Authorization: Bearer <API_KEY>(matchinguser_id+api_key), createsWaterQualityDatarecords and broadcastsWaterQualityCreatedevents - Models: app/Models/WaterQualityData.php, app/Models/User.php (primary key:
user_id), app/Models/ModelMetadata.php - Events: app/Events/WaterQualityCreated.php - broadcasts on channel
water-quality-data-created(ShouldBroadcastNow) - Livewire: app/Livewire/ClassifyFish.php - calls external ML endpoints (
/predictand/train_model) configured viaconfig/services.php(services.ml.base_url)
Event payload example:
{
"waterQualityData": {
"recorded_at": "2025-11-06 12:00:00",
"temperature": 28.5,
"salinity": 15.3,
"dissolved_oxygen": 6.8,
"ph_level": 7.2,
"user_id": 1
}
}See the architecture diagram in notes/architecture.md for a rendered Mermaid diagram and component explanations. Additional project notes live in notes/agwasuri_notes.md.
Tests use Pest. Run the full test suite:
php artisan test
# or
./vendor/bin/pestRun a single test or filter by name:
php artisan test --filter=WaterQualityDataTestNotes:
- Ensure
.env.testingis configured or your testing DB is available. - Some feature tests that rely on real-time broadcasts may require
php artisan reverb:start.
The project centralizes UI status styling in the status_map config entry so views and Livewire components render consistent badges, value coloring and row borders.
- Location: config/water_quality.php
- Canonical keys:
GOOD,CRITICAL - Each entry contains:
badge(badge classes),value(value text classes),border(row border classes)
Example (simplified):
'status_map' => [
'GOOD' => ['badge' => 'text-green-700 bg-green-50', 'value' => 'text-green-700', 'border' => 'border-l-4 border-green-100'],
'CRITICAL' => ['badge' => 'text-red-700 bg-red-50', 'value' => 'text-red-700 font-semibold', 'border' => 'border-l-4 border-red-200'],
]When updating palette or accessibility contrast, update status_map and sweep Livewire components to keep UI consistent.
Contributions are welcome. Please follow these guidelines:
- File issues for bugs or feature requests.
- Fork the repo and create a branch named like
feat/short-descriptionorfix/short-description. - Run tests and linters before opening a PR:
php artisan test. - Include screenshots and reproduction steps for UI changes.
- Use small, focused pull requests — maintainers will run CI (Pest tests, static analysis) before merging.
See .github/CONTRIBUTING.md for project credits and contribution guidelines.
This project is licensed under the MIT License. See the LICENSE file for details.