ultimatedarktower 2.5.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -1
- package/README.md +84 -71
- package/dist/esm/index.mjs +1270 -268
- package/dist/src/UltimateDarkTower.d.ts +48 -6
- package/dist/src/UltimateDarkTower.js +115 -53
- package/dist/src/UltimateDarkTower.js.map +1 -1
- package/dist/src/adapters/NodeBluetoothAdapter.js +9 -5
- package/dist/src/adapters/NodeBluetoothAdapter.js.map +1 -1
- package/dist/src/adapters/WebBluetoothAdapter.js +11 -8
- package/dist/src/adapters/WebBluetoothAdapter.js.map +1 -1
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +34 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/sinks/IndexedDBSink.d.ts +26 -0
- package/dist/src/sinks/IndexedDBSink.js +165 -0
- package/dist/src/sinks/IndexedDBSink.js.map +1 -0
- package/dist/src/udtBleConnection.d.ts +28 -5
- package/dist/src/udtBleConnection.js +80 -13
- package/dist/src/udtBleConnection.js.map +1 -1
- package/dist/src/udtBluetoothAdapter.d.ts +6 -6
- package/dist/src/udtBluetoothAdapter.js.map +1 -1
- package/dist/src/udtCommandFactory.d.ts +6 -0
- package/dist/src/udtCommandFactory.js +26 -22
- package/dist/src/udtCommandFactory.js.map +1 -1
- package/dist/src/udtCommandQueue.d.ts +6 -3
- package/dist/src/udtCommandQueue.js +28 -5
- package/dist/src/udtCommandQueue.js.map +1 -1
- package/dist/src/udtConstants.d.ts +3 -8
- package/dist/src/udtConstants.js +2 -0
- package/dist/src/udtConstants.js.map +1 -1
- package/dist/src/udtDiagnostics.d.ts +122 -0
- package/dist/src/udtDiagnostics.js +228 -0
- package/dist/src/udtDiagnostics.js.map +1 -0
- package/dist/src/udtGameBoard.d.ts +38 -0
- package/dist/src/udtGameBoard.js +86 -0
- package/dist/src/udtGameBoard.js.map +1 -0
- package/dist/src/udtLogger.d.ts +16 -0
- package/dist/src/udtLogger.js +41 -2
- package/dist/src/udtLogger.js.map +1 -1
- package/dist/src/udtSeedParser.d.ts +124 -0
- package/dist/src/udtSeedParser.js +369 -0
- package/dist/src/udtSeedParser.js.map +1 -0
- package/dist/src/udtSystemRandom.d.ts +58 -0
- package/dist/src/udtSystemRandom.js +154 -0
- package/dist/src/udtSystemRandom.js.map +1 -0
- package/dist/src/udtTowerCommands.d.ts +4 -2
- package/dist/src/udtTowerCommands.js +24 -43
- package/dist/src/udtTowerCommands.js.map +1 -1
- package/dist/src/udtTowerResponse.d.ts +9 -5
- package/dist/src/udtTowerResponse.js +5 -6
- package/dist/src/udtTowerResponse.js.map +1 -1
- package/package.json +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebBluetoothAdapter.js","sourceRoot":"","sources":["../../../src/adapters/WebBluetoothAdapter.ts"],"names":[],"mappings":";;;AAAA,kDAcyB;AACzB,gEAKgC;AAGhC;;;GAGG;AACH,MAAa,mBAAmB;IAAhC;QACY,WAAM,
|
|
1
|
+
{"version":3,"file":"WebBluetoothAdapter.js","sourceRoot":"","sources":["../../../src/adapters/WebBluetoothAdapter.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -15,5 +15,13 @@ export { rtdt_unpack_state, rtdt_pack_state, isCalibrated } from './udtTowerStat
|
|
|
15
15
|
export { createDefaultTowerState, parseDifferentialReadings, type ParsedDifferentialReadings } from './udtHelpers';
|
|
16
16
|
export type { TowerResponseConfig } from './udtTowerResponse';
|
|
17
17
|
export type { TowerEventCallbacks, DeviceInformation, ConnectionStatus } from './udtBleConnection';
|
|
18
|
+
export { UdtDiagnosticsRecorder, InMemorySink, bytesToHex } from './udtDiagnostics';
|
|
19
|
+
export type { DiagnosticsConfig, DiagnosticsSink, DiagEvent, DiagEventKind, DisconnectCause, IncidentReport, BatterySample, CommandQueueSnapshot, } from './udtDiagnostics';
|
|
20
|
+
export { IndexedDBSink } from './sinks/IndexedDBSink';
|
|
21
|
+
export { charToValue, valueToChar, validateSeed, decodeSeed, decodeRngSeed, createSeed, encodeSeed, compareSeedsRaw, dumpSeedChars, TIER1_FOES, TIER2_FOES, TIER3_FOES, ADVERSARIES, ALLIES, DIFFICULTIES, GAME_SOURCES, } from './udtSeedParser';
|
|
22
|
+
export type { Tier1Foe, Tier2Foe, Tier3Foe, Adversary, Ally, Difficulty, GameSource, ExpansionType, Confidence, SeedBank, DecodedSeed, SeedConfig, CharDiff, SeedComparison, CharInfo, CharDump, } from './udtSeedParser';
|
|
23
|
+
export { SystemRandom } from './udtSystemRandom';
|
|
24
|
+
export { BOARD_LOCATIONS, BOARD_LOCATION_BY_NAME, BOARD_GROUPINGS, } from './udtGameBoard';
|
|
25
|
+
export type { TerrainType, BuildingType, BoardKingdom, BoardGrouping, BoardLocation } from './udtGameBoard';
|
|
18
26
|
import UltimateDarkTower from './UltimateDarkTower';
|
|
19
27
|
export default UltimateDarkTower;
|
package/dist/src/index.js
CHANGED
|
@@ -21,7 +21,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
21
21
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.parseDifferentialReadings = exports.createDefaultTowerState = exports.isCalibrated = exports.rtdt_pack_state = exports.rtdt_unpack_state = exports.BluetoothAdapterFactory = exports.BluetoothPlatform = exports.BluetoothTimeoutError = exports.BluetoothUserCancelledError = exports.BluetoothDeviceNotFoundError = exports.BluetoothConnectionError = exports.BluetoothError = exports.milliVoltsToPercentageNumber = exports.milliVoltsToPercentage = exports.BufferOutput = exports.DOMOutput = exports.ConsoleOutput = exports.Logger = exports.logger = exports.UltimateDarkTower = void 0;
|
|
24
|
+
exports.BOARD_GROUPINGS = exports.BOARD_LOCATION_BY_NAME = exports.BOARD_LOCATIONS = exports.SystemRandom = exports.GAME_SOURCES = exports.DIFFICULTIES = exports.ALLIES = exports.ADVERSARIES = exports.TIER3_FOES = exports.TIER2_FOES = exports.TIER1_FOES = exports.dumpSeedChars = exports.compareSeedsRaw = exports.encodeSeed = exports.createSeed = exports.decodeRngSeed = exports.decodeSeed = exports.validateSeed = exports.valueToChar = exports.charToValue = exports.IndexedDBSink = exports.bytesToHex = exports.InMemorySink = exports.UdtDiagnosticsRecorder = exports.parseDifferentialReadings = exports.createDefaultTowerState = exports.isCalibrated = exports.rtdt_pack_state = exports.rtdt_unpack_state = exports.BluetoothAdapterFactory = exports.BluetoothPlatform = exports.BluetoothTimeoutError = exports.BluetoothUserCancelledError = exports.BluetoothDeviceNotFoundError = exports.BluetoothConnectionError = exports.BluetoothError = exports.milliVoltsToPercentageNumber = exports.milliVoltsToPercentage = exports.BufferOutput = exports.DOMOutput = exports.ConsoleOutput = exports.Logger = exports.logger = exports.UltimateDarkTower = void 0;
|
|
25
25
|
var UltimateDarkTower_1 = require("./UltimateDarkTower");
|
|
26
26
|
Object.defineProperty(exports, "UltimateDarkTower", { enumerable: true, get: function () { return __importDefault(UltimateDarkTower_1).default; } });
|
|
27
27
|
__exportStar(require("./udtConstants"), exports);
|
|
@@ -50,6 +50,39 @@ Object.defineProperty(exports, "isCalibrated", { enumerable: true, get: function
|
|
|
50
50
|
var udtHelpers_2 = require("./udtHelpers");
|
|
51
51
|
Object.defineProperty(exports, "createDefaultTowerState", { enumerable: true, get: function () { return udtHelpers_2.createDefaultTowerState; } });
|
|
52
52
|
Object.defineProperty(exports, "parseDifferentialReadings", { enumerable: true, get: function () { return udtHelpers_2.parseDifferentialReadings; } });
|
|
53
|
+
// BLE disconnect diagnostics ("flight recorder") - off by default, see docs/BLE_DIAGNOSTICS.md
|
|
54
|
+
var udtDiagnostics_1 = require("./udtDiagnostics");
|
|
55
|
+
Object.defineProperty(exports, "UdtDiagnosticsRecorder", { enumerable: true, get: function () { return udtDiagnostics_1.UdtDiagnosticsRecorder; } });
|
|
56
|
+
Object.defineProperty(exports, "InMemorySink", { enumerable: true, get: function () { return udtDiagnostics_1.InMemorySink; } });
|
|
57
|
+
Object.defineProperty(exports, "bytesToHex", { enumerable: true, get: function () { return udtDiagnostics_1.bytesToHex; } });
|
|
58
|
+
var IndexedDBSink_1 = require("./sinks/IndexedDBSink");
|
|
59
|
+
Object.defineProperty(exports, "IndexedDBSink", { enumerable: true, get: function () { return IndexedDBSink_1.IndexedDBSink; } });
|
|
60
|
+
// Seed parser
|
|
61
|
+
var udtSeedParser_1 = require("./udtSeedParser");
|
|
62
|
+
Object.defineProperty(exports, "charToValue", { enumerable: true, get: function () { return udtSeedParser_1.charToValue; } });
|
|
63
|
+
Object.defineProperty(exports, "valueToChar", { enumerable: true, get: function () { return udtSeedParser_1.valueToChar; } });
|
|
64
|
+
Object.defineProperty(exports, "validateSeed", { enumerable: true, get: function () { return udtSeedParser_1.validateSeed; } });
|
|
65
|
+
Object.defineProperty(exports, "decodeSeed", { enumerable: true, get: function () { return udtSeedParser_1.decodeSeed; } });
|
|
66
|
+
Object.defineProperty(exports, "decodeRngSeed", { enumerable: true, get: function () { return udtSeedParser_1.decodeRngSeed; } });
|
|
67
|
+
Object.defineProperty(exports, "createSeed", { enumerable: true, get: function () { return udtSeedParser_1.createSeed; } });
|
|
68
|
+
Object.defineProperty(exports, "encodeSeed", { enumerable: true, get: function () { return udtSeedParser_1.encodeSeed; } });
|
|
69
|
+
Object.defineProperty(exports, "compareSeedsRaw", { enumerable: true, get: function () { return udtSeedParser_1.compareSeedsRaw; } });
|
|
70
|
+
Object.defineProperty(exports, "dumpSeedChars", { enumerable: true, get: function () { return udtSeedParser_1.dumpSeedChars; } });
|
|
71
|
+
Object.defineProperty(exports, "TIER1_FOES", { enumerable: true, get: function () { return udtSeedParser_1.TIER1_FOES; } });
|
|
72
|
+
Object.defineProperty(exports, "TIER2_FOES", { enumerable: true, get: function () { return udtSeedParser_1.TIER2_FOES; } });
|
|
73
|
+
Object.defineProperty(exports, "TIER3_FOES", { enumerable: true, get: function () { return udtSeedParser_1.TIER3_FOES; } });
|
|
74
|
+
Object.defineProperty(exports, "ADVERSARIES", { enumerable: true, get: function () { return udtSeedParser_1.ADVERSARIES; } });
|
|
75
|
+
Object.defineProperty(exports, "ALLIES", { enumerable: true, get: function () { return udtSeedParser_1.ALLIES; } });
|
|
76
|
+
Object.defineProperty(exports, "DIFFICULTIES", { enumerable: true, get: function () { return udtSeedParser_1.DIFFICULTIES; } });
|
|
77
|
+
Object.defineProperty(exports, "GAME_SOURCES", { enumerable: true, get: function () { return udtSeedParser_1.GAME_SOURCES; } });
|
|
78
|
+
// System.Random replica (C# PRNG)
|
|
79
|
+
var udtSystemRandom_1 = require("./udtSystemRandom");
|
|
80
|
+
Object.defineProperty(exports, "SystemRandom", { enumerable: true, get: function () { return udtSystemRandom_1.SystemRandom; } });
|
|
81
|
+
// Game board data
|
|
82
|
+
var udtGameBoard_1 = require("./udtGameBoard");
|
|
83
|
+
Object.defineProperty(exports, "BOARD_LOCATIONS", { enumerable: true, get: function () { return udtGameBoard_1.BOARD_LOCATIONS; } });
|
|
84
|
+
Object.defineProperty(exports, "BOARD_LOCATION_BY_NAME", { enumerable: true, get: function () { return udtGameBoard_1.BOARD_LOCATION_BY_NAME; } });
|
|
85
|
+
Object.defineProperty(exports, "BOARD_GROUPINGS", { enumerable: true, get: function () { return udtGameBoard_1.BOARD_GROUPINGS; } });
|
|
53
86
|
// For convenience, also export as default
|
|
54
87
|
const UltimateDarkTower_2 = __importDefault(require("./UltimateDarkTower"));
|
|
55
88
|
exports.default = UltimateDarkTower_2.default;
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;AAEH,yDAAmE;AAA1D,uIAAA,OAAO,OAAqB;AAErC,iDAA+B;AAC/B,yCAAoH;AAA3G,mGAAA,MAAM,OAAA;AAAE,mGAAA,MAAM,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,sGAAA,SAAS,OAAA;AAAE,yGAAA,YAAY,OAAA;AAC/D,2CAAoF;AAA3E,oHAAA,sBAAsB,OAAA;AAAE,0HAAA,4BAA4B,OAAA;AAI7D,6DAM+B;AAL7B,qHAAA,cAAc,OAAA;AACd,+HAAA,wBAAwB,OAAA;AACxB,mIAAA,4BAA4B,OAAA;AAC5B,kIAAA,2BAA2B,OAAA;AAC3B,4HAAA,qBAAqB,OAAA;AAEvB,2EAA0F;AAAjF,+HAAA,iBAAiB,OAAA;AAAE,qIAAA,uBAAuB,OAAA;AAInD,iDAAmF;AAA1E,kHAAA,iBAAiB,OAAA;AAAE,gHAAA,eAAe,OAAA;AAAE,6GAAA,YAAY,OAAA;AACzD,2CAAmH;AAA1G,qHAAA,uBAAuB,OAAA;AAAE,uHAAA,yBAAyB,OAAA;AAQ3D,0CAA0C;AAC1C,4EAAoD;AACpD,kBAAe,2BAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;AAEH,yDAAmE;AAA1D,uIAAA,OAAO,OAAqB;AAErC,iDAA+B;AAC/B,yCAAoH;AAA3G,mGAAA,MAAM,OAAA;AAAE,mGAAA,MAAM,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,sGAAA,SAAS,OAAA;AAAE,yGAAA,YAAY,OAAA;AAC/D,2CAAoF;AAA3E,oHAAA,sBAAsB,OAAA;AAAE,0HAAA,4BAA4B,OAAA;AAI7D,6DAM+B;AAL7B,qHAAA,cAAc,OAAA;AACd,+HAAA,wBAAwB,OAAA;AACxB,mIAAA,4BAA4B,OAAA;AAC5B,kIAAA,2BAA2B,OAAA;AAC3B,4HAAA,qBAAqB,OAAA;AAEvB,2EAA0F;AAAjF,+HAAA,iBAAiB,OAAA;AAAE,qIAAA,uBAAuB,OAAA;AAInD,iDAAmF;AAA1E,kHAAA,iBAAiB,OAAA;AAAE,gHAAA,eAAe,OAAA;AAAE,6GAAA,YAAY,OAAA;AACzD,2CAAmH;AAA1G,qHAAA,uBAAuB,OAAA;AAAE,uHAAA,yBAAyB,OAAA;AAQ3D,+FAA+F;AAC/F,mDAAoF;AAA3E,wHAAA,sBAAsB,OAAA;AAAE,8GAAA,YAAY,OAAA;AAAE,4GAAA,UAAU,OAAA;AAKzD,uDAAsD;AAA7C,8GAAA,aAAa,OAAA;AAEtB,cAAc;AACd,iDAIyB;AAHvB,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,6GAAA,YAAY,OAAA;AAAE,2GAAA,UAAU,OAAA;AAAE,8GAAA,aAAa,OAAA;AACjE,2GAAA,UAAU,OAAA;AAAE,2GAAA,UAAU,OAAA;AAAE,gHAAA,eAAe,OAAA;AAAE,8GAAA,aAAa,OAAA;AACtD,2GAAA,UAAU,OAAA;AAAE,2GAAA,UAAU,OAAA;AAAE,2GAAA,UAAU,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,uGAAA,MAAM,OAAA;AAAE,6GAAA,YAAY,OAAA;AAAE,6GAAA,YAAY,OAAA;AAOrF,kCAAkC;AAClC,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AAErB,kBAAkB;AAClB,+CAIwB;AAHtB,+GAAA,eAAe,OAAA;AACf,sHAAA,sBAAsB,OAAA;AACtB,+GAAA,eAAe,OAAA;AAIjB,0CAA0C;AAC1C,4EAAoD;AACpD,kBAAe,2BAAiB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-only durable sink. Persists incidents to IndexedDB so they survive
|
|
3
|
+
* page refresh and tab close.
|
|
4
|
+
*
|
|
5
|
+
* Quota policy: keeps at most `maxIncidents` (default 50). Oldest by
|
|
6
|
+
* triggeredAt are evicted. Reads are async via list() / get().
|
|
7
|
+
*
|
|
8
|
+
* Falls back to a no-op if IndexedDB is unavailable (server-side rendering,
|
|
9
|
+
* old browsers, file:// protocol with restrictive policies, etc.).
|
|
10
|
+
*/
|
|
11
|
+
import type { DiagnosticsSink, IncidentReport } from '../udtDiagnostics';
|
|
12
|
+
export declare class IndexedDBSink implements DiagnosticsSink {
|
|
13
|
+
private maxIncidents;
|
|
14
|
+
private dbPromise;
|
|
15
|
+
private available;
|
|
16
|
+
constructor(maxIncidents?: number);
|
|
17
|
+
private getDb;
|
|
18
|
+
onIncident(report: IncidentReport): Promise<void>;
|
|
19
|
+
list(): Promise<IncidentReport[]>;
|
|
20
|
+
get(incidentId: string): Promise<IncidentReport | undefined>;
|
|
21
|
+
delete(incidentId: string): Promise<void>;
|
|
22
|
+
clear(): Promise<void>;
|
|
23
|
+
/** Insert an externally-supplied report (e.g. from a JSON import). */
|
|
24
|
+
put(report: IncidentReport): Promise<void>;
|
|
25
|
+
private evictOld;
|
|
26
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Browser-only durable sink. Persists incidents to IndexedDB so they survive
|
|
4
|
+
* page refresh and tab close.
|
|
5
|
+
*
|
|
6
|
+
* Quota policy: keeps at most `maxIncidents` (default 50). Oldest by
|
|
7
|
+
* triggeredAt are evicted. Reads are async via list() / get().
|
|
8
|
+
*
|
|
9
|
+
* Falls back to a no-op if IndexedDB is unavailable (server-side rendering,
|
|
10
|
+
* old browsers, file:// protocol with restrictive policies, etc.).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.IndexedDBSink = void 0;
|
|
14
|
+
const DB_NAME = 'udt-diagnostics';
|
|
15
|
+
const DB_VERSION = 1;
|
|
16
|
+
const STORE_NAME = 'incidents';
|
|
17
|
+
function indexedDBAvailable() {
|
|
18
|
+
try {
|
|
19
|
+
return typeof indexedDB !== 'undefined';
|
|
20
|
+
}
|
|
21
|
+
catch (_a) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function openDb() {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const req = indexedDB.open(DB_NAME, DB_VERSION);
|
|
28
|
+
req.onupgradeneeded = () => {
|
|
29
|
+
const db = req.result;
|
|
30
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
31
|
+
const store = db.createObjectStore(STORE_NAME, { keyPath: 'incidentId' });
|
|
32
|
+
store.createIndex('triggeredAt', 'triggeredAt', { unique: false });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
req.onsuccess = () => resolve(req.result);
|
|
36
|
+
req.onerror = () => reject(req.error);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
class IndexedDBSink {
|
|
40
|
+
constructor(maxIncidents = 50) {
|
|
41
|
+
this.dbPromise = null;
|
|
42
|
+
this.maxIncidents = maxIncidents;
|
|
43
|
+
this.available = indexedDBAvailable();
|
|
44
|
+
}
|
|
45
|
+
async getDb() {
|
|
46
|
+
if (!this.available)
|
|
47
|
+
return null;
|
|
48
|
+
if (!this.dbPromise) {
|
|
49
|
+
this.dbPromise = openDb().catch(err => {
|
|
50
|
+
this.available = false;
|
|
51
|
+
this.dbPromise = null;
|
|
52
|
+
throw err;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
return await this.dbPromise;
|
|
57
|
+
}
|
|
58
|
+
catch (_a) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async onIncident(report) {
|
|
63
|
+
const db = await this.getDb();
|
|
64
|
+
if (!db)
|
|
65
|
+
return;
|
|
66
|
+
await new Promise((resolve, reject) => {
|
|
67
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
68
|
+
const store = tx.objectStore(STORE_NAME);
|
|
69
|
+
store.put(report);
|
|
70
|
+
tx.oncomplete = () => resolve();
|
|
71
|
+
tx.onerror = () => reject(tx.error);
|
|
72
|
+
tx.onabort = () => reject(tx.error);
|
|
73
|
+
}).catch(e => console.error('IndexedDBSink put failed:', e));
|
|
74
|
+
await this.evictOld();
|
|
75
|
+
}
|
|
76
|
+
async list() {
|
|
77
|
+
const db = await this.getDb();
|
|
78
|
+
if (!db)
|
|
79
|
+
return [];
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
82
|
+
const store = tx.objectStore(STORE_NAME);
|
|
83
|
+
const req = store.getAll();
|
|
84
|
+
req.onsuccess = () => {
|
|
85
|
+
const all = req.result.slice();
|
|
86
|
+
all.sort((a, b) => b.triggeredAt - a.triggeredAt);
|
|
87
|
+
resolve(all);
|
|
88
|
+
};
|
|
89
|
+
req.onerror = () => reject(req.error);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async get(incidentId) {
|
|
93
|
+
const db = await this.getDb();
|
|
94
|
+
if (!db)
|
|
95
|
+
return undefined;
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
98
|
+
const store = tx.objectStore(STORE_NAME);
|
|
99
|
+
const req = store.get(incidentId);
|
|
100
|
+
req.onsuccess = () => resolve(req.result);
|
|
101
|
+
req.onerror = () => reject(req.error);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async delete(incidentId) {
|
|
105
|
+
const db = await this.getDb();
|
|
106
|
+
if (!db)
|
|
107
|
+
return;
|
|
108
|
+
await new Promise((resolve, reject) => {
|
|
109
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
110
|
+
tx.objectStore(STORE_NAME).delete(incidentId);
|
|
111
|
+
tx.oncomplete = () => resolve();
|
|
112
|
+
tx.onerror = () => reject(tx.error);
|
|
113
|
+
}).catch(e => console.error('IndexedDBSink delete failed:', e));
|
|
114
|
+
}
|
|
115
|
+
async clear() {
|
|
116
|
+
const db = await this.getDb();
|
|
117
|
+
if (!db)
|
|
118
|
+
return;
|
|
119
|
+
await new Promise((resolve, reject) => {
|
|
120
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
121
|
+
tx.objectStore(STORE_NAME).clear();
|
|
122
|
+
tx.oncomplete = () => resolve();
|
|
123
|
+
tx.onerror = () => reject(tx.error);
|
|
124
|
+
}).catch(e => console.error('IndexedDBSink clear failed:', e));
|
|
125
|
+
}
|
|
126
|
+
/** Insert an externally-supplied report (e.g. from a JSON import). */
|
|
127
|
+
async put(report) {
|
|
128
|
+
return this.onIncident(report);
|
|
129
|
+
}
|
|
130
|
+
async evictOld() {
|
|
131
|
+
const db = await this.getDb();
|
|
132
|
+
if (!db)
|
|
133
|
+
return;
|
|
134
|
+
await new Promise((resolve) => {
|
|
135
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
136
|
+
const store = tx.objectStore(STORE_NAME);
|
|
137
|
+
const countReq = store.count();
|
|
138
|
+
countReq.onsuccess = () => {
|
|
139
|
+
const total = countReq.result;
|
|
140
|
+
if (total <= this.maxIncidents) {
|
|
141
|
+
resolve();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const toRemove = total - this.maxIncidents;
|
|
145
|
+
const idx = store.index('triggeredAt');
|
|
146
|
+
const cursorReq = idx.openCursor();
|
|
147
|
+
let removed = 0;
|
|
148
|
+
cursorReq.onsuccess = () => {
|
|
149
|
+
const cursor = cursorReq.result;
|
|
150
|
+
if (!cursor || removed >= toRemove) {
|
|
151
|
+
resolve();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
cursor.delete();
|
|
155
|
+
removed++;
|
|
156
|
+
cursor.continue();
|
|
157
|
+
};
|
|
158
|
+
cursorReq.onerror = () => resolve();
|
|
159
|
+
};
|
|
160
|
+
countReq.onerror = () => resolve();
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.IndexedDBSink = IndexedDBSink;
|
|
165
|
+
//# sourceMappingURL=IndexedDBSink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexedDBSink.js","sourceRoot":"","sources":["../../../src/sinks/IndexedDBSink.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Logger } from './udtLogger';
|
|
2
2
|
import { type IBluetoothAdapter } from './udtBluetoothAdapter';
|
|
3
|
+
import type { UdtDiagnosticsRecorder, DisconnectCause, IncidentReport } from './udtDiagnostics';
|
|
3
4
|
export interface TowerEventCallbacks {
|
|
4
5
|
onTowerConnect: () => void;
|
|
5
6
|
onTowerDisconnect: () => void;
|
|
@@ -36,6 +37,8 @@ export declare class UdtBleConnection {
|
|
|
36
37
|
private logger;
|
|
37
38
|
private callbacks;
|
|
38
39
|
private responseProcessor;
|
|
40
|
+
private recorder;
|
|
41
|
+
private snapshotProviders;
|
|
39
42
|
private bluetoothAdapter;
|
|
40
43
|
isConnected: boolean;
|
|
41
44
|
isDisposed: boolean;
|
|
@@ -52,11 +55,11 @@ export declare class UdtBleConnection {
|
|
|
52
55
|
enableBatteryHeartbeatMonitoring: boolean;
|
|
53
56
|
batteryHeartbeatVerifyConnection: boolean;
|
|
54
57
|
towerSkullDropCount: number;
|
|
55
|
-
|
|
58
|
+
lastBatteryLog: number;
|
|
56
59
|
lastBatteryPercentage: string;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
batteryLogFrequency: number;
|
|
61
|
+
batteryLogOnChangeOnly: boolean;
|
|
62
|
+
batteryLogEnabled: boolean;
|
|
60
63
|
private deviceInformation;
|
|
61
64
|
logTowerResponses: boolean;
|
|
62
65
|
logTowerResponseConfig: {
|
|
@@ -71,7 +74,27 @@ export declare class UdtBleConnection {
|
|
|
71
74
|
CALIBRATION_FINISHED: boolean;
|
|
72
75
|
LOG_ALL: boolean;
|
|
73
76
|
};
|
|
74
|
-
constructor(logger: Logger, callbacks: TowerEventCallbacks, adapter?: IBluetoothAdapter);
|
|
77
|
+
constructor(logger: Logger, callbacks: TowerEventCallbacks, adapter?: IBluetoothAdapter, recorder?: UdtDiagnosticsRecorder);
|
|
78
|
+
setDiagnosticsSnapshotProviders(providers: {
|
|
79
|
+
commandQueue: () => {
|
|
80
|
+
queueLength: number;
|
|
81
|
+
isProcessing: boolean;
|
|
82
|
+
currentCommand: {
|
|
83
|
+
id: string;
|
|
84
|
+
description?: string;
|
|
85
|
+
timestamp: number;
|
|
86
|
+
} | null;
|
|
87
|
+
};
|
|
88
|
+
towerState: () => unknown;
|
|
89
|
+
brokenSeals: () => string[];
|
|
90
|
+
}): void;
|
|
91
|
+
/**
|
|
92
|
+
* Record a disconnect incident with the recorder. Public so higher layers
|
|
93
|
+
* (e.g. UltimateDarkTower's beforeunload handler) can synthesize causes
|
|
94
|
+
* like 'page_unload' that aren't tied to a specific BLE detection path.
|
|
95
|
+
*/
|
|
96
|
+
recordIncidentPublic(cause: DisconnectCause): IncidentReport | null;
|
|
97
|
+
private recordIncident;
|
|
75
98
|
connect(): Promise<void>;
|
|
76
99
|
disconnect(): Promise<void>;
|
|
77
100
|
/**
|
|
@@ -7,7 +7,12 @@ const udtHelpers_1 = require("./udtHelpers");
|
|
|
7
7
|
const udtTowerState_1 = require("./udtTowerState");
|
|
8
8
|
const udtBluetoothAdapterFactory_1 = require("./udtBluetoothAdapterFactory");
|
|
9
9
|
class UdtBleConnection {
|
|
10
|
-
constructor(logger, callbacks, adapter) {
|
|
10
|
+
constructor(logger, callbacks, adapter, recorder) {
|
|
11
|
+
this.recorder = null;
|
|
12
|
+
// Snapshot providers wired by UltimateDarkTower so the recorder can capture
|
|
13
|
+
// higher-level state (command queue, tower state, broken seals) at the
|
|
14
|
+
// moment a disconnect cause fires.
|
|
15
|
+
this.snapshotProviders = null;
|
|
11
16
|
// Connection state
|
|
12
17
|
this.isConnected = false;
|
|
13
18
|
this.isDisposed = false;
|
|
@@ -27,11 +32,11 @@ class UdtBleConnection {
|
|
|
27
32
|
this.batteryHeartbeatVerifyConnection = true; // When true, verifies connection before triggering disconnection on heartbeat timeout
|
|
28
33
|
// Tower state
|
|
29
34
|
this.towerSkullDropCount = -1;
|
|
30
|
-
this.
|
|
35
|
+
this.lastBatteryLog = 0;
|
|
31
36
|
this.lastBatteryPercentage = "";
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
37
|
+
this.batteryLogFrequency = 15 * 1000;
|
|
38
|
+
this.batteryLogOnChangeOnly = false;
|
|
39
|
+
this.batteryLogEnabled = true;
|
|
35
40
|
// Device information
|
|
36
41
|
this.deviceInformation = {};
|
|
37
42
|
// Logging configuration
|
|
@@ -51,6 +56,7 @@ class UdtBleConnection {
|
|
|
51
56
|
this.logger = logger;
|
|
52
57
|
this.callbacks = callbacks;
|
|
53
58
|
this.responseProcessor = new udtTowerResponse_1.TowerResponseProcessor();
|
|
59
|
+
this.recorder = recorder !== null && recorder !== void 0 ? recorder : null;
|
|
54
60
|
// Use provided adapter or auto-detect platform
|
|
55
61
|
this.bluetoothAdapter = adapter || udtBluetoothAdapterFactory_1.BluetoothAdapterFactory.create(udtBluetoothAdapterFactory_1.BluetoothPlatform.AUTO);
|
|
56
62
|
// Set up adapter event callbacks
|
|
@@ -64,7 +70,37 @@ class UdtBleConnection {
|
|
|
64
70
|
this.bleAvailabilityChange(available);
|
|
65
71
|
});
|
|
66
72
|
}
|
|
73
|
+
setDiagnosticsSnapshotProviders(providers) {
|
|
74
|
+
this.snapshotProviders = providers;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Record a disconnect incident with the recorder. Public so higher layers
|
|
78
|
+
* (e.g. UltimateDarkTower's beforeunload handler) can synthesize causes
|
|
79
|
+
* like 'page_unload' that aren't tied to a specific BLE detection path.
|
|
80
|
+
*/
|
|
81
|
+
recordIncidentPublic(cause) {
|
|
82
|
+
return this.recordIncident(cause);
|
|
83
|
+
}
|
|
84
|
+
recordIncident(cause) {
|
|
85
|
+
var _a, _b, _c, _d, _e, _f;
|
|
86
|
+
if (!this.recorder || !this.recorder.enabled)
|
|
87
|
+
return null;
|
|
88
|
+
const queueSnapshot = (_b = (_a = this.snapshotProviders) === null || _a === void 0 ? void 0 : _a.commandQueue()) !== null && _b !== void 0 ? _b : {
|
|
89
|
+
queueLength: 0, isProcessing: false, currentCommand: null
|
|
90
|
+
};
|
|
91
|
+
const towerState = ((_d = (_c = this.snapshotProviders) === null || _c === void 0 ? void 0 : _c.towerState()) !== null && _d !== void 0 ? _d : null);
|
|
92
|
+
const brokenSeals = (_f = (_e = this.snapshotProviders) === null || _e === void 0 ? void 0 : _e.brokenSeals()) !== null && _f !== void 0 ? _f : [];
|
|
93
|
+
return this.recorder.recordIncident({
|
|
94
|
+
cause,
|
|
95
|
+
connectionStatus: this.getConnectionStatus(),
|
|
96
|
+
deviceInformation: this.getDeviceInformation(),
|
|
97
|
+
commandQueue: queueSnapshot,
|
|
98
|
+
towerState,
|
|
99
|
+
brokenSeals,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
67
102
|
async connect() {
|
|
103
|
+
var _a;
|
|
68
104
|
if (this.isDisposed) {
|
|
69
105
|
throw new Error('UdtBleConnection instance has been disposed and cannot reconnect');
|
|
70
106
|
}
|
|
@@ -75,6 +111,7 @@ class UdtBleConnection {
|
|
|
75
111
|
this.isConnected = true;
|
|
76
112
|
this.lastSuccessfulCommand = Date.now();
|
|
77
113
|
this.lastBatteryHeartbeat = Date.now();
|
|
114
|
+
(_a = this.recorder) === null || _a === void 0 ? void 0 : _a.beginSession();
|
|
78
115
|
// Read device information after successful connection
|
|
79
116
|
await this.readDeviceInformation();
|
|
80
117
|
if (this.enableConnectionMonitoring) {
|
|
@@ -85,11 +122,14 @@ class UdtBleConnection {
|
|
|
85
122
|
catch (error) {
|
|
86
123
|
this.logger.error(`Tower Connection Error: ${error}`, '[UDT][BLE]');
|
|
87
124
|
this.isConnected = false;
|
|
88
|
-
|
|
125
|
+
throw error;
|
|
89
126
|
}
|
|
90
127
|
}
|
|
91
128
|
async disconnect() {
|
|
92
129
|
this.stopConnectionMonitoring();
|
|
130
|
+
if (this.isConnected) {
|
|
131
|
+
this.recordIncident('user_initiated');
|
|
132
|
+
}
|
|
93
133
|
if (this.bluetoothAdapter.isConnected()) {
|
|
94
134
|
await this.bluetoothAdapter.disconnect();
|
|
95
135
|
this.logger.info("Tower disconnected", '[UDT]');
|
|
@@ -101,6 +141,8 @@ class UdtBleConnection {
|
|
|
101
141
|
* Used by UdtTowerCommands instead of direct characteristic access.
|
|
102
142
|
*/
|
|
103
143
|
async writeCommand(command) {
|
|
144
|
+
var _a;
|
|
145
|
+
(_a = this.recorder) === null || _a === void 0 ? void 0 : _a.recordCommandPayload('cmd_sent', command, { len: command.length });
|
|
104
146
|
return await this.bluetoothAdapter.writeCharacteristic(command);
|
|
105
147
|
}
|
|
106
148
|
/**
|
|
@@ -108,12 +150,16 @@ class UdtBleConnection {
|
|
|
108
150
|
* Called by the adapter's onCharacteristicValueChanged callback.
|
|
109
151
|
*/
|
|
110
152
|
onRxData(receivedData) {
|
|
153
|
+
var _a, _b;
|
|
111
154
|
this.lastSuccessfulCommand = Date.now();
|
|
112
155
|
const { cmdKey } = this.responseProcessor.getTowerCommand(receivedData[0]);
|
|
113
156
|
const isBattery = this.responseProcessor.isBatteryResponse(cmdKey);
|
|
157
|
+
if (((_a = this.recorder) === null || _a === void 0 ? void 0 : _a.enabled) && !isBattery) {
|
|
158
|
+
this.recorder.recordCommandPayload('cmd_response', receivedData, { cmdKey, len: receivedData.length });
|
|
159
|
+
}
|
|
114
160
|
const shouldLogCommand = this.logTowerResponses &&
|
|
115
161
|
this.responseProcessor.shouldLogResponse(cmdKey, this.logTowerResponseConfig) &&
|
|
116
|
-
|
|
162
|
+
!isBattery;
|
|
117
163
|
if (shouldLogCommand) {
|
|
118
164
|
this.logger.info(`${cmdKey}`, '[UDT][BLE][RCVD]');
|
|
119
165
|
}
|
|
@@ -127,17 +173,19 @@ class UdtBleConnection {
|
|
|
127
173
|
this.lastBatteryHeartbeat = Date.now();
|
|
128
174
|
const millivolts = (0, udtHelpers_1.getMilliVoltsFromTowerResponse)(receivedData);
|
|
129
175
|
const batteryPercentage = (0, udtHelpers_1.milliVoltsToPercentage)(millivolts);
|
|
176
|
+
(_b = this.recorder) === null || _b === void 0 ? void 0 : _b.recordBattery(millivolts, (0, udtHelpers_1.milliVoltsToPercentageNumber)(millivolts));
|
|
130
177
|
const didBatteryLevelChange = this.lastBatteryPercentage !== "" && this.lastBatteryPercentage !== batteryPercentage;
|
|
131
|
-
const
|
|
132
|
-
const
|
|
178
|
+
const batteryLogFrequencyPassed = ((Date.now() - this.lastBatteryLog) >= this.batteryLogFrequency);
|
|
179
|
+
const shouldLog = this.batteryLogEnabled && (this.batteryLogOnChangeOnly ?
|
|
133
180
|
(didBatteryLevelChange || this.lastBatteryPercentage === "") :
|
|
134
|
-
|
|
135
|
-
if (
|
|
181
|
+
batteryLogFrequencyPassed);
|
|
182
|
+
if (shouldLog) {
|
|
136
183
|
this.logger.info(`${this.responseProcessor.commandToString(receivedData).join(' ')}`, '[UDT][BLE]');
|
|
137
|
-
this.
|
|
184
|
+
this.lastBatteryLog = Date.now();
|
|
138
185
|
this.lastBatteryPercentage = batteryPercentage;
|
|
139
|
-
this.callbacks.onBatteryLevelNotify(millivolts);
|
|
140
186
|
}
|
|
187
|
+
// Always notify so internal state and UI stay current
|
|
188
|
+
this.callbacks.onBatteryLevelNotify(millivolts);
|
|
141
189
|
}
|
|
142
190
|
else {
|
|
143
191
|
// For non-battery responses, notify the command queue
|
|
@@ -148,20 +196,24 @@ class UdtBleConnection {
|
|
|
148
196
|
}
|
|
149
197
|
}
|
|
150
198
|
handleTowerStateResponse(receivedData) {
|
|
199
|
+
var _a, _b, _c;
|
|
151
200
|
const dataSkullDropCount = receivedData[udtConstants_1.SKULL_DROP_COUNT_POS];
|
|
152
201
|
const state = (0, udtTowerState_1.rtdt_unpack_state)(receivedData);
|
|
153
202
|
this.logger.debug(`Tower State: ${JSON.stringify(state)} `, '[UDT][BLE]');
|
|
203
|
+
(_a = this.recorder) === null || _a === void 0 ? void 0 : _a.recordEvent('tower_state_response');
|
|
154
204
|
if (this.performingCalibration) {
|
|
155
205
|
this.performingCalibration = false;
|
|
156
206
|
this.performingLongCommand = false;
|
|
157
207
|
this.lastBatteryHeartbeat = Date.now();
|
|
158
208
|
this.callbacks.onCalibrationComplete();
|
|
159
209
|
this.logger.info('Tower calibration complete', '[UDT]');
|
|
210
|
+
(_b = this.recorder) === null || _b === void 0 ? void 0 : _b.recordEvent('calibration_complete');
|
|
160
211
|
}
|
|
161
212
|
if (dataSkullDropCount !== this.towerSkullDropCount) {
|
|
162
213
|
if (dataSkullDropCount) {
|
|
163
214
|
this.callbacks.onSkullDrop(dataSkullDropCount);
|
|
164
215
|
this.logger.info(`Skull drop detected: app:${this.towerSkullDropCount < 0 ? 'empty' : this.towerSkullDropCount} tower:${dataSkullDropCount}`, '[UDT]');
|
|
216
|
+
(_c = this.recorder) === null || _c === void 0 ? void 0 : _c.recordEvent('skull_drop', { count: dataSkullDropCount });
|
|
165
217
|
}
|
|
166
218
|
else {
|
|
167
219
|
this.logger.info(`Skull count reset to ${dataSkullDropCount}`, '[UDT]');
|
|
@@ -189,11 +241,15 @@ class UdtBleConnection {
|
|
|
189
241
|
this.logger.info('Bluetooth availability changed', '[UDT][BLE]');
|
|
190
242
|
if (!available && this.isConnected) {
|
|
191
243
|
this.logger.warn('Bluetooth became unavailable - handling disconnection', '[UDT][BLE]');
|
|
244
|
+
this.recordIncident('bt_unavailable');
|
|
192
245
|
this.handleDisconnection();
|
|
193
246
|
}
|
|
194
247
|
}
|
|
195
248
|
onTowerDeviceDisconnected() {
|
|
196
249
|
this.logger.warn('Tower device disconnected unexpectedly', '[UDT][BLE]');
|
|
250
|
+
if (this.isConnected) {
|
|
251
|
+
this.recordIncident('adapter_event');
|
|
252
|
+
}
|
|
197
253
|
this.handleDisconnection();
|
|
198
254
|
}
|
|
199
255
|
handleDisconnection() {
|
|
@@ -222,11 +278,13 @@ class UdtBleConnection {
|
|
|
222
278
|
}
|
|
223
279
|
}
|
|
224
280
|
checkConnectionHealth() {
|
|
281
|
+
var _a;
|
|
225
282
|
if (!this.isConnected) {
|
|
226
283
|
return;
|
|
227
284
|
}
|
|
228
285
|
if (!this.bluetoothAdapter.isGattConnected()) {
|
|
229
286
|
this.logger.warn('GATT connection lost detected during health check', '[UDT][BLE]');
|
|
287
|
+
this.recordIncident('gatt_health_check');
|
|
230
288
|
this.handleDisconnection();
|
|
231
289
|
return;
|
|
232
290
|
}
|
|
@@ -246,6 +304,13 @@ class UdtBleConnection {
|
|
|
246
304
|
// Check if GATT is still connected via the adapter
|
|
247
305
|
if (this.bluetoothAdapter.isGattConnected()) {
|
|
248
306
|
this.logger.info('GATT connection still available - heartbeat timeout may be temporary', '[UDT][BLE]');
|
|
307
|
+
// Near-miss: the heartbeat went late but the GATT is still up. This is a
|
|
308
|
+
// strong signal worth recording for diagnostics — repeated near-misses
|
|
309
|
+
// before a real drop are the smoking gun.
|
|
310
|
+
(_a = this.recorder) === null || _a === void 0 ? void 0 : _a.recordEvent('heartbeat_late', {
|
|
311
|
+
sinceMs: timeSinceLastBatteryHeartbeat,
|
|
312
|
+
threshold: timeoutThreshold,
|
|
313
|
+
});
|
|
249
314
|
// Reset the last battery heartbeat to current time to give it another chance
|
|
250
315
|
this.lastBatteryHeartbeat = Date.now();
|
|
251
316
|
this.logger.info('Reset battery heartbeat timer - will monitor for another timeout period', '[UDT][BLE]');
|
|
@@ -253,6 +318,7 @@ class UdtBleConnection {
|
|
|
253
318
|
}
|
|
254
319
|
}
|
|
255
320
|
this.logger.warn('Tower possibly disconnected due to battery depletion or power loss', '[UDT][BLE]');
|
|
321
|
+
this.recordIncident('heartbeat_timeout');
|
|
256
322
|
this.handleDisconnection();
|
|
257
323
|
return;
|
|
258
324
|
}
|
|
@@ -260,6 +326,7 @@ class UdtBleConnection {
|
|
|
260
326
|
const timeSinceLastResponse = Date.now() - this.lastSuccessfulCommand;
|
|
261
327
|
if (timeSinceLastResponse > this.connectionTimeoutThreshold) {
|
|
262
328
|
this.logger.warn('General connection timeout detected - no responses received', '[UDT][BLE]');
|
|
329
|
+
this.recordIncident('response_timeout');
|
|
263
330
|
this.handleDisconnection();
|
|
264
331
|
}
|
|
265
332
|
}
|