Compare commits
4 Commits
d084944bc0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f90fdbc40 | |||
| 104c9ce889 | |||
| 5f478a806c | |||
| b1b6c61beb |
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
@@ -44,6 +46,16 @@ class _HomeScreenContentState extends State<HomeScreenContent> {
|
||||
}
|
||||
// 25.12.03 지은 추가 끝
|
||||
|
||||
Future<Map<String, dynamic>?> test() async {
|
||||
final data = await _api.getTimeseries(target: "*", limit: 200);
|
||||
|
||||
if (data != null) {
|
||||
print("받은 데이터 길이: ${data['samples'].length}");
|
||||
print(data['samples'][0]); // 첫 번째 데이터 출력
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
int _selectedImageIndex = 0;
|
||||
|
||||
static const BoxShadow _cleanShadow = BoxShadow(
|
||||
@@ -60,6 +72,46 @@ class _HomeScreenContentState extends State<HomeScreenContent> {
|
||||
'FAN': false,
|
||||
};
|
||||
|
||||
double? _battPct;
|
||||
double? _volt;
|
||||
double? _temp;
|
||||
double? _humi;
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadBattPct();
|
||||
_timer = Timer.periodic(const Duration(seconds: 2), (_) => _loadBattPct());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loadBattPct() async {
|
||||
final data = await test(); // Future → Map으로 resolve
|
||||
|
||||
if (data == null) return;
|
||||
|
||||
// samples[0]에서 batt_pct 값 읽기
|
||||
final battPct = data['samples'][0]['batt_pct'];
|
||||
final volt = data['samples'][0]['pv_volt'];
|
||||
final temp = data['samples'][0]['temp'];
|
||||
final humi = data['samples'][0]['humi'];
|
||||
|
||||
setState(() {
|
||||
// 숫자/문자 둘 다 안전하게 처리
|
||||
_battPct = battPct.toDouble();
|
||||
_volt = volt.toDouble();
|
||||
_temp = temp.toDouble();
|
||||
_humi = humi.toDouble();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
@@ -273,11 +325,20 @@ class _HomeScreenContentState extends State<HomeScreenContent> {
|
||||
painter: _BatteryArcPainter(
|
||||
backgroundColor: _accentContainerColor,
|
||||
color: _mainBlueColor,
|
||||
percentage: 1.0,
|
||||
percentage: _battPct!.floor()/100 ,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text('86', style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: _mainTextColor)),
|
||||
Text(
|
||||
_battPct == null
|
||||
? '--' // 아직 로딩 전
|
||||
: _battPct!.floor().toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: _mainTextColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -503,9 +564,21 @@ class _HomeScreenContentState extends State<HomeScreenContent> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildSensorInfoRow(Icons.water_drop_outlined, '습도: 60%', '습도'),
|
||||
_buildSensorInfoRow(
|
||||
Icons.water_drop_outlined,
|
||||
_humi == null
|
||||
? '--' // 아직 로딩 전
|
||||
: '습도: '+_humi!.floor().toString()+'%',
|
||||
'습도'
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_buildSensorInfoRow(Icons.thermostat, '온도: 24.5℃', '온도'),
|
||||
_buildSensorInfoRow(
|
||||
Icons.thermostat,
|
||||
_temp == null
|
||||
? '--' // 아직 로딩 전
|
||||
: '온도: '+_temp!.floor().toString()+'℃',
|
||||
'온도'
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -5,7 +5,7 @@ class LockerApi {
|
||||
// 안드로이드 에뮬레이터: "http://10.0.2.2:8182"
|
||||
// iOS 시뮬레이터: "http://127.0.0.1:8182"
|
||||
// "http://192.168.0.82:8182"
|
||||
static const String baseUrl = "http://192.168.0.81:8182";
|
||||
static const String baseUrl = "http://192.168.0.81:8182";
|
||||
|
||||
// 명령 전송 공통 함수
|
||||
Future<bool> sendCommand({
|
||||
@@ -40,6 +40,37 @@ class LockerApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> getTimeseries({
|
||||
String target = "*",
|
||||
int limit = 200,
|
||||
}) async {
|
||||
final url = Uri.parse('$baseUrl/timeseries/get');
|
||||
|
||||
try {
|
||||
final response = await http.post(
|
||||
url,
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode({
|
||||
"target": target,
|
||||
"limit": limit,
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final jsonData = jsonDecode(response.body);
|
||||
|
||||
print("Timeseries 수신 성공");
|
||||
return jsonData;
|
||||
} else {
|
||||
print("Timeseries 조회 실패: ${response.body}");
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
print("서버 연결 오류: $e");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// --- [기능별 동작 함수] ---
|
||||
|
||||
// 1. 잠금 해제 (주소: 0x0016 / 값: 1)
|
||||
|
||||
@@ -166,13 +166,20 @@ const String _locationTermContent =
|
||||
'부칙 제1조 (시행일)\n'
|
||||
'본 약관은 2025년 11월 28일부터 시행합니다.\n';
|
||||
|
||||
const String _marketingTermContent = """
|
||||
1. 수집 및 이용 목적
|
||||
이벤트 정보 및 참여 기회 제공, 광고성 정보 제공 등 마케팅 활동을 위해 사용됩니다.
|
||||
|
||||
2. 수신 동의 철회
|
||||
회원은 언제든지 설정 메뉴 또는 고객센터를 통해 마케팅 정보 수신 동의를 철회할 수 있습니다. 수신 동의를 철회하더라도 기본 서비스 이용에는 제한이 없습니다.
|
||||
""";
|
||||
const String _marketingTermContent =
|
||||
'(주)메타큐랩이 제공하는 이벤트 및 혜택 등 마케팅 정보를 수신하는 것에 동의합니다.\n\n'
|
||||
'1. 수집 및 이용 목적\n'
|
||||
'- 신규 서비스(기능) 개발 및 맞춤 서비스 제공.\n'
|
||||
'- 이벤트, 프로모션, 혜택 등 광고성 정보 제공.\n'
|
||||
'- 서비스 이용 통계 및 설문조사.\n\n'
|
||||
'2. 수집하는 개인정보 항목\n'
|
||||
'- 이름, 휴대전화번호, 이메일, PUSH 토큰.\n\n'
|
||||
'3. 보유 및 이용 기간\n'
|
||||
'- 회원 탈퇴 또는 동의 철회 시까지\n\n'
|
||||
'4. 전송 방법\n'
|
||||
'- 앱 푸시(App Push) 알림, SMS(문자메시지), 이메일 등.\n\n'
|
||||
'5. 동의 거부 권리\n'
|
||||
'귀하는 마케팅 정보 수신에 대한 동의를 거부할 수 있습니다. 동의를 거부하더라도 회원 가입 및 기본 서비스 이용에는 제한이 없습니다. 다만, 이벤트 및 혜택 정보 제공이 제한될 수 있습니다.\n';
|
||||
|
||||
class SettingsScreen extends StatefulWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
||||
Reference in New Issue
Block a user