101 lines
3.2 KiB
Dart
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 [];
|
|
}
|
|
}
|
|
}
|