import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:dio/dio.dart'; import 'package:package_info_plus/package_info_plus.dart'; import '../../../../push/push_registration_store.dart'; import '../../../../push/push_registration_type.dart'; import '../../errors/marianumconnect_error.dart'; import '../../marianumconnect_api.dart'; import '../../marianumconnect_endpoint.dart'; import 'telemetry_device_id.dart'; /// Sends a telemetry heartbeat to MarianumConnect (`POST me/telemetry`) — one /// upsert per app start carrying the stable install id, platform, app version /// and device info. Bearer-authenticated via the shared dio interceptor. /// Replaces the legacy mhsl.eu `server/userIndex/update` call. class TelemetryHeartbeat { final Dio _dio; TelemetryHeartbeat({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio(); /// Fire-and-forget: schedules a heartbeat and swallows any error, so a failed /// send never disrupts app start. Used from the app shell's initState. static void report() { unawaited(TelemetryHeartbeat().send().catchError((Object _) {})); } Future send() async { try { final info = DeviceInfoPlugin(); final package = await PackageInfo.fromPlatform(); final deviceIdentifier = await TelemetryDeviceId.resolve(); final pushDeviceIdentifier = await const PushRegistrationStore() .deviceIdentifier(PushRegistrationType.general); var platform = 'unknown'; String? deviceModel; String? osVersion; var raw = {}; if (Platform.isAndroid) { platform = 'android'; final androidInfo = await info.androidInfo; deviceModel = androidInfo.model; osVersion = androidInfo.version.release; raw = androidInfo.data; } else if (Platform.isIOS) { platform = 'ios'; final appleInfo = await info.iosInfo; deviceModel = appleInfo.utsname.machine; osVersion = appleInfo.systemVersion; raw = appleInfo.data; } await _dio.post( MarianumConnectEndpoint.resolve('me/telemetry'), data: { 'deviceIdentifier': deviceIdentifier, 'pushDeviceIdentifier': ?pushDeviceIdentifier, 'platform': platform, 'appVersion': package.version, 'appBuild': int.tryParse(package.buildNumber), 'deviceModel': deviceModel, 'osVersion': osVersion, 'deviceInfo': jsonEncode(raw), }, ); } on DioException catch (e) { throw mapMarianumConnectError(e); } } }