feat(gps): valid=false от протокола H02 → точка сохраняется как LBS-примерная (не выбрасывается), сигнал потери GPS
This commit is contained in:
@@ -51,6 +51,8 @@ export interface ProcessPositionInput {
|
||||
course?: number | null;
|
||||
accuracy?: number | null;
|
||||
recordedAt?: Date;
|
||||
/** Протокольный признак «GPS невалиден» (Traccar valid=false) — LBS-точка */
|
||||
forceLbs?: boolean;
|
||||
}
|
||||
|
||||
// Вердикт фильтрации точки относительно предыдущей принятой
|
||||
@@ -500,6 +502,50 @@ export async function processPosition(
|
||||
? { lat: asset.lastLat, lng: asset.lastLng, recordedAt: asset.lastRecordedAt, speed: asset.lastSpeed }
|
||||
: null;
|
||||
|
||||
// Протокольный флаг «GPS невалиден» (Traccar valid=false): это точка по вышкам.
|
||||
// Сохраняем как примерную (is_lbs), маркер двигаем, но walker/геозоны/пробег
|
||||
// не трогаем. Заодно это сигнал потери GPS — как stale re-send.
|
||||
if (input.forceLbs) {
|
||||
assetLastStaleAt.set(assetId, Date.now());
|
||||
if (!asset.gpsLost) {
|
||||
await gpsStorage.setGpsLost(assetId, true);
|
||||
console.log(`[GPS] gps_lost ON: asset=${assetId} (valid=false от протокола)`);
|
||||
}
|
||||
await gpsStorage.insertPosition({
|
||||
assetId,
|
||||
organizationId,
|
||||
lat: input.lat,
|
||||
lng: input.lng,
|
||||
speed: input.speed ?? null,
|
||||
course: input.course ?? null,
|
||||
accuracy: input.accuracy ?? null,
|
||||
isLbs: true,
|
||||
recordedAt,
|
||||
});
|
||||
await gpsStorage.updateAssetLastPosition(assetId, {
|
||||
lat: input.lat,
|
||||
lng: input.lng,
|
||||
speed: input.speed,
|
||||
course: input.course,
|
||||
recordedAt,
|
||||
isLbs: true,
|
||||
});
|
||||
eventBus.publishEvent({
|
||||
type: "gps_asset_moved",
|
||||
data: {
|
||||
assetId,
|
||||
lat: input.lat,
|
||||
lng: input.lng,
|
||||
speed: input.speed ?? null,
|
||||
course: input.course ?? null,
|
||||
recordedAt: recordedAt.toISOString(),
|
||||
isLbs: true,
|
||||
},
|
||||
organizationId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Фильтры stale/jump/echo с гистерезисом подтверждения (устаревшие копии,
|
||||
// LBS-скачки, heartbeat-эхо стоянки)
|
||||
const walker = getAssetWalker(assetId, prev, settings);
|
||||
|
||||
@@ -261,16 +261,12 @@ async function handleIngest(req: AuthenticatedRequest, res: Response) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Traccar пометил позицию как невалидную (valid=false) — не сохраняем,
|
||||
// но считаем признаком жизни устройства
|
||||
if (!point.valid) {
|
||||
await gpsStorage.touchAssetSeen(asset.id);
|
||||
processed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await processPosition(asset.id, asset.organizationId, {
|
||||
// Traccar пометил позицию как невалидную (valid=false) — протокольный
|
||||
// признак «нет GPS-фикса»: сохраняем как примерную (LBS), в геозоны
|
||||
// и пробег не пускаем
|
||||
forceLbs: !point.valid,
|
||||
lat: point.lat,
|
||||
lng: point.lng,
|
||||
speed: point.speed,
|
||||
|
||||
Reference in New Issue
Block a user