Files
ignis_app/lib/services/api_client.dart
2026-05-16 10:29:54 +07:00

136 lines
5.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:dio/dio.dart';
/// HTTP-клиент для одного сервера Ignis.
/// Покрывает все эндпоинты из openapi.json.
class IgnisApi {
IgnisApi({Dio? dio}) : _dio = dio ?? Dio();
final Dio _dio;
Dio get dioInstance => _dio;
static String normalizeBaseUrl(String baseUrl) {
var url = baseUrl.trim();
final lowerUrl = url.toLowerCase();
if (!lowerUrl.startsWith('http://') && !lowerUrl.startsWith('https://')) {
url = 'https://$url';
}
while (url.endsWith('/')) {
url = url.substring(0, url.length - 1);
}
return url;
}
/// Инициализация базового URL и API-ключа
void init(String baseUrl, String apiKey) {
_dio.options.baseUrl = normalizeBaseUrl(baseUrl);
_dio.options.headers['X-API-Key'] = apiKey;
// Бэкенд WiZ ламп тормозит -- даём запас
_dio.options.connectTimeout = const Duration(seconds: 15);
_dio.options.receiveTimeout = const Duration(seconds: 15);
}
Future<void> validateCredentials(String baseUrl, String apiKey) async {
final probe = IgnisApi()..init(baseUrl, apiKey);
try {
await probe.getAuthMe();
} finally {
probe.dioInstance.close();
}
}
// ─── Авторизация ───────────────────────────────────────────
/// Проверка текущего ключа: возвращает {is_admin, name}
Future<Response> getAuthMe() => _dio.get('/auth/me');
// ─── Устройства и группы ───────────────────────────────────
/// Все устройства (лампы)
Future<Response> getDevices() => _dio.get('/devices');
/// Все группы
Future<Response> getGroups() => _dio.get('/devices/groups');
/// Все доступные сцены
Future<Response> getScenes() => _dio.get('/devices/scenes');
/// Создать группу
Future<Response> createGroup(String id, String name, List<String> macs) =>
_dio.post(
'/devices/groups',
data: {'id': id, 'name': name, 'macs': macs},
);
/// Удалить группу
Future<Response> deleteGroup(String groupId) =>
_dio.delete('/devices/groups/$groupId');
/// Пересканировать сеть (найти новые лампы)
Future<Response> rescanNetwork() => _dio.post('/devices/rescan');
// ─── Управление ────────────────────────────────────────────
/// Управление группой: state, brightness, temp, scene, r/g/b
Future<Response> controlGroup(String id, Map<String, dynamic> params) =>
_dio.post('/control/group/$id', data: params);
/// Управление одной лампой
Future<Response> controlDevice(String id, Map<String, dynamic> params) =>
_dio.post('/control/device/$id', data: params);
/// Мигнуть лампой (для идентификации)
Future<Response> blinkDevice(String id) =>
_dio.post('/control/device/$id/blink');
/// Статус группы (реальный опрос ламп)
Future<Response> getGroupStatus(String id) =>
_dio.get('/control/group/$id/status');
/// Статус одной лампы
Future<Response> getDeviceStatus(String id) =>
_dio.get('/control/device/$id/status');
// ─── Расписания ────────────────────────────────────────────
/// Одноразовое расписание (таймер)
Future<Response> scheduleOnce(Map<String, dynamic> params) =>
_dio.post('/schedules/once', data: params);
/// Cron-расписание (повторяющееся)
Future<Response> scheduleCron(Map<String, dynamic> params) =>
_dio.post('/schedules/cron', data: params);
/// Все активные задачи расписания
Future<Response> getTasks() => _dio.get('/schedules/tasks');
/// Отменить задачу расписания
Future<Response> cancelTask(String jobId) => _dio.delete('/schedules/$jobId');
// ─── API-ключи ─────────────────────────────────────────────
/// Список всех гостевых ключей
Future<Response> getApiKeys() => _dio.get('/api-keys');
/// Создать гостевой ключ
Future<Response> createApiKey(String name, {bool isAdmin = false}) => _dio
.post('/api-keys', queryParameters: {'name': name, 'is_admin': isAdmin});
/// Отозвать ключ (body: {key: ...})
Future<Response> revokeApiKey(String key) =>
_dio.post('/api-keys/revoke', data: {'key': key});
/// Активировать ключ (body: {key: ...})
Future<Response> activateApiKey(String key) =>
_dio.post('/api-keys/activate', data: {'key': key});
// ─── Статистика ────────────────────────────────────────────
/// Сводная статистика за N дней
Future<Response> getStatsSummary({int days = 7}) =>
_dio.get('/stats/summary', queryParameters: {'days': days});
/// Лог последних N событий
Future<Response> getStatsLog({int limit = 100}) =>
_dio.get('/stats/log', queryParameters: {'limit': limit});
}