MotorSignal-App/lib/services/alerts/community_traffic_provider....

101 lines
3.2 KiB
Dart

import 'dart:convert';
import 'dart:math' as math;
import 'package:http/http.dart' as http;
import 'road_alert_models.dart';
import 'road_alert_provider_interface.dart';
import 'community_traffic_parser.dart';
class CommunityTrafficRoadAlertProvider implements RoadAlertProvider {
final String _customEndpointUrl;
CommunityTrafficRoadAlertProvider({String? endpointUrl})
: _customEndpointUrl = endpointUrl ?? '';
@override
String get id => 'community_traffic';
@override
String get name => 'Community Traffic API';
@override
Set<RoadAlertCategory> get supportedCategories => const {
RoadAlertCategory.police,
RoadAlertCategory.speedCamera,
RoadAlertCategory.accident,
RoadAlertCategory.hazard,
RoadAlertCategory.roadClosure,
RoadAlertCategory.construction,
RoadAlertCategory.traffic,
RoadAlertCategory.other,
};
@override
Future<RoadAlertProviderStatus> testConnection(String apiKey) async {
if (apiKey.trim().isEmpty && _customEndpointUrl.isEmpty) {
return RoadAlertProviderStatus.notConfigured;
}
try {
final endpoint = _customEndpointUrl.isNotEmpty
? _customEndpointUrl
: 'https://api.communitytraffic.org/v1/incidents';
final uri = Uri.parse('$endpoint?top=37.80&bottom=37.70&left=-122.50&right=-122.35&apiKey=$apiKey');
final response = await http.get(uri).timeout(const Duration(seconds: 6));
if (response.statusCode == 200) {
return RoadAlertProviderStatus.connected;
} else if (response.statusCode == 401 || response.statusCode == 403) {
return RoadAlertProviderStatus.authError;
} else if (response.statusCode == 429) {
return RoadAlertProviderStatus.rateLimited;
}
return RoadAlertProviderStatus.networkError;
} catch (_) {
return RoadAlertProviderStatus.networkError;
}
}
@override
Future<List<RoadAlert>> getAlerts({
required double latitude,
required double longitude,
required double radiusMeters,
String? apiKey,
}) async {
if ((apiKey == null || apiKey.trim().isEmpty) && _customEndpointUrl.isEmpty) {
return [];
}
try {
final latOffset = radiusMeters / 111000.0;
final lngOffset = radiusMeters / (111000.0 * math.cos(latitude * math.pi / 180.0));
final top = (latitude + latOffset).toStringAsFixed(5);
final bottom = (latitude - latOffset).toStringAsFixed(5);
final left = (longitude - lngOffset).toStringAsFixed(5);
final right = (longitude + lngOffset).toStringAsFixed(5);
final endpoint = _customEndpointUrl.isNotEmpty
? _customEndpointUrl
: 'https://api.communitytraffic.org/v1/incidents';
final uri = Uri.parse('$endpoint?top=$top&bottom=$bottom&left=$left&right=$right&apiKey=${apiKey ?? ''}');
final response = await http.get(uri).timeout(const Duration(seconds: 8));
if (response.statusCode != 200) {
return [];
}
final Map<String, dynamic> jsonMap = json.decode(response.body);
return CommunityTrafficParser.parseAlertsJson(
jsonMap,
providerId: id,
providerName: name,
);
} catch (_) {
return [];
}
}
}