Cleanup: Hapus folder Flutter yang tidak diperlukan di backend

This commit is contained in:
flems 2026-06-25 18:32:41 +07:00
parent 349a275594
commit 18114de707
5 changed files with 544 additions and 183 deletions

17
backend/README.md Normal file
View File

@ -0,0 +1,17 @@
# aplikasi_novil
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@ -0,0 +1,414 @@
# 🔧 SOLUSI: Data ESP32 Tidak Masuk ke MySQL Railway
## 🎯 Masalah
ESP32 sudah publish data ke MQTT, tapi data **tidak masuk ke MySQL** di Railway.
---
## 🔍 Penyebab
### Arsitektur yang Salah:
```
❌ SEBELUM:
ESP32 → HiveMQ (broker.hivemq.com)
(data hilang di sini)
Backend Railway (Aedes Broker Internal - DISABLED)
MySQL (tidak ada data)
```
**Masalah:**
1. ESP32 publish ke **HiveMQ** public broker
2. Backend Railway menggunakan **Aedes** (MQTT broker internal)
3. Aedes **DISABLED** di Railway (tidak bisa bind port 1883)
4. Backend **TIDAK connect** ke HiveMQ
5. Backend **TIDAK subscribe** ke topic ESP32
6. **Data hilang** karena tidak ada yang terima
---
## ✅ Solusi
### Arsitektur yang Benar:
```
✅ SESUDAH:
ESP32 → HiveMQ (broker.hivemq.com)
Backend Railway (MQTT Client)
↓ (subscribe & save)
MySQL Database
```
**Perubahan:**
1. Backend connect ke **HiveMQ sebagai MQTT Client**
2. Backend **subscribe** ke topic ESP32
3. Backend **terima data** dari ESP32
4. Backend **save ke MySQL**
---
## 🛠️ Perubahan yang Sudah Dilakukan
### 1. **Install Package MQTT Client**
```bash
npm install mqtt
```
### 2. **Update `server.js`**
- Tambah import `mqtt` client
- Connect ke HiveMQ sebagai client
- Subscribe ke topic: `novil/pengering/data`, `status`, `button`
- Handle message dan save ke MySQL
- Publish command via HiveMQ
### 3. **Update `.env`**
- Tambah `MQTT_BROKER_URL=mqtt://broker.hivemq.com:1883`
- Tambah template untuk MySQL credentials
---
## 🚀 Cara Deploy
### 1. **Test Lokal (Optional)**
```bash
cd backend
npm install
npm start
```
**Expected Output:**
```
✅ Connected to MQTT Broker (HiveMQ)
✅ Subscribed to topics:
- novil/pengering/data
- novil/pengering/status
- novil/pengering/button
🚀 REST API running on port 3000
```
### 2. **Push ke GitHub**
```bash
cd backend
git add .
git commit -m "Fix: Backend connect to HiveMQ as MQTT client"
git push
```
### 3. **Configure Railway**
Di Railway Dashboard:
1. Buka project → **Variables**
2. Tambahkan variable baru:
- **Key:** `MQTT_BROKER_URL`
- **Value:** `mqtt://broker.hivemq.com:1883`
3. MySQL credentials sudah otomatis dari Railway MySQL Plugin (tidak perlu diubah)
### 4. **Wait for Auto-Deploy**
Railway akan otomatis deploy setelah push ke GitHub.
---
## 🧪 Testing
### 1. **Check MQTT Connection**
```bash
curl https://your-app.railway.app/api/stats
```
**Expected Response:**
```json
{
"success": true,
"stats": {
"mqttConnected": true, // ← HARUS TRUE
"sensorDataCount": 0,
"statusHistoryCount": 0,
...
}
}
```
**Jika `mqttConnected: false`:**
- Check Railway logs
- Pastikan `MQTT_BROKER_URL` sudah ditambahkan
- Redeploy
---
### 2. **Test dengan ESP32**
1. **Upload sketch ESP32** (tidak perlu diubah)
2. **Buka Serial Monitor** (115200 baud)
3. **Tekan button** untuk start pengeringan
4. **Tunggu 5 detik** (scan berat)
5. **Check Serial Monitor:**
```
MQTT Data Sent: {"suhu":28.5,"berat":450,"target":315}
MQTT Data Sent: {"suhu":28.6,"berat":448,"target":315}
```
---
### 3. **Check Data di MySQL**
```bash
curl https://your-app.railway.app/api/data/latest
```
**Expected Response:**
```json
{
"success": true,
"data": {
"suhu": 28.5,
"berat": 450.0,
"target": 315.0,
"status": "RUNNING",
"timestamp": "2026-05-28T10:30:00.000Z"
}
}
```
**Jika data masih kosong:**
- Check Railway logs untuk error
- Pastikan ESP32 sudah publish data
- Check MySQL credentials
---
### 4. **Check History**
```bash
curl https://your-app.railway.app/api/data/history?limit=10
```
**Expected Response:**
```json
{
"success": true,
"count": 10,
"data": [
{
"id": 1,
"suhu": 28.5,
"berat": 450.0,
"target": 315.0,
"relay1": true,
"relay2": true,
"relay3": true,
"relay4": false,
"status": "RUNNING",
"timestamp": "2026-05-28 10:30:00"
},
...
]
}
```
---
### 5. **Test Send Command**
```bash
curl -X POST https://your-app.railway.app/api/control \
-H "Content-Type: application/json" \
-d '{"command":"HEATER_ON"}'
```
**Expected Response:**
```json
{
"success": true,
"message": "Command sent successfully",
"command": "HEATER_ON"
}
```
**Check ESP32 Serial Monitor:**
```
MQTT Message [novil/pengering/control] : HEATER_ON
HEATER ON
```
---
## 📊 Monitoring
### Railway Logs
Di Railway Dashboard → Deployments → View Logs
**Expected Logs:**
```
🔄 Connecting to MQTT Broker: mqtt://broker.hivemq.com:1883
✅ Connected to MQTT Broker (HiveMQ)
✅ Subscribed to topics:
- novil/pengering/data
- novil/pengering/status
- novil/pengering/button
📨 MQTT Message received:
Topic: novil/pengering/data
Message: {"suhu":28.5,"berat":450,"target":315}
✅ Data saved to MySQL database
📨 MQTT Message received:
Topic: novil/pengering/status
Message: PENGERINGAN DIMULAI
✅ Status saved to MySQL database
```
---
## 🔍 Troubleshooting
### Problem 1: `mqttConnected: false`
**Penyebab:** Backend tidak bisa connect ke HiveMQ
**Solusi:**
1. Check Railway logs untuk error message
2. Pastikan variable `MQTT_BROKER_URL` sudah ditambahkan
3. Pastikan value: `mqtt://broker.hivemq.com:1883` (bukan `http://`)
4. Redeploy
---
### Problem 2: Data masih tidak masuk ke MySQL
**Penyebab:** Database credentials salah atau database belum diinit
**Solusi:**
1. **Test database connection:**
```bash
curl https://your-app.railway.app/api/database/test
```
2. **Initialize database tables:**
```bash
curl -X POST https://your-app.railway.app/api/database/init
```
3. **Check MySQL credentials di Railway:**
- `MYSQLHOST`
- `MYSQLPORT`
- `MYSQLUSER`
- `MYSQLPASSWORD`
- `MYSQLDATABASE`
---
### Problem 3: ESP32 tidak terima command
**Penyebab:** ESP32 tidak subscribe atau MQTT disconnect
**Solusi:**
1. **Check ESP32 Serial Monitor:**
```
MQTT Connected
Subscribed to: novil/pengering/control
```
2. **Restart ESP32**
3. **Check WiFi connection**
---
### Problem 4: Railway logs error "Cannot find module 'mqtt'"
**Penyebab:** Package `mqtt` belum terinstall
**Solusi:**
1. **Pastikan `package.json` sudah update:**
```json
"dependencies": {
"mqtt": "^5.3.5",
...
}
```
2. **Push ke GitHub lagi:**
```bash
git add package.json
git commit -m "Add mqtt package"
git push
```
---
## ✅ Checklist
### Pre-Deploy:
- [x] Package `mqtt` sudah ditambahkan di `package.json`
- [x] `server.js` sudah diupdate dengan MQTT client
- [x] `.env` sudah ada template MySQL credentials
- [x] `npm install` berhasil
### Deploy:
- [ ] Push ke GitHub
- [ ] Tambahkan `MQTT_BROKER_URL` di Railway Variables
- [ ] Wait for auto-deploy (2-3 menit)
- [ ] Check Railway logs untuk "Connected to MQTT Broker"
### Testing:
- [ ] Test `/api/stats``mqttConnected: true`
- [ ] Upload ESP32 sketch
- [ ] Test ESP32 publish data
- [ ] Test `/api/data/latest` → ada data
- [ ] Test `/api/data/history` → ada history
- [ ] Test send command → ESP32 terima
---
## 📝 Catatan Penting
1. **ESP32 tidak perlu diubah** - sketch tetap sama
2. **MySQL credentials** sudah otomatis dari Railway MySQL Plugin
3. **HiveMQ** adalah public broker, gratis, tidak perlu registrasi
4. **Backend sekarang sebagai MQTT Client**, bukan broker
5. **Aedes broker tetap ada** tapi disabled (untuk future use)
---
## 🎯 Expected Result
Setelah deploy:
1. ✅ Backend connect ke HiveMQ
2. ✅ Backend subscribe ke topic ESP32
3. ✅ ESP32 publish data → Backend terima
4. ✅ Backend save data ke MySQL
5. ✅ Data history tersimpan
6. ✅ Status history tersimpan
7. ✅ Command dari Flutter → ESP32 berfungsi
---
## 📞 Support
Jika masih ada masalah:
1. **Check Railway Logs** untuk error detail
2. **Check ESP32 Serial Monitor** untuk MQTT status
3. **Test API endpoints** untuk verify data
4. **Baca dokumentasi lengkap** di `backend/FIX_MQTT_MYSQL.md`
---
Selamat mencoba! 🚀🎉

View File

@ -1,183 +0,0 @@
# =====================================================
# Script Deploy Backend ke Railway
# =====================================================
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " DEPLOY BACKEND KE RAILWAY" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Cek apakah di folder yang benar
$currentPath = Get-Location
if (-not $currentPath.Path.EndsWith("backend")) {
Write-Host "❌ Error: Script harus dijalankan dari folder backend" -ForegroundColor Red
Write-Host " Current path: $currentPath" -ForegroundColor Yellow
Write-Host " Pindah ke folder backend dulu:" -ForegroundColor Yellow
Write-Host " cd backend" -ForegroundColor Yellow
exit 1
}
Write-Host "📁 Current directory: $currentPath" -ForegroundColor Green
Write-Host ""
# =====================================================
# 1. CEK GIT STATUS
# =====================================================
Write-Host "🔍 Checking Git status..." -ForegroundColor Yellow
git status --short
Write-Host ""
$confirm = Read-Host "Lanjutkan commit dan push? (y/n)"
if ($confirm -ne "y") {
Write-Host "❌ Deployment dibatalkan" -ForegroundColor Red
exit 0
}
# =====================================================
# 2. GIT ADD
# =====================================================
Write-Host ""
Write-Host "📦 Adding files to Git..." -ForegroundColor Yellow
git add server.js
git add DEPLOY_PERBAIKAN.md
git add deploy-to-railway.ps1
git add ../PERBAIKAN_CONTROL_COMMANDS.md
Write-Host "✅ Files added" -ForegroundColor Green
# =====================================================
# 3. GIT COMMIT
# =====================================================
Write-Host ""
Write-Host "💾 Committing changes..." -ForegroundColor Yellow
$commitMessage = "Fix: Subscribe to control topic and save to database
- Backend now subscribes to novil/pengering/control topic
- Added handler to save control commands to database
- Added handler to update relay status from ESP32
- Status messages with STATUS: prefix saved to status_history
- Command messages saved to control_commands table"
git commit -m $commitMessage
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ Commit successful" -ForegroundColor Green
} else {
Write-Host "⚠️ No changes to commit or commit failed" -ForegroundColor Yellow
}
# =====================================================
# 4. GIT PUSH
# =====================================================
Write-Host ""
Write-Host "🚀 Pushing to repository..." -ForegroundColor Yellow
git push origin main
if ($LASTEXITCODE -eq 0) {
Write-Host "✅ Push successful" -ForegroundColor Green
} else {
Write-Host "❌ Push failed" -ForegroundColor Red
Write-Host " Coba push manual: git push origin main" -ForegroundColor Yellow
exit 1
}
# =====================================================
# 5. TUNGGU RAILWAY DEPLOY
# =====================================================
Write-Host ""
Write-Host "⏳ Railway sedang deploy..." -ForegroundColor Yellow
Write-Host " Buka Railway Dashboard untuk monitor progress:" -ForegroundColor Cyan
Write-Host " https://railway.app/dashboard" -ForegroundColor Cyan
Write-Host ""
Write-Host " Tunggu hingga status: ✅ Deployed" -ForegroundColor Green
Write-Host ""
$waitDeploy = Read-Host "Sudah selesai deploy? (y/n)"
if ($waitDeploy -ne "y") {
Write-Host "⏸️ Tunggu deploy selesai dulu, lalu jalankan test manual" -ForegroundColor Yellow
exit 0
}
# =====================================================
# 6. TEST DEPLOYMENT
# =====================================================
Write-Host ""
Write-Host "🧪 Testing deployment..." -ForegroundColor Yellow
Write-Host ""
$railwayUrl = Read-Host "Masukkan URL Railway (contoh: https://your-app.up.railway.app)"
if ([string]::IsNullOrWhiteSpace($railwayUrl)) {
Write-Host "⚠️ URL tidak diisi, skip testing" -ForegroundColor Yellow
Write-Host " Test manual dengan:" -ForegroundColor Yellow
Write-Host " curl https://your-app.up.railway.app/" -ForegroundColor Cyan
exit 0
}
# Remove trailing slash
$railwayUrl = $railwayUrl.TrimEnd('/')
Write-Host ""
Write-Host "📡 Testing health check..." -ForegroundColor Yellow
try {
$response = Invoke-RestMethod -Uri "$railwayUrl/" -Method Get
Write-Host "✅ Health check OK" -ForegroundColor Green
Write-Host " Status: $($response.status)" -ForegroundColor Cyan
Write-Host " Message: $($response.message)" -ForegroundColor Cyan
Write-Host " Version: $($response.version)" -ForegroundColor Cyan
} catch {
Write-Host "❌ Health check failed" -ForegroundColor Red
Write-Host " Error: $_" -ForegroundColor Red
}
Write-Host ""
Write-Host "📊 Testing stats..." -ForegroundColor Yellow
try {
$response = Invoke-RestMethod -Uri "$railwayUrl/api/stats" -Method Get
Write-Host "✅ Stats OK" -ForegroundColor Green
Write-Host " MQTT Connected: $($response.stats.mqttConnected)" -ForegroundColor Cyan
Write-Host " Sensor Data Count: $($response.stats.sensorDataCount)" -ForegroundColor Cyan
Write-Host " Status History Count: $($response.stats.statusHistoryCount)" -ForegroundColor Cyan
Write-Host " Control Commands Count: $($response.stats.controlCommandsCount)" -ForegroundColor Cyan
} catch {
Write-Host "❌ Stats failed" -ForegroundColor Red
Write-Host " Error: $_" -ForegroundColor Red
}
Write-Host ""
Write-Host "🎛️ Testing control command..." -ForegroundColor Yellow
try {
$body = @{
command = "HEATER_ON"
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "$railwayUrl/api/control" -Method Post -Body $body -ContentType "application/json"
Write-Host "✅ Control command OK" -ForegroundColor Green
Write-Host " Success: $($response.success)" -ForegroundColor Cyan
Write-Host " Message: $($response.message)" -ForegroundColor Cyan
Write-Host " Command: $($response.command)" -ForegroundColor Cyan
} catch {
Write-Host "❌ Control command failed" -ForegroundColor Red
Write-Host " Error: $_" -ForegroundColor Red
}
# =====================================================
# 7. SELESAI
# =====================================================
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " ✅ DEPLOYMENT SELESAI" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "📋 Next Steps:" -ForegroundColor Yellow
Write-Host " 1. Cek Railway logs untuk memastikan subscribe ke control topic" -ForegroundColor White
Write-Host " 2. Upload kode ESP32 (esp32_pengering_ikan_v2.ino)" -ForegroundColor White
Write-Host " 3. Monitor Serial ESP32 untuk melihat status relay" -ForegroundColor White
Write-Host " 4. Cek database Railway untuk memastikan data masuk" -ForegroundColor White
Write-Host ""
Write-Host "📚 Dokumentasi:" -ForegroundColor Yellow
Write-Host " - PERBAIKAN_CONTROL_COMMANDS.md" -ForegroundColor Cyan
Write-Host " - DEPLOY_PERBAIKAN.md" -ForegroundColor Cyan
Write-Host ""
Write-Host "🔗 Railway URL: $railwayUrl" -ForegroundColor Cyan
Write-Host ""

111
backend/migrate_database.js Normal file
View File

@ -0,0 +1,111 @@
// =====================================================
// DATABASE MIGRATION SCRIPT
// Migrate data dari Railway lama ke Railway baru
// =====================================================
const mysql = require('mysql2/promise');
// Konfigurasi Database LAMA (Railway account lama)
const oldDB = {
host: process.env.OLD_DB_HOST || 'mysql.railway.internal',
port: process.env.OLD_DB_PORT || 3306,
user: process.env.OLD_DB_USER || 'root',
password: process.env.OLD_DB_PASSWORD || '',
database: process.env.OLD_DB_NAME || 'railway'
};
// Konfigurasi Database BARU (Railway account baru)
const newDB = {
host: process.env.NEW_DB_HOST || 'mysql.railway.internal',
port: process.env.NEW_DB_PORT || 3306,
user: process.env.NEW_DB_USER || 'root',
password: process.env.NEW_DB_PASSWORD || '',
database: process.env.NEW_DB_NAME || 'railway'
};
async function migrateData() {
let oldConnection, newConnection;
try {
console.log('🔄 Connecting to OLD database...');
oldConnection = await mysql.createConnection(oldDB);
console.log('✅ Connected to OLD database');
console.log('🔄 Connecting to NEW database...');
newConnection = await mysql.createConnection(newDB);
console.log('✅ Connected to NEW database');
// =====================================================
// 1. Migrate sensor_data
// =====================================================
console.log('\n📊 Migrating sensor_data...');
const [sensorData] = await oldConnection.query('SELECT * FROM sensor_data ORDER BY id');
console.log(` Found ${sensorData.length} records`);
for (const row of sensorData) {
await newConnection.query(
`INSERT INTO sensor_data (suhu, berat, target, relay1, relay2, relay3, relay4, status, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[row.suhu, row.berat, row.target, row.relay1, row.relay2, row.relay3, row.relay4, row.status, row.timestamp]
);
}
console.log('✅ sensor_data migrated');
// =====================================================
// 2. Migrate status_history
// =====================================================
console.log('\n📝 Migrating status_history...');
const [statusHistory] = await oldConnection.query('SELECT * FROM status_history ORDER BY id');
console.log(` Found ${statusHistory.length} records`);
for (const row of statusHistory) {
await newConnection.query(
`INSERT INTO status_history (message, timestamp) VALUES (?, ?)`,
[row.message, row.timestamp]
);
}
console.log('✅ status_history migrated');
// =====================================================
// 3. Migrate control_commands
// =====================================================
console.log('\n🎛 Migrating control_commands...');
const [controlCommands] = await oldConnection.query('SELECT * FROM control_commands ORDER BY id');
console.log(` Found ${controlCommands.length} records`);
for (const row of controlCommands) {
await newConnection.query(
`INSERT INTO control_commands (command, source, timestamp) VALUES (?, ?, ?)`,
[row.command, row.source, row.timestamp]
);
}
console.log('✅ control_commands migrated');
console.log('\n🎉 MIGRATION COMPLETED SUCCESSFULLY!');
console.log('=====================================');
console.log(`Total sensor_data: ${sensorData.length}`);
console.log(`Total status_history: ${statusHistory.length}`);
console.log(`Total control_commands: ${controlCommands.length}`);
console.log('=====================================');
} catch (error) {
console.error('❌ Migration Error:', error);
throw error;
} finally {
if (oldConnection) await oldConnection.end();
if (newConnection) await newConnection.end();
}
}
// Run migration
console.log('🚀 Starting Database Migration...');
console.log('=====================================');
migrateData()
.then(() => {
console.log('✅ Migration script finished');
process.exit(0);
})
.catch((error) => {
console.error('❌ Migration failed:', error);
process.exit(1);
});

View File

@ -5,3 +5,5 @@ builder = "NIXPACKS"
startCommand = "node server.js" startCommand = "node server.js"
restartPolicyType = "ON_FAILURE" restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10 restartPolicyMaxRetries = 10
# Force rebuild for relay fix v1.0.3