Skip to Content
配置企业特色

企业特色

Tracelet 配备了多种专为企业用例设计的高安全性功能,例如军事跟踪、符合 HIPAA 的患者监控和加密验证的物流。


1.数据加密(SQLCipher)

当 Tracelet 在后台记录位置时,它会在将其同步到服务器之前将其临时存储在内部 SQLite 数据库中。如果设备被盗,物理访问可能会让攻击者读取这些历史路线。

Tracelet 通过使用 SQLCipher 提供静态数据库加密解决了这个问题。

数据加密的工作原理

  1. 当您启用 encryptDatabase 标志时,底层 Rust SQLite 数据库会立即通过 SQLCipher 使用 AES-256 进行加密。
  2. 默认情况下,Tracelet 自动生成安全的 256 位密钥并将其安全地存储在平台的本机安全存储(Android Keystore / iOS Keychain)中。您不必手动管理密钥!
  3. 如果没有密钥,写入磁盘的所有数据将完全无法读取。
  4. 当启用该标志时,现有的未加密数据库将自动迁移为加密数据库。

执行

要使用平台管理的安全密钥启用加密(推荐):

final config = Config.balanced( security: tl.SecurityConfig( encryptDatabase: true, // This MUST be true to enable encryption ), );

自定义密钥管理(高级)

如果您的应用程序更喜欢管理自己的密钥材料(例如,使用 flutter_secure_storage),您可以提供自定义 encryptionKey。请注意,encryptDatabase 必须仍然为 true

// Generate a secure random key final customKey = await tl.Tracelet.generateEncryptionKey(); await secureStorage.write(key: 'my_db_key', value: customKey); // Pass it to Tracelet final config = Config.balanced( security: tl.SecurityConfig( encryptDatabase: true, encryptionKey: await secureStorage.read(key: 'my_db_key'), ), );

2. 审计跟踪管理和验证

在敏感的物流或执法中,您必须能够以数学方式证明位置记录在事后未被篡改、欺骗或更改。 Tracelet 提供审计跟踪功能来创建加密监管链。

审计追踪管理如何运作

AuditConfig.enabled 设置为 true 时,Tracelet 不仅仅保存纬度和经度。它为每个位置创建一个“类似区块链”的记录。底层 Rust 引擎确保此过程是原子的且万无一失:

  1. 创世区块: 当引擎首次在新设备上启动时,它会计算创世哈希:SHA-256("tracelet:genesis:{device_id}")
  2. 规范字符串生成: 对于每个位置,Tracelet 会结合先前的哈希值和新位置的精确数据生成严格的、确定性的字符串格式。
  3. 哈希: 此规范字符串经过哈希处理(默认使用 SHA-256),为当前位置生成 hash
  4. 链: 该哈希值成为下一个位置的 previous_hash,从而创建一条不间断的链。如果攻击者修改了数据库中过去位置的单个坐标,该位置的哈希值就会发生变化,从而破坏整个后续哈希值链。

配置

final config = Config.highAccuracy( audit: tl.AuditConfig( enabled: true, hashAlgorithm: tl.HashAlgorithm.sha256, ), );

当 Tracelet 将这些位置同步到后端时,每个位置的 JSON 负载将直接包含审核字段。

{ "device": "tracelet-example", "locationCount": 1, "locations": [ { "uuid": "loc-1234-abcd", "timestamp": "2024-01-01T00:00:00Z", "is_moving": true, "coords": { "latitude": 37.774900, "longitude": -122.419400, "accuracy": 10.0, "speed": 15.5, "heading": 90.0, "altitude": 100.0 }, "audit_hash": "a1b2c3d4e5f6...", "audit_previous_hash": "f6e5d4c3b2a1...", "audit_chain_index": 42 } ] }

服务端验证(如何验证代码)

要验证服务器上数据的完整性,您必须重新创建 Tracelet Rust 核心使用的确切规范字符串,并将生成的哈希值与有效负载中的 audit_hash 字段进行比较。

1. 构建规范字符串

字符串的格式必须与此完全相同,并用管道 | 字符分隔: 未翻译

重要的格式规则(基于 Tracelet 的 Rust Core):

  • latitudelongitude:格式精确到小数点后 6 位(例如 37.774900)。
  • accuracyspeedheadingaltitude:格式精确到小数点后 2 位(例如 10.00)。
  • is_moving:格式为 1 (true) 或 0 (false)。

规范字符串示例:

f6e5d4c3b2a1...|TRACELET_AUDIT|42|loc-1234-abcd|37.774900|-122.419400|2024-01-01T00:00:00Z|10.00|15.50|90.00|100.00|1

2. 散列和比较

通过标准 SHA-256 哈希函数传递构造的规范字符串,并将其转换为小写十六进制字符串。

  • 如果您计算的哈希匹配 audit_hash 字段:该位置在数学上被证明是未被篡改的。
  • 如果不匹配:位置数据已被更改。您应该立即标记此记录并调查该设备。

3. 定位精度曲线(HF/LF)

查看 Tracelet 示例应用程序时,您会注意到 LF AccuracyHF Accuracy 按钮。这些直接映射到 Tracelet 的预构建配置文件。

  • LF(低频/低精度): 这映射到 Config.lowPower() 配置文件。它限制引擎仅使用蜂窝塔和 Wi-Fi 三角测量(无 GPS)。它具有很高的电池效率,但提供了更广泛的精度半径。
  • HF(高频/高精度): 这映射到 Config.highAccuracy() 配置文件。它强制启用物理 GPS 芯片,以更高的电池消耗为代价提供 1-5 米的精度。

Tracelet 包含一个内置的 CarbonEstimator 实用程序。它将活动识别(检测用户是否在开车、步行或骑自行车)与精确的地理距离相融合,以计算一次旅行的估计二氧化碳排放量。这对于可持续发展报告、碳抵消计划或 ESG(环境、社会和治理)合规性至关重要。

它是如何运作的

  1. 您实例化一个 CarbonEstimator
  2. 当用户开始移动(isMoving == true)时,您调用 startTrip()
  3. 将实时活动变化(例如,从步行切换到驾驶)和位置输入估计器。
  4. 当用户停止移动(isMoving == false)时,调用 endTrip() 生成 TripCarbonSummary

实施例

final carbonEstimator = tl.CarbonEstimator(); // 1. Listen for motion changes to start and end trips Tracelet.onMotionChange((loc) { if (loc.isMoving) { carbonEstimator.startTrip(); } else { final summary = carbonEstimator.endTrip(); if (summary != null) { print('Trip ended: \${summary.totalCarbonGrams}g CO2'); print('Total Distance: \${summary.totalDistanceMeters}m'); print('Dominant Mode: \${summary.dominantMode}'); // e.g. "driving" } } }); // 2. Feed Activity Recognition data to detect the transport mode Tracelet.onActivityChange((evt) { // Activity names map to emissions factors internally (e.g., driving vs walking) carbonEstimator.setActivity(evt.activity.name); }); // 3. Feed location coordinates to accumulate distance accurately Tracelet.onLocation((loc) { carbonEstimator.onLocationReceived( loc.coords.latitude, loc.coords.longitude, ); });

然后,生成的 TripCarbonSummary 可以同步到您的服务器或直接显示给用户,以鼓励环保的运输选择。


5. 远程配置

3.6.2 起在 iOS 和 Android 上本地获取并应用。早期版本接受 remoteConfigUrl 但从未获取它 - 本机端默默地回退到本地配置。

对于车队和大型部署,您经常需要更改跟踪行为 - 准确性、同步节奏、地理围栏半径、电池预算 - 无需发布应用程序更新。 Tracelet 的 远程配置 允许 SDK 从您自己的 HTTPS 端点提取配置文档,并在运行时将其应用到本地配置之上。

远程配置的工作原理

  1. AppConfig 中设置 remoteConfigUrl(和可选标头)。
  2. ready() 上,SDK 首先从设备缓存中应用上次成功获取的配置 — 因此,在任何网络调用之前,立即重新启动最新发布的设置并离线,并且不会阻止 ready()
  3. 然后,它从后台中的端点获取新副本,并通过与 setConfig() 相同的运行时路径应用它 — 仅当跟踪相关密钥实际更改时才重新启动活动跟踪管道。
  4. 它通过以 remoteConfigRefreshInterval 节奏(以分钟为单位)重新获取来保持配置最新。

仅接受 HTTPS URL — http:// URL 会被拒绝并记录,因为配置控制跟踪行为并且在传输过程中不得被篡改。

端点合约

您的端点使用形状像 Tracelet 配置映射的 JSON 对象来响应 GET — 要么是 扁平,要么是 Config.toMap() 生成的 嵌套 { "geo": {…}, "app": {…}, "http": {…} } 形式。只有您包含的键才会被覆盖;所有其他设置都保留其本地值。

{ "geo": { "distanceFilter": 25.0, "desiredAccuracy": 0 }, "app": { "heartbeatInterval": 120 }, "http": { "autoSync": true } }

配置

final config = Config.balanced().copyWith( app: tl.AppConfig( remoteConfigUrl: 'https://config.mycompany.com/tracelet/fleet-a.json', remoteConfigHeaders: {'Authorization': 'Bearer $token'}, remoteConfigTimeout: 15000, // milliseconds remoteConfigRefreshInterval: 60, // minutes ), );
领域类型默认描述
不翻译迟到不翻译晚点不翻译2晚返回 JSON 配置映射的 HTTPS 端点。 null 禁用远程配置。
不翻译迟到不翻译晚点不翻译2晚随 fetch 一起发送的标头(例如身份验证令牌)。
不翻译迟到不翻译晚点不翻译2晚获取超时(以毫秒为单位)。
不翻译迟到不翻译晚点不翻译2晚后台刷新间隔时间为 15 分钟(默认为 15 分钟)。 0 获取一次并且永不重复。

应用的远程值将合并到设备的持久配置中,并且远程覆盖优于本地值。仅发布您想要获取要采用的 URL 的每个设备的值 - 通过将每个构建指向不同的 URL,在每个队列或每个队列的范围内发布值。

从 Dart 观察应用的远程配置

远程配置在本机端获取并应用。自 3.6.10 起,每次应用远程覆盖时(在 ready() 恢复的缓存副本和**每次后台刷新),SDK 都会将其显示回 Dart:

  • Tracelet.activeConfig(因此 tracelet_doctor 和 Dart 端电池预算引擎)现在反映获取的值,而不是仅反映您在本地设置的最后一个配置。
  • 订阅以在服务器驱动的变更发生时做出反应:
// Callback — fires after a remote override is applied. // Tracelet.activeConfig already reflects the new values when this fires. Tracelet.onRemoteConfig((Config config) { print('Remote battery budget: ${config.geo.batteryBudgetPerHour}%/hr'); }); // …or listen to the broadcast stream directly. final sub = Tracelet.remoteConfigStream.listen((config) { // react to the merged, now-active config });

在 3.6.10 之前,远程值应用于本机跟踪,但镜像到 Tracelet.activeConfig,因此即使跟踪已使用远程值,诊断仍然可以显示最后一个本地设置的值。