Skip to content

Commit 50382d7

Browse files
committed
Restore and upgrade devices endpoints
1 parent ba0b8d1 commit 50382d7

2 files changed

Lines changed: 48 additions & 42 deletions

File tree

app/api/v1/devices.py

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,81 @@
11
from fastapi import APIRouter, Depends, HTTPException, Request
22
from sqlalchemy.orm import Session
33
from pydantic import BaseModel
4-
from app.core.database import get_db
5-
from app.models.device import Device
6-
from app.core.security import get_current_user
7-
from app.core.limiter import limiter
8-
from app.mqtt.client import mqtt_client
4+
from typing import Optional
5+
6+
# --- UPDATE IMPORT (Sesuai Struktur Baru) ---
7+
from app.db.database import get_db # <-- Folder db
8+
from app.models.device import SensorLog # <-- Sesuaikan nama class device kamu (Device/SensorLog?)
9+
# Cek model kamu: Kalau nama classnya Device, ganti SensorLog jadi Device di baris atas
10+
from app.mqtt.client import publish_message # <-- Kita pakai helper publish kalau ada, atau client langsung
11+
12+
# --- IMPORT RATE LIMITER REDIS ---
13+
from fastapi_limiter.depends import RateLimiter
914

1015
router = APIRouter()
1116

12-
# --- SCHEMA 1: UNTUK USER (CLAIM) ---
13-
# User HANYA input ID dan PIN. Tidak perlu Factory Secret.
17+
# --- SCHEMA ---
1418
class UserClaimSchema(BaseModel):
1519
device_id: str
1620
pin_code: str
1721

18-
# --- SCHEMA 2: UNTUK ESP32 (AUTO REGISTER) ---
19-
# Alat WAJIB punya Factory Secret.
2022
class AutoRegisterSchema(BaseModel):
2123
device_id: str
2224
pin_code: str
2325
factory_secret: str
2426

27+
# Kita butuh model Device (Definisikan ulang kalau belum import)
28+
# Asumsi kamu punya model Device di app/models/device.py
29+
from app.models.device import Device # Pastikan ini ada
2530

2631
# --- 1. ENDPOINT CLAIM (User) ---
27-
@router.post("/claim")
28-
@limiter.limit("5/minute")
32+
# Rate Limit: 5x per 60 detik
33+
@router.post("/claim", dependencies=[Depends(RateLimiter(times=5, seconds=60))])
2934
def claim_device(
30-
request: Request,
31-
claim_data: UserClaimSchema, # <--- GUNAKAN SCHEMA USER
32-
db: Session = Depends(get_db),
33-
user_uid: str = Depends(get_current_user)
35+
claim_data: UserClaimSchema,
36+
db: Session = Depends(get_db)
37+
# user_uid: str = Depends(get_current_user) # <-- Aktifkan ini nanti kalau AUTH firebase sudah dipasang
3438
):
35-
# 1. Bersihkan Input (Spasi & Huruf Besar)
39+
# Sementara kita hardcode user_uid dulu biar bisa tes tanpa login frontend
40+
user_uid = "TEST_USER_UID_001"
41+
3642
clean_id = claim_data.device_id.strip().upper()
3743
clean_pin = claim_data.pin_code.strip()
3844

39-
# 2. Cari Alat
45+
# Cari Alat
4046
device = db.query(Device).filter(Device.device_id == clean_id).first()
4147

4248
if not device:
43-
raise HTTPException(status_code=404, detail=f"Alat {clean_id} tidak ditemukan. Pastikan alat sudah nyala.")
49+
raise HTTPException(status_code=404, detail=f"Alat {clean_id} tidak ditemukan.")
4450

4551
if device.owner_uid:
4652
if device.owner_uid == user_uid:
4753
return {"message": "Alat ini memang sudah punya kamu kok."}
4854
raise HTTPException(status_code=400, detail="Alat ini sudah dimiliki orang lain!")
4955

50-
# 3. Cek PIN
56+
# Cek PIN
5157
if device.pin_code != clean_pin:
52-
raise HTTPException(status_code=400, detail="PIN Salah! Cek stiker alat.")
58+
raise HTTPException(status_code=400, detail="PIN Salah!")
5359

54-
# 4. Simpan Pemilik
60+
# Simpan Pemilik
5561
device.owner_uid = user_uid
5662
device.device_name = "Alat Baru Saya"
5763
db.commit()
5864

59-
return {
60-
"status": "success",
61-
"message": f"Selamat! Alat {clean_id} berhasil ditambahkan ke akunmu.",
62-
"owner": user_uid
63-
}
65+
return {"status": "success", "message": f"Alat {clean_id} berhasil diklaim!"}
6466

6567

6668
# --- 2. ENDPOINT CONTROL RELAY ---
67-
@router.post("/control-relay")
68-
@limiter.limit("10/minute") # Limit agak longgar buat kontrol
69+
# Rate Limit: 10x per 60 detik
70+
@router.post("/control-relay", dependencies=[Depends(RateLimiter(times=10, seconds=60))])
6971
def control_relay(
70-
request: Request,
7172
device_id: str,
7273
state: str,
73-
user_uid: str = Depends(get_current_user),
7474
db: Session = Depends(get_db)
7575
):
76+
# Hardcode user dulu
77+
user_uid = "TEST_USER_UID_001"
78+
7679
clean_id = device_id.strip().upper()
7780

7881
if state not in ["ON", "OFF"]:
@@ -83,26 +86,28 @@ def control_relay(
8386
if not device:
8487
raise HTTPException(status_code=404, detail="Alat tidak ditemukan.")
8588

86-
if device.owner_uid != user_uid:
87-
raise HTTPException(status_code=403, detail="Eits! Ini bukan alat kamu.")
89+
# Proteksi Kepemilikan (Nyalakan nanti kalau Auth siap)
90+
# if device.owner_uid != user_uid:
91+
# raise HTTPException(status_code=403, detail="Bukan alat kamu!")
8892

8993
topic = f"alat/{clean_id}/command"
9094
payload = f'{{"relay": "{state}"}}'
9195

96+
# Publish ke MQTT
97+
# Pastikan kamu import client mqtt yg benar, atau pakai cara ini:
98+
from app.mqtt.client import client as mqtt_client
9299
mqtt_client.publish(topic, payload)
93100

94-
return {"message": "Perintah dikirim", "topic": topic, "payload": payload}
101+
return {"message": "Perintah dikirim", "topic": topic, "state": state}
95102

96103

97104
# --- 3. ENDPOINT AUTO REGISTER (ESP32) ---
98-
@router.post("/auto-register")
99-
@limiter.limit("5/minute")
105+
@router.post("/auto-register", dependencies=[Depends(RateLimiter(times=5, seconds=60))])
100106
def auto_register_device(
101-
request: Request,
102-
data: AutoRegisterSchema, # <--- GUNAKAN SCHEMA ALAT
107+
data: AutoRegisterSchema,
103108
db: Session = Depends(get_db)
104109
):
105-
FACTORY_SECRET = "RAHASIA_PABRIK_PCB_SERIUS_2026"
110+
FACTORY_SECRET = "RAHASIA_PABRIK_PCB_SERIUS_2026"
106111

107112
if data.factory_secret != FACTORY_SECRET:
108113
raise HTTPException(status_code=403, detail="Anda bukan perangkat resmi!")
@@ -118,10 +123,9 @@ def auto_register_device(
118123
device_id=clean_id,
119124
pin_code=clean_pin,
120125
device_name="New Device",
121-
is_active=True
126+
# is_active=True # Sesuaikan dengan model kamu
122127
)
123128
db.add(new_device)
124129
db.commit()
125-
db.refresh(new_device)
126130

127-
return {"message": f"Sukses! Alat {clean_id} berhasil didaftarkan otomatis."}
131+
return {"message": f"Sukses! Alat {clean_id} didaftarkan."}

app/main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
# Import komponen buatan kita
77
from app.mqtt.client import start_mqtt
8-
from app.api.v1 import logs
8+
from app.api.v1 import logs, devices
9+
910

1011
# --- SETTING LIFESPAN (Cara Modern Handle Startup/Shutdown) ---
1112
@asynccontextmanager
@@ -41,6 +42,7 @@ async def lifespan(app: FastAPI):
4142

4243
# --- DAFTARKAN ROUTER ---
4344
app.include_router(logs.router, prefix="/api/logs", tags=["Sensor Logs"])
45+
app.include_router(devices.router, prefix="/api/devices", tags=["Devices & Control"])
4446

4547
@app.get("/")
4648
def read_root():

0 commit comments

Comments
 (0)