HTTP-клиент к /api/v1 с Sanctum-токеном (хранится в secure storage), модели зеркалят Laravel API Resources. Экраны: логин, список устройств с живым статусом, детальная страница устройства (история телеметрии, turn-on/turn-off/set-level с проверкой capability), списки зон и правил автоматизации (пока только чтение — формы создания/редактирования впереди).
130 lines
4.2 KiB
Dart
130 lines
4.2 KiB
Dart
import '../models/automation_rule.dart';
|
|
import '../models/device.dart';
|
|
import '../models/device_type.dart';
|
|
import '../models/zone.dart';
|
|
import 'api_client.dart';
|
|
|
|
/// Typed wrappers for every `/api/v1` endpoint besides auth (see
|
|
/// [AuthService] for login/logout/me). One method per backend action —
|
|
/// no generic "request" escape hatch, so call sites stay self-documenting.
|
|
class ApiService {
|
|
ApiService(this._client);
|
|
|
|
final ApiClient _client;
|
|
|
|
// --- Zones ---
|
|
|
|
Future<List<Zone>> zones() async {
|
|
final json = await _client.get('/zones');
|
|
return _list(json).map(Zone.fromJson).toList();
|
|
}
|
|
|
|
Future<Zone> createZone({required String name, String? description}) async {
|
|
final json = await _client.post('/zones', {
|
|
'name': name,
|
|
if (description != null && description.isNotEmpty) 'description': description,
|
|
});
|
|
return Zone.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<Zone> updateZone(int id, {required String name, String? description}) async {
|
|
final json = await _client.put('/zones/$id', {
|
|
'name': name,
|
|
if (description != null && description.isNotEmpty) 'description': description,
|
|
});
|
|
return Zone.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<void> deleteZone(int id) => _client.delete('/zones/$id');
|
|
|
|
// --- Device types ---
|
|
|
|
Future<List<DeviceType>> deviceTypes() async {
|
|
final json = await _client.get('/device-types');
|
|
return _list(json).map(DeviceType.fromJson).toList();
|
|
}
|
|
|
|
// --- Devices ---
|
|
|
|
Future<List<Device>> devices() async {
|
|
final json = await _client.get('/devices');
|
|
return _list(json).map(Device.fromJson).toList();
|
|
}
|
|
|
|
Future<DeviceDetail> device(int id) async {
|
|
final json = await _client.get('/devices/$id');
|
|
return DeviceDetail.fromJson(json as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<Device> createDevice({
|
|
required int zoneId,
|
|
required int deviceTypeId,
|
|
required String name,
|
|
required String externalId,
|
|
String protocol = 'mqtt',
|
|
}) async {
|
|
final json = await _client.post('/devices', {
|
|
'zone_id': zoneId,
|
|
'device_type_id': deviceTypeId,
|
|
'name': name,
|
|
'external_id': externalId,
|
|
'protocol': protocol,
|
|
});
|
|
return Device.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<Device> updateDevice(
|
|
int id, {
|
|
required int zoneId,
|
|
required int deviceTypeId,
|
|
required String name,
|
|
required String externalId,
|
|
String protocol = 'mqtt',
|
|
}) async {
|
|
final json = await _client.put('/devices/$id', {
|
|
'zone_id': zoneId,
|
|
'device_type_id': deviceTypeId,
|
|
'name': name,
|
|
'external_id': externalId,
|
|
'protocol': protocol,
|
|
});
|
|
return Device.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<void> deleteDevice(int id) => _client.delete('/devices/$id');
|
|
|
|
Future<String> turnOn(int deviceId) => _commandMessage(_client.post('/devices/$deviceId/turn-on'));
|
|
|
|
Future<String> turnOff(int deviceId) => _commandMessage(_client.post('/devices/$deviceId/turn-off'));
|
|
|
|
Future<String> setLevel(int deviceId, double level) =>
|
|
_commandMessage(_client.post('/devices/$deviceId/set-level', {'level': level}));
|
|
|
|
Future<String> _commandMessage(Future<dynamic> request) async {
|
|
final json = await request;
|
|
return (json as Map<String, dynamic>)['message'] as String? ?? 'Готово.';
|
|
}
|
|
|
|
// --- Automation rules ---
|
|
|
|
Future<List<AutomationRule>> automationRules() async {
|
|
final json = await _client.get('/automation-rules');
|
|
return _list(json).map(AutomationRule.fromJson).toList();
|
|
}
|
|
|
|
Future<AutomationRule> createAutomationRule(Map<String, dynamic> payload) async {
|
|
final json = await _client.post('/automation-rules', payload);
|
|
return AutomationRule.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<AutomationRule> updateAutomationRule(int id, Map<String, dynamic> payload) async {
|
|
final json = await _client.put('/automation-rules/$id', payload);
|
|
return AutomationRule.fromJson(json['data'] as Map<String, dynamic>);
|
|
}
|
|
|
|
Future<void> deleteAutomationRule(int id) => _client.delete('/automation-rules/$id');
|
|
|
|
List<Map<String, dynamic>> _list(dynamic json) =>
|
|
List<Map<String, dynamic>>.from((json as Map<String, dynamic>)['data'] as List);
|
|
}
|