Fix route calculation HTTP 400 by filtering empty profile tags

Built-in profiles (Flock, Motorola, etc.) include placeholder empty
values like camera:mount: '' for user refinement. When these get
serialized into the routing request body, the alprwatch API rejects
them with HTTP 400.

Fix: strip empty-valued tags from enabled_profiles before sending
the routing request. Also refactor RoutingService to accept an
injectable http.Client for testability, and log error response
bodies for easier debugging of future API issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Doug Borg
2026-02-08 10:07:25 -07:00
committed by Doug Borg
parent 6607e30038
commit 71776ee8f0

View File

@@ -27,6 +27,9 @@ class RouteResult {
class RoutingService {
static const String _baseUrl = 'https://alprwatch.org/api/v1/deflock/directions';
static const String _userAgent = 'DeFlock/1.0 (OSM surveillance mapping app)';
final http.Client _client;
RoutingService({http.Client? client}) : _client = client ?? http.Client();
// Calculate route between two points using alprwatch
Future<RouteResult> calculateRoute({
@@ -40,10 +43,12 @@ class RoutingService {
final enabledProfiles = AppState.instance.enabledProfiles.map((p) {
final full = p.toJson();
final tags = Map<String, String>.from(full['tags'] as Map);
tags.removeWhere((key, value) => value.isEmpty);
return {
'id': full['id'],
'name': full['name'],
'tags': full['tags'],
'tags': tags,
};
}).toList();
@@ -65,7 +70,7 @@ class RoutingService {
debugPrint('[RoutingService] alprwatch request: $uri $params');
try {
final response = await http.post(
final response = await _client.post(
uri,
headers: {
'User-Agent': _userAgent,
@@ -75,6 +80,7 @@ class RoutingService {
).timeout(kNavigationRoutingTimeout);
if (response.statusCode != 200) {
debugPrint('[RoutingService] Error response body: ${response.body}');
throw RoutingException('HTTP ${response.statusCode}: ${response.reasonPhrase}');
}