diff --git a/.nvim.lua b/.nvim.lua new file mode 100644 index 0000000..7c5744d --- /dev/null +++ b/.nvim.lua @@ -0,0 +1,19 @@ +require("flutter-tools").setup_project({ + { + name = "Development", + flavor = "development", + target = "lib/main_development.dart", + }, + { + name = "Development Simulator", + flavor = "development", + target = "lib/main_development.dart", + device = "658DAB68-40FB-4DEA-8C0B-C92451326570", + }, + { + name = "Production", + flavor = "production", + target = "lib/main_production.dart", + device = "658DAB68-40FB-4DEA-8C0B-C92451326570", + }, +}) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7fd8db3..af6b17e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -51,7 +51,8 @@ android { applicationId "com.example.verygoodcore.xiao_pet_tracker" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + // ObjectBox Sync requires at least SDK 21 (Android 5.0) + minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2e95815..07a763b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -32,5 +32,7 @@ + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 37d8c86..bf87ae7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2,20 +2,27 @@ PODS: - Flutter (1.0.0) - flutter_blue_plus (0.0.1): - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS DEPENDENCIES: - Flutter (from `Flutter`) - flutter_blue_plus (from `.symlinks/plugins/flutter_blue_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) EXTERNAL SOURCES: Flutter: :path: Flutter flutter_blue_plus: :path: ".symlinks/plugins/flutter_blue_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_blue_plus: 4837da7d00cf5d441fdd6635b3a57f936778ea96 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 diff --git a/lib/app/app.dart b/lib/app/app.dart index f23ab3c..ae71c5c 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -1 +1,20 @@ -export 'view/app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:xiao_pet_tracker/app/view/app.dart'; +import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart'; + +class App extends StatelessWidget { + const App({super.key}); + + @override + Widget build(BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (BuildContext context) => XiaoConnectorCubit()..init(), + ), + ], + child: const AppView(), + ); + } +} diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 1001d7c..f1473aa 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -2,19 +2,22 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus_windows/flutter_blue_plus_windows.dart'; -import 'package:shadcn_ui/shadcn_ui.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:forui/forui.dart'; +import 'package:xiao_pet_tracker/app_router/app_router.dart'; +import 'package:xiao_pet_tracker/bootstrap.dart'; import 'package:xiao_pet_tracker/home/view/home_page.dart'; import 'package:xiao_pet_tracker/l10n/l10n.dart'; import 'package:xiao_pet_tracker/screens/bluetooth_off_screen.dart'; -class App extends StatefulWidget { - const App({super.key}); +class AppView extends StatefulWidget { + const AppView({super.key}); @override - State createState() => _AppState(); + State createState() => _AppState(); } -class _AppState extends State { +class _AppState extends State { BluetoothAdapterState _adapterState = BluetoothAdapterState.unknown; late StreamSubscription _adapterStateStateSubscription; @@ -45,11 +48,25 @@ class _AppState extends State { adapterState: _adapterState, ); - return ShadApp.material( - localizationsDelegates: AppLocalizations.localizationsDelegates, + return MaterialApp.router( + title: 'Xiao Pet Tracker', + localizationsDelegates: const [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + // localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, - navigatorObservers: [BluetoothAdapterStateObserver()], - home: screen, + routerConfig: getIt().config(), + theme: ThemeData(), + darkTheme: ThemeData.dark(), + builder: (context, child) => FTheme( + data: MediaQuery.of(context).platformBrightness == Brightness.light + ? FThemes.zinc.light + : FThemes.zinc.dark, + child: child!, + ), ); } } @@ -63,13 +80,14 @@ class BluetoothAdapterStateObserver extends NavigatorObserver { super.didPush(route, previousRoute); if (route.settings.name == '/DeviceScreen') { // Start listening to Bluetooth state changes when a new route is pushed - _adapterStateSubscription ??= - FlutterBluePlus.adapterState.listen((state) { - if (state != BluetoothAdapterState.on) { - // Pop the current route if Bluetooth is off - navigator?.pop(); - } - }); + _adapterStateSubscription ??= FlutterBluePlus.adapterState.listen( + (state) { + if (state != BluetoothAdapterState.on) { + // Pop the current route if Bluetooth is off + navigator?.pop(); + } + }, + ); } } diff --git a/lib/app_router/app_router.dart b/lib/app_router/app_router.dart new file mode 100644 index 0000000..55659fc --- /dev/null +++ b/lib/app_router/app_router.dart @@ -0,0 +1,88 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:forui/forui.dart'; +import 'package:xiao_pet_tracker/app_router/app_router.gr.dart'; + +@AutoRouterConfig() +class AppRouter extends RootStackRouter { + @override + RouteType get defaultRouteType => const RouteType.material(); + + @override + List get routes => [ + AutoRoute( + page: MainRoute.page, + path: '/', + children: [ + AutoRoute( + page: HomeRoute.page, + ), + AutoRoute( + page: XiaoConnectorRoute.page, + ), + AutoRoute( + page: SettingsRoute.page, + ), + ], + ) + ]; +} + +@RoutePage() +class MainPage extends StatelessWidget { + const MainPage({super.key}); + + @override + Widget build(BuildContext context) { + return AutoTabsScaffold( + // transitionBuilder: (context, child, animation) => AnimatedBuilder( + // animation: animation, + // child: child, + // // builder: (BuildContext context, Widget? child) { + // // const begin = Offset(0.0, 0.1); + // // const end = Offset.zero; + // // final tween = Tween(begin: begin, end: end); + // // final offsetAnimation = animation.drive(tween); + // // return SlideTransition( + // // position: offsetAnimation, + // // child: Transform.scale( + // // alignment: Alignment.bottomCenter, + // // scale: animation.value, + // // child: ClipPath( + // // clipper: CircularRevealClipper( + // // fraction: animation.value, + // // centerAlignment: Alignment.bottomCenter, + // // // centerOffset: centerOffset, + // // // minRadius: minRadius, + // // // maxRadius: maxRadius, + // // ), + // // child: child, + // // ), + // // ), + // // ); + // // }, + // ), + animationDuration: const Duration(milliseconds: 650), + routes: const [ + XiaoConnectorRoute(), + SettingsRoute(), + ], + bottomNavigationBuilder: (context, tabsRouter) { + return FBottomNavigationBar( + index: tabsRouter.activeIndex, + onChange: tabsRouter.setActiveIndex, + children: [ + FBottomNavigationBarItem( + label: const Text('Home'), + icon: FIcon(FAssets.icons.house), + ), + FBottomNavigationBarItem( + label: const Text('Settings'), + icon: FIcon(FAssets.icons.settings), + ), + ], + ); + }, + ); + } +} diff --git a/lib/app_router/app_router.gr.dart b/lib/app_router/app_router.gr.dart new file mode 100644 index 0000000..1423936 --- /dev/null +++ b/lib/app_router/app_router.gr.dart @@ -0,0 +1,92 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// AutoRouterGenerator +// ************************************************************************** + +// ignore_for_file: type=lint +// coverage:ignore-file + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:auto_route/auto_route.dart' as _i5; +import 'package:xiao_pet_tracker/app_router/app_router.dart' as _i2; +import 'package:xiao_pet_tracker/home/view/home_page.dart' as _i1; +import 'package:xiao_pet_tracker/settings/view/settings_page.dart' as _i3; +import 'package:xiao_pet_tracker/xiao_connector/view/xiao_connector_page.dart' + as _i4; + +/// generated route for +/// [_i1.HomePage] +class HomeRoute extends _i5.PageRouteInfo { + const HomeRoute({List<_i5.PageRouteInfo>? children}) + : super( + HomeRoute.name, + initialChildren: children, + ); + + static const String name = 'HomeRoute'; + + static _i5.PageInfo page = _i5.PageInfo( + name, + builder: (data) { + return const _i1.HomePage(); + }, + ); +} + +/// generated route for +/// [_i2.MainPage] +class MainRoute extends _i5.PageRouteInfo { + const MainRoute({List<_i5.PageRouteInfo>? children}) + : super( + MainRoute.name, + initialChildren: children, + ); + + static const String name = 'MainRoute'; + + static _i5.PageInfo page = _i5.PageInfo( + name, + builder: (data) { + return const _i2.MainPage(); + }, + ); +} + +/// generated route for +/// [_i3.SettingsPage] +class SettingsRoute extends _i5.PageRouteInfo { + const SettingsRoute({List<_i5.PageRouteInfo>? children}) + : super( + SettingsRoute.name, + initialChildren: children, + ); + + static const String name = 'SettingsRoute'; + + static _i5.PageInfo page = _i5.PageInfo( + name, + builder: (data) { + return const _i3.SettingsPage(); + }, + ); +} + +/// generated route for +/// [_i4.XiaoConnectorPage] +class XiaoConnectorRoute extends _i5.PageRouteInfo { + const XiaoConnectorRoute({List<_i5.PageRouteInfo>? children}) + : super( + XiaoConnectorRoute.name, + initialChildren: children, + ); + + static const String name = 'XiaoConnectorRoute'; + + static _i5.PageInfo page = _i5.PageInfo( + name, + builder: (data) { + return const _i4.XiaoConnectorPage(); + }, + ); +} diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index c173883..5591fc2 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -3,6 +3,11 @@ import 'dart:developer'; import 'package:bloc/bloc.dart'; import 'package:flutter/widgets.dart'; +import 'package:get_it/get_it.dart'; +import 'package:xiao_pet_tracker/app_router/app_router.dart'; +import 'package:xiao_pet_tracker/objectbox.dart'; + +final getIt = GetIt.instance; class AppBlocObserver extends BlocObserver { const AppBlocObserver(); @@ -31,5 +36,9 @@ Future bootstrap(FutureOr Function() builder) async { WidgetsFlutterBinding.ensureInitialized(); + final AppRouter appRouter = getIt.registerSingleton(AppRouter()); + + final ObjectBox objectBox = getIt.registerSingleton(await ObjectBox.create()); + runApp(await builder()); } diff --git a/lib/home/view/home_page.dart b/lib/home/view/home_page.dart index c63226f..2a95b95 100644 --- a/lib/home/view/home_page.dart +++ b/lib/home/view/home_page.dart @@ -1,10 +1,11 @@ import 'dart:async'; +import 'package:auto_route/auto_route.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_blue_plus_windows/flutter_blue_plus_windows.dart'; -import 'package:shadcn_ui/shadcn_ui.dart'; +@RoutePage() class HomePage extends StatelessWidget { const HomePage({super.key}); @@ -199,8 +200,8 @@ class _HomeScreenState extends State { // }, // ), if (_connected) Text('Connected!'), - ShadButton( - enabled: !_isScanning, + ElevatedButton( + // enabled: !_isScanning, onPressed: () async { // await Future.delayed(const Duration(seconds: 2)); // onScanPressed(); @@ -210,19 +211,19 @@ class _HomeScreenState extends State { onConnectPressed(); } }, - icon: _isScanning - ? const SizedBox.square( - dimension: 16, - child: CircularProgressIndicator(), - ) - : null, + // icon: _isScanning + // ? const SizedBox.square( + // dimension: 16, + // child: CircularProgressIndicator(), + // ) + // : null, child: _isScanning ? const Text('Please wait') : _connected ? const Text('Disconnect') : const Text('Connect'), ), - ShadButton( + ElevatedButton( onPressed: () async { print('Toggle LED'); print(_services); @@ -250,7 +251,7 @@ class _HomeScreenState extends State { }, child: Text('Toggle LED'), ), - ShadButton( + ElevatedButton( onPressed: () async { print('Toggle LED'); print(_services); @@ -258,21 +259,32 @@ class _HomeScreenState extends State { .where( (s) => s.serviceUuid == - Guid('a0b40003-926d-4d61-98df-8c5c62ee53b3'), + Guid('4c534d36-4453-3354-5253-657276696365'), ) .first .characteristics - .where((c) => - c.characteristicUuid == - Guid('a0b40004-926d-4d61-98df-8c5c62ee53b3')) + .where( + (c) => + c.characteristicUuid == + Guid('61636365-6c65-7261-7469-6f6e44617461'), + ) .first; + final senseSubscription = + ledService.onValueReceived.listen((value) { + print("UPDATE: ${String.fromCharCodes(value)}"); + }); + + device!.cancelWhenDisconnected(senseSubscription); + + await ledService.setNotifyValue(true); + // await ledService.write([1, 2, 3]); // await Future.delayed(Duration(seconds: 2)); - List ledServiceValue = await ledService.read(); - print("READ Sense SERVICE: $ledServiceValue"); - print( - "READ Sense SERVICE: ${String.fromCharCodes(ledServiceValue)}"); + // List ledServiceValue = await ledService.read(); + // print("READ Sense SERVICE: $ledServiceValue"); + // print( + // "READ Sense SERVICE: ${String.fromCharCodes(ledServiceValue)}"); }, child: Text('Read Sense'), ) diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json new file mode 100644 index 0000000..f43b2c5 --- /dev/null +++ b/lib/objectbox-model.json @@ -0,0 +1,84 @@ +{ + "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", + "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", + "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", + "entities": [ + { + "id": "2:23371849066855038", + "lastPropertyId": "10:4052938287274443905", + "name": "CapturePoint", + "properties": [ + { + "id": "1:9209282349575641428", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:8441629944202144182", + "name": "rotationX", + "type": 9 + }, + { + "id": "3:3805193742978753321", + "name": "rotationY", + "type": 9 + }, + { + "id": "4:7632102454091387966", + "name": "rotationZ", + "type": 9 + }, + { + "id": "5:1175247580397683930", + "name": "accelerationX", + "type": 9 + }, + { + "id": "6:133552602314920473", + "name": "accelerationY", + "type": 9 + }, + { + "id": "7:7272664476171529007", + "name": "accelerationZ", + "type": 9 + }, + { + "id": "9:5697556233714735057", + "name": "type", + "type": 9 + }, + { + "id": "10:4052938287274443905", + "name": "millisecondsSinceEpoch", + "type": 6 + } + ], + "relations": [] + } + ], + "lastEntityId": "2:23371849066855038", + "lastIndexId": "0:0", + "lastRelationId": "0:0", + "lastSequenceId": "0:0", + "modelVersion": 5, + "modelVersionParserMinimum": 5, + "retiredEntityUids": [ + 6206931177901930822 + ], + "retiredIndexUids": [], + "retiredPropertyUids": [ + 696937191447548336, + 7375635633551465262, + 7972299062087181706, + 5044874535120106939, + 6473009355337784814, + 8948425706967252950, + 5134040367670771080, + 4879888592430478383, + 2890906455219707986 + ], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/lib/objectbox.dart b/lib/objectbox.dart new file mode 100644 index 0000000..219aae7 --- /dev/null +++ b/lib/objectbox.dart @@ -0,0 +1,18 @@ +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; +import 'objectbox.g.dart'; + +class ObjectBox { + late final Store store; + + /// Initialization + ObjectBox._create(this.store); + + /// Create an instance of ObjectBox to use throughout the app. + static Future create() async { + final docsDir = await getApplicationDocumentsDirectory(); + final store = + await openStore(directory: p.join(docsDir.path, 'obx-pet-tracker')); + return ObjectBox._create(store); + } +} diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart new file mode 100644 index 0000000..b0e6031 --- /dev/null +++ b/lib/objectbox.g.dart @@ -0,0 +1,242 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// This code was generated by ObjectBox. To update it run the generator again +// with `dart run build_runner build`. +// See also https://docs.objectbox.io/getting-started#generate-objectbox-code + +// ignore_for_file: camel_case_types, depend_on_referenced_packages +// coverage:ignore-file + +import 'dart:typed_data'; + +import 'package:flat_buffers/flat_buffers.dart' as fb; +import 'package:objectbox/internal.dart' + as obx_int; // generated code can access "internal" functionality +import 'package:objectbox/objectbox.dart' as obx; +import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart'; + +import 'xiao_connector/models/capture_point.dart'; + +export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file + +final _entities = [ + obx_int.ModelEntity( + id: const obx_int.IdUid(2, 23371849066855038), + name: 'CapturePoint', + lastPropertyId: const obx_int.IdUid(10, 4052938287274443905), + flags: 0, + properties: [ + obx_int.ModelProperty( + id: const obx_int.IdUid(1, 9209282349575641428), + name: 'id', + type: 6, + flags: 1), + obx_int.ModelProperty( + id: const obx_int.IdUid(2, 8441629944202144182), + name: 'rotationX', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(3, 3805193742978753321), + name: 'rotationY', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(4, 7632102454091387966), + name: 'rotationZ', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(5, 1175247580397683930), + name: 'accelerationX', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(6, 133552602314920473), + name: 'accelerationY', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(7, 7272664476171529007), + name: 'accelerationZ', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(9, 5697556233714735057), + name: 'type', + type: 9, + flags: 0), + obx_int.ModelProperty( + id: const obx_int.IdUid(10, 4052938287274443905), + name: 'millisecondsSinceEpoch', + type: 6, + flags: 0) + ], + relations: [], + backlinks: []) +]; + +/// Shortcut for [obx.Store.new] that passes [getObjectBoxModel] and for Flutter +/// apps by default a [directory] using `defaultStoreDirectory()` from the +/// ObjectBox Flutter library. +/// +/// Note: for desktop apps it is recommended to specify a unique [directory]. +/// +/// See [obx.Store.new] for an explanation of all parameters. +/// +/// For Flutter apps, also calls `loadObjectBoxLibraryAndroidCompat()` from +/// the ObjectBox Flutter library to fix loading the native ObjectBox library +/// on Android 6 and older. +Future openStore( + {String? directory, + int? maxDBSizeInKB, + int? maxDataSizeInKB, + int? fileMode, + int? maxReaders, + bool queriesCaseSensitiveDefault = true, + String? macosApplicationGroup}) async { + await loadObjectBoxLibraryAndroidCompat(); + return obx.Store(getObjectBoxModel(), + directory: directory ?? (await defaultStoreDirectory()).path, + maxDBSizeInKB: maxDBSizeInKB, + maxDataSizeInKB: maxDataSizeInKB, + fileMode: fileMode, + maxReaders: maxReaders, + queriesCaseSensitiveDefault: queriesCaseSensitiveDefault, + macosApplicationGroup: macosApplicationGroup); +} + +/// Returns the ObjectBox model definition for this project for use with +/// [obx.Store.new]. +obx_int.ModelDefinition getObjectBoxModel() { + final model = obx_int.ModelInfo( + entities: _entities, + lastEntityId: const obx_int.IdUid(2, 23371849066855038), + lastIndexId: const obx_int.IdUid(0, 0), + lastRelationId: const obx_int.IdUid(0, 0), + lastSequenceId: const obx_int.IdUid(0, 0), + retiredEntityUids: const [6206931177901930822], + retiredIndexUids: const [], + retiredPropertyUids: const [ + 696937191447548336, + 7375635633551465262, + 7972299062087181706, + 5044874535120106939, + 6473009355337784814, + 8948425706967252950, + 5134040367670771080, + 4879888592430478383, + 2890906455219707986 + ], + retiredRelationUids: const [], + modelVersion: 5, + modelVersionParserMinimum: 5, + version: 1); + + final bindings = { + CapturePoint: obx_int.EntityDefinition( + model: _entities[0], + toOneRelations: (CapturePoint object) => [], + toManyRelations: (CapturePoint object) => {}, + getId: (CapturePoint object) => object.id, + setId: (CapturePoint object, int id) { + object.id = id; + }, + objectToFB: (CapturePoint object, fb.Builder fbb) { + final rotationXOffset = fbb.writeString(object.rotationX); + final rotationYOffset = fbb.writeString(object.rotationY); + final rotationZOffset = fbb.writeString(object.rotationZ); + final accelerationXOffset = fbb.writeString(object.accelerationX); + final accelerationYOffset = fbb.writeString(object.accelerationY); + final accelerationZOffset = fbb.writeString(object.accelerationZ); + final typeOffset = fbb.writeString(object.type); + fbb.startTable(11); + fbb.addInt64(0, object.id); + fbb.addOffset(1, rotationXOffset); + fbb.addOffset(2, rotationYOffset); + fbb.addOffset(3, rotationZOffset); + fbb.addOffset(4, accelerationXOffset); + fbb.addOffset(5, accelerationYOffset); + fbb.addOffset(6, accelerationZOffset); + fbb.addOffset(8, typeOffset); + fbb.addInt64(9, object.millisecondsSinceEpoch); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (obx.Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + final typeParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 20, ''); + final rotationXParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 6, ''); + final rotationYParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 8, ''); + final rotationZParam = const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 10, ''); + final accelerationXParam = + const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 12, ''); + final accelerationYParam = + const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 14, ''); + final accelerationZParam = + const fb.StringReader(asciiOptimization: true) + .vTableGet(buffer, rootOffset, 16, ''); + final millisecondsSinceEpochParam = + const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 22); + final object = CapturePoint( + type: typeParam, + rotationX: rotationXParam, + rotationY: rotationYParam, + rotationZ: rotationZParam, + accelerationX: accelerationXParam, + accelerationY: accelerationYParam, + accelerationZ: accelerationZParam, + millisecondsSinceEpoch: millisecondsSinceEpochParam) + ..id = const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0); + + return object; + }) + }; + + return obx_int.ModelDefinition(model, bindings); +} + +/// [CapturePoint] entity fields to define ObjectBox queries. +class CapturePoint_ { + /// See [CapturePoint.id]. + static final id = + obx.QueryIntegerProperty(_entities[0].properties[0]); + + /// See [CapturePoint.rotationX]. + static final rotationX = + obx.QueryStringProperty(_entities[0].properties[1]); + + /// See [CapturePoint.rotationY]. + static final rotationY = + obx.QueryStringProperty(_entities[0].properties[2]); + + /// See [CapturePoint.rotationZ]. + static final rotationZ = + obx.QueryStringProperty(_entities[0].properties[3]); + + /// See [CapturePoint.accelerationX]. + static final accelerationX = + obx.QueryStringProperty(_entities[0].properties[4]); + + /// See [CapturePoint.accelerationY]. + static final accelerationY = + obx.QueryStringProperty(_entities[0].properties[5]); + + /// See [CapturePoint.accelerationZ]. + static final accelerationZ = + obx.QueryStringProperty(_entities[0].properties[6]); + + /// See [CapturePoint.type]. + static final type = + obx.QueryStringProperty(_entities[0].properties[7]); + + /// See [CapturePoint.millisecondsSinceEpoch]. + static final millisecondsSinceEpoch = + obx.QueryIntegerProperty(_entities[0].properties[8]); +} diff --git a/lib/settings/settings.dart b/lib/settings/settings.dart new file mode 100644 index 0000000..00ffcf9 --- /dev/null +++ b/lib/settings/settings.dart @@ -0,0 +1 @@ +export 'view/view.dart'; diff --git a/lib/settings/view/settings_page.dart b/lib/settings/view/settings_page.dart new file mode 100644 index 0000000..af122cd --- /dev/null +++ b/lib/settings/view/settings_page.dart @@ -0,0 +1,23 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class SettingsPage extends StatelessWidget { + const SettingsPage({super.key}); + + @override + Widget build(BuildContext context) { + return const SettingsView(); + } +} + +class SettingsView extends StatelessWidget { + const SettingsView({super.key}); + + @override + Widget build(BuildContext context) { + return const Center( + child: Text('Settings'), + ); + } +} diff --git a/lib/settings/view/view.dart b/lib/settings/view/view.dart new file mode 100644 index 0000000..10ba3ac --- /dev/null +++ b/lib/settings/view/view.dart @@ -0,0 +1 @@ +export 'settings_page.dart'; diff --git a/lib/xiao_connector/constants/constants.dart b/lib/xiao_connector/constants/constants.dart new file mode 100644 index 0000000..565fa08 --- /dev/null +++ b/lib/xiao_connector/constants/constants.dart @@ -0,0 +1,6 @@ +const uuidLSM6DS3TRService = '4c534d36-4453-3354-5253-657276696365'; +const uuidAccelerationData = '61636365-6c65-7261-7469-6f6e44617461'; + + + //tempSenseService = [16]byte{0x74, 0x65, 0x6D, 0x70, 0x53, 0x65, 0x6E, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65} + //temperatureSense = [16]byte{0x74, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x6E, 0x73, 0x65} diff --git a/lib/xiao_connector/cubit/xiao_connector_cubit.dart b/lib/xiao_connector/cubit/xiao_connector_cubit.dart new file mode 100644 index 0000000..2128bed --- /dev/null +++ b/lib/xiao_connector/cubit/xiao_connector_cubit.dart @@ -0,0 +1,194 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_blue_plus_windows/flutter_blue_plus_windows.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:xiao_pet_tracker/bootstrap.dart'; +import 'package:xiao_pet_tracker/objectbox.dart'; +import 'package:xiao_pet_tracker/xiao_connector/models/capture_point.dart'; + +part 'xiao_connector_state.dart'; + +class XiaoConnectorCubit extends Cubit { + XiaoConnectorCubit() : super(const XiaoConnectorState()); + + late BluetoothDevice device; + List _systemDevices = []; + List _services = []; + + late StreamSubscription> dataCapturingSubscription; + + final ObjectBox _objectBox = getIt(); + late final Box _capturePointsBox; + + bool gotRotationX = false; + bool gotRotationY = false; + bool gotRotationZ = false; + bool gotAcceleration = false; + + late String _rotX; + late String _rotY; + late String _rotZ; + late String _accel; + + Future init() async { + _capturePointsBox = _objectBox.store.box(); + } + + Future connect() async { + emit(state.copyWith(status: XiaoConnectorStatus.loading)); + try { + _systemDevices = await FlutterBluePlus.systemDevices([]); + } catch (e) { + emit(state.copyWith(status: XiaoConnectorStatus.failure)); + throw Exception('System Devices Error: $e'); + } + + try { + // scan for devices for 15 seconds + await FlutterBluePlus.startScan(timeout: const Duration(seconds: 15)); + } catch (e) { + emit(state.copyWith(status: XiaoConnectorStatus.failure)); + throw Exception('Start Scan Error: $e'); + } + + FlutterBluePlus.scanResults.listen( + (results) async { + for (final r in results) { + if (kDebugMode) { + print(r); + } + + // set the xiao sense name + if (r.device.advName == 'Go Bluetooth') { + await FlutterBluePlus.stopScan(); + device = r.device; + + await device.connect(); + + try { + _services = await device.discoverServices(); + } catch (e) { + emit(state.copyWith(status: XiaoConnectorStatus.failure)); + throw Exception('Discover Services Error: $e'); + } + + device.connectionState + .listen((BluetoothConnectionState blueState) async { + if (blueState == BluetoothConnectionState.disconnected) { + debugPrint('DISCONNECTED!'); + emit(state.copyWith(status: XiaoConnectorStatus.initial)); + } + }); + + // device.cancelWhenDisconnected(deviceConnectionStream); + emit(state.copyWith(status: XiaoConnectorStatus.connected)); + } + } + }, + onDone: () { + debugPrint('DONE'); + emit(state.copyWith(status: XiaoConnectorStatus.initial)); + }, + ); + } + + Future startCapturing({required String captureType}) async { + final senseService = _services + .where( + (s) => s.serviceUuid == Guid('4c534d36-4453-3354-5253-657276696365'), + ) + .first + .characteristics + .where( + (c) => + c.characteristicUuid == + Guid('61636365-6c65-7261-7469-6f6e44617461'), + ) + .first; + + dataCapturingSubscription = senseService.onValueReceived.listen((value) { + debugPrint('UPDATE: $value'); + debugPrint('UPDATE: ${String.fromCharCodes(value)}'); + + final valueAsString = String.fromCharCodes(value); + + if (valueAsString.startsWith('rX=')) { + gotRotationX = true; + _rotX = valueAsString.replaceAll('rX=', ''); + } + + if (valueAsString.startsWith('rY=')) { + gotRotationY = true; + _rotY = valueAsString.replaceAll('rY=', ''); + } + + if (valueAsString.startsWith('rZ=')) { + gotRotationZ = true; + _rotZ = valueAsString.replaceAll('rZ=', ''); + } + + if (valueAsString.contains(',')) { + gotAcceleration = true; + _accel = valueAsString; + } + + if (gotAcceleration && gotRotationX && gotRotationY && gotRotationZ) { + final accelerations = _accel.split(','); + final capturePoint = CapturePoint( + type: captureType, + rotationX: _rotX, + rotationY: _rotY, + rotationZ: _rotZ, + accelerationX: accelerations[0], + accelerationY: accelerations[1], + accelerationZ: accelerations[2], + millisecondsSinceEpoch: DateTime.now().toUtc().millisecondsSinceEpoch, + ); + emit(state.copyWith(lastCapturedPoint: capturePoint)); + debugPrint("UPDATED POINT!"); + // _writeToObjectBox(capturePoint: capturePoint); + gotRotationX = false; + gotRotationY = false; + gotRotationZ = false; + gotAcceleration = false; + } + }); + + device.cancelWhenDisconnected(dataCapturingSubscription); + + await senseService.setNotifyValue(true); + + emit(state.copyWith(status: XiaoConnectorStatus.capturing)); + } + + Future stopCapturing() async { + await dataCapturingSubscription.cancel(); + + emit(state.copyWith(status: XiaoConnectorStatus.connected)); + } + + void _writeToObjectBox({ + required CapturePoint capturePoint, + }) { + _capturePointsBox.put(capturePoint); + } + + void readFromObjectBox() { + final points = _capturePointsBox.getAll(); + for (var i = 0; i < points.length; i++) { + final point = points[i]; + debugPrint('Type: ${point.type}'); + debugPrint('Id: ${point.id}'); + debugPrint('RotX: ${point.rotationX}'); + debugPrint('RotY: ${point.rotationY}'); + debugPrint('RotZ: ${point.rotationZ}'); + debugPrint('AccelX: ${point.accelerationX}'); + debugPrint('AccelY: ${point.accelerationY}'); + debugPrint('AccelZ: ${point.accelerationZ}'); + debugPrint('Date: ${point.millisecondsSinceEpoch}'); + } + } +} diff --git a/lib/xiao_connector/cubit/xiao_connector_state.dart b/lib/xiao_connector/cubit/xiao_connector_state.dart new file mode 100644 index 0000000..1fce195 --- /dev/null +++ b/lib/xiao_connector/cubit/xiao_connector_state.dart @@ -0,0 +1,40 @@ +part of 'xiao_connector_cubit.dart'; + +enum XiaoConnectorStatus { + initial, + loading, + connected, + capturing, + failure, +} + +extension XiaoConnectorStatusX on XiaoConnectorStatus { + bool get isInitial => this == XiaoConnectorStatus.initial; + bool get isLoading => this == XiaoConnectorStatus.loading; + bool get isConnected => this == XiaoConnectorStatus.connected; + bool get isCapturing => this == XiaoConnectorStatus.capturing; + bool get isFailure => this == XiaoConnectorStatus.failure; +} + +final class XiaoConnectorState extends Equatable { + const XiaoConnectorState({ + this.status = XiaoConnectorStatus.initial, + this.lastCapturedPoint, + }); + + final XiaoConnectorStatus status; + final CapturePoint? lastCapturedPoint; + + XiaoConnectorState copyWith({ + XiaoConnectorStatus? status, + CapturePoint? lastCapturedPoint, + }) { + return XiaoConnectorState( + status: status ?? this.status, + lastCapturedPoint: lastCapturedPoint ?? this.lastCapturedPoint, + ); + } + + @override + List get props => [status, lastCapturedPoint]; +} diff --git a/lib/xiao_connector/models/capture_point.dart b/lib/xiao_connector/models/capture_point.dart new file mode 100644 index 0000000..85a8892 --- /dev/null +++ b/lib/xiao_connector/models/capture_point.dart @@ -0,0 +1,28 @@ +import 'package:objectbox/objectbox.dart'; + +@Entity() +class CapturePoint { + CapturePoint({ + required this.type, + required this.rotationX, + required this.rotationY, + required this.rotationZ, + required this.accelerationX, + required this.accelerationY, + required this.accelerationZ, + this.millisecondsSinceEpoch, + }); + @Id() + int id = 0; + + String type; + String rotationX; + String rotationY; + String rotationZ; + String accelerationX; + String accelerationY; + String accelerationZ; + + // @Property(type: PropertyType.date) + int? millisecondsSinceEpoch; +} diff --git a/lib/xiao_connector/view/capture_view.dart b/lib/xiao_connector/view/capture_view.dart new file mode 100644 index 0000000..048a98c --- /dev/null +++ b/lib/xiao_connector/view/capture_view.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart'; + +class CaptureView extends StatelessWidget { + const CaptureView({super.key}); + + @override + Widget build(BuildContext context) { + final lastCapturePoint = context + .select((XiaoConnectorCubit cubit) => cubit.state.lastCapturedPoint); + return Scaffold( + appBar: AppBar( + title: const Text('Capturing'), + ), + body: SingleChildScrollView( + child: Center( + child: Column( + children: [ + ElevatedButton( + onPressed: () { + context.read().stopCapturing(); + }, + child: const Text('Stop Capturing'), + ), + const Text( + 'Last Captured Point', + style: TextStyle(fontWeight: FontWeight.bold), + ), + Text( + '${DateTime.fromMillisecondsSinceEpoch(lastCapturePoint?.millisecondsSinceEpoch ?? 0)}'), + const Divider(), + Text('Acceleration X: ${lastCapturePoint?.accelerationX}'), + Text('Acceleration Y: ${lastCapturePoint?.accelerationY}'), + Text('Acceleration Z: ${lastCapturePoint?.accelerationZ}'), + const Divider(), + Text('Rotation X: ${lastCapturePoint?.rotationX}'), + Text('Rotation Y: ${lastCapturePoint?.rotationY}'), + Text('Rotation Z: ${lastCapturePoint?.rotationZ}'), + ], + ), + ), + ), + ); + } +} diff --git a/lib/xiao_connector/view/failure_view.dart b/lib/xiao_connector/view/failure_view.dart new file mode 100644 index 0000000..7205938 --- /dev/null +++ b/lib/xiao_connector/view/failure_view.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class FailureView extends StatelessWidget { + const FailureView({super.key}); + + @override + Widget build(BuildContext context) { + return const Text('Failure'); + } +} diff --git a/lib/xiao_connector/view/view.dart b/lib/xiao_connector/view/view.dart new file mode 100644 index 0000000..4f3b923 --- /dev/null +++ b/lib/xiao_connector/view/view.dart @@ -0,0 +1 @@ +export 'xiao_connector_page.dart'; diff --git a/lib/xiao_connector/view/xiao_connector_page.dart b/lib/xiao_connector/view/xiao_connector_page.dart new file mode 100644 index 0000000..3507f9e --- /dev/null +++ b/lib/xiao_connector/view/xiao_connector_page.dart @@ -0,0 +1,59 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart'; +import 'package:xiao_pet_tracker/xiao_connector/view/capture_view.dart'; +import 'package:xiao_pet_tracker/xiao_connector/view/failure_view.dart'; + +@RoutePage() +class XiaoConnectorPage extends StatelessWidget { + const XiaoConnectorPage({super.key}); + + @override + Widget build(BuildContext context) { + return const XiaoConnectorView(); + } +} + +class XiaoConnectorView extends StatelessWidget { + const XiaoConnectorView({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: BlocBuilder( + builder: (context, state) { + return switch (state.status) { + XiaoConnectorStatus.initial => ElevatedButton( + onPressed: () { + context.read().connect(); + }, + child: const Text('Connect'), + ), + XiaoConnectorStatus.loading => const CircularProgressIndicator(), + XiaoConnectorStatus.connected => Column( + children: [ + ElevatedButton( + onPressed: () { + context.read().startCapturing( + captureType: 'test', + ); + }, + child: const Text('Start Capturing'), + ), + ElevatedButton( + onPressed: () { + context.read().readFromObjectBox(); + }, + child: const Text('Get Points'), + ), + ], + ), + XiaoConnectorStatus.capturing => const CaptureView(), + XiaoConnectorStatus.failure => const FailureView(), + }; + }, + ), + ); + } +} diff --git a/lib/xiao_connector/view/xiao_data_page.dart b/lib/xiao_connector/view/xiao_data_page.dart new file mode 100644 index 0000000..dcc8539 --- /dev/null +++ b/lib/xiao_connector/view/xiao_data_page.dart @@ -0,0 +1,22 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +@RoutePage() +class XiaoDataPage extends StatelessWidget { + const XiaoDataPage({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + +class XiaoDataView extends StatelessWidget { + const XiaoDataView({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/xiao_connector/xiao_connector.dart b/lib/xiao_connector/xiao_connector.dart new file mode 100644 index 0000000..00ffcf9 --- /dev/null +++ b/lib/xiao_connector/xiao_connector.dart @@ -0,0 +1 @@ +export 'view/view.dart'; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index bb4b4e2..59f602d 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,9 +6,11 @@ import FlutterMacOS import Foundation import flutter_blue_plus +import objectbox_flutter_libs import path_provider_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterBluePlusPlugin.register(with: registry.registrar(forPlugin: "FlutterBluePlusPlugin")) + ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 49ec2ce..2330d0c 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -2,6 +2,10 @@ PODS: - flutter_blue_plus (0.0.1): - FlutterMacOS - FlutterMacOS (1.0.0) + - ObjectBox (4.0.1) + - objectbox_flutter_libs (0.0.1): + - FlutterMacOS + - ObjectBox (= 4.0.1) - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS @@ -9,21 +13,30 @@ PODS: DEPENDENCIES: - flutter_blue_plus (from `Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus/macos`) - FlutterMacOS (from `Flutter/ephemeral`) + - objectbox_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/objectbox_flutter_libs/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) +SPEC REPOS: + trunk: + - ObjectBox + EXTERNAL SOURCES: flutter_blue_plus: :path: Flutter/ephemeral/.symlinks/plugins/flutter_blue_plus/macos FlutterMacOS: :path: Flutter/ephemeral + objectbox_flutter_libs: + :path: Flutter/ephemeral/.symlinks/plugins/objectbox_flutter_libs/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin SPEC CHECKSUMS: flutter_blue_plus: e2868679021f19d12a8c0c58a33f1df66ec7fa6a FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + ObjectBox: 0bc4bb75eea85f6af06b369148b334c2056bbc29 + objectbox_flutter_libs: 769e6f44f7381c8a8e46a2ed5c71c6068bb476f7 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 -COCOAPODS: 1.13.0 +COCOAPODS: 1.16.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index c8bbc50..0c96578 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -228,7 +228,6 @@ 523E0585C8B64B20217F29E1 /* Pods-RunnerTests.profile-development.xcconfig */, 378BBA354E8F3A05134CE72F /* Pods-RunnerTests.profile-staging.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -282,6 +281,7 @@ 33CC10E52044A3C60003C045 /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0920; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; @@ -500,7 +500,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -515,7 +517,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -530,7 +534,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -567,9 +573,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -594,12 +602,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; @@ -610,6 +620,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Profile-production"; @@ -642,9 +654,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -695,9 +709,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -722,12 +738,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -744,12 +762,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; @@ -760,6 +780,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Debug-production"; @@ -768,6 +790,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Release-production"; @@ -800,9 +824,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -834,12 +860,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[STG] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.stg"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -854,7 +882,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -867,6 +897,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Debug-staging"; @@ -899,9 +931,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -933,12 +967,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[DEV] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.dev"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -953,7 +989,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -966,6 +1004,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Debug-development"; @@ -998,9 +1038,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1025,12 +1067,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[DEV] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.dev"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1044,7 +1088,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1057,6 +1103,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Release-development"; @@ -1089,9 +1137,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1116,12 +1166,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[STG] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.stg"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1135,7 +1187,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1148,6 +1202,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Release-staging"; @@ -1180,9 +1236,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1207,12 +1265,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[DEV] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.dev"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1226,7 +1286,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1239,6 +1301,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Profile-development"; @@ -1271,9 +1335,11 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1298,12 +1364,14 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; FLAVOR_APP_NAME = "[STG] Xiao Pet Tracker"; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.stg"; PRODUCT_NAME = "$(FLAVOR_APP_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1317,7 +1385,9 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.example.verygoodcore.xiao-pet-tracker.RunnerTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1330,6 +1400,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Manual; + DEAD_CODE_STRIPPING = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = "Profile-staging"; diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme index 6ea64c3..70b46d5 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme @@ -1,6 +1,6 @@ com.apple.security.network.server + com.apple.security.app-sandbox + diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements index 852fa1a..38ce6c1 100644 --- a/macos/Runner/Release.entitlements +++ b/macos/Runner/Release.entitlements @@ -4,5 +4,7 @@ com.apple.security.app-sandbox + com.apple.security.app-sandbox + diff --git a/pubspec.lock b/pubspec.lock index 61cddf4..547835b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -38,6 +38,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + auto_route: + dependency: "direct main" + description: + name: auto_route + sha256: b83e8ce46da7228cdd019b5a11205454847f0a971bca59a7529b98df9876889b + url: "https://pub.dev" + source: hosted + version: "9.2.2" + auto_route_generator: + dependency: "direct dev" + description: + name: auto_route_generator + sha256: c9086eb07271e51b44071ad5cff34e889f3156710b964a308c2ab590769e79e6 + url: "https://pub.dev" + source: hosted + version: "9.0.0" + beacon_distance: + dependency: "direct main" + description: + name: beacon_distance + sha256: "59ea80f7d31c7e9591e2095dae808d15a7fb28243da276019190ea94d1203cf7" + url: "https://pub.dev" + source: hosted + version: "0.0.3" bloc: dependency: "direct main" description: @@ -62,6 +86,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" characters: dependency: transitive description: @@ -70,6 +158,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" clock: dependency: transitive description: @@ -78,6 +174,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" collection: dependency: transitive description: @@ -110,6 +214,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" diff_match_patch: dependency: transitive description: @@ -118,6 +230,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" + ditredi: + dependency: "direct main" + description: + name: ditredi + sha256: "0b6c5334fa4198a3e880d1865eece06189edf91ae894087ba67d347ead5aae4e" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -142,19 +270,27 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flat_buffers: + dependency: transitive + description: + name: flat_buffers + sha256: "380bdcba5664a718bfd4ea20a45d39e13684f5318fcd8883066a55e21f37f4c3" + url: "https://pub.dev" + source: hosted + version: "23.5.26" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" - flutter_animate: - dependency: transitive - description: - name: flutter_animate - sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" - url: "https://pub.dev" - source: hosted - version: "4.5.0" flutter_bloc: dependency: "direct main" description: @@ -184,27 +320,40 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_shaders: + flutter_svg: dependency: transitive description: - name: flutter_shaders - sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2" + name: flutter_svg + sha256: "1b7723a814d84fb65869ea7115cdb3ee7c3be5a27a755c1ec60e049f6b9fcbb2" url: "https://pub.dev" source: hosted - version: "0.1.3" - flutter_svg_plus: - dependency: transitive - description: - name: flutter_svg_plus - sha256: "4dcfedc6c7dd6e8c6b23cce4034cd78501cf00ea183c68840f0065178a68d86a" - url: "https://pub.dev" - source: hosted - version: "2.0.13+1" + version: "2.0.11" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + forui: + dependency: "direct main" + description: + name: forui + sha256: b3b4652aaf7e6e3f8165a234a05a53cd80e13b805ae78004b8e5ef35dd67e51c + url: "https://pub.dev" + source: hosted + version: "0.6.1" + forui_assets: + dependency: "direct main" + description: + name: forui_assets + sha256: "48a036b329a855db9a18ebb3db98d5e9d1320479d747b48efd4e698ec7b1f178" + url: "https://pub.dev" + source: hosted + version: "0.3.0" frontend_server_client: dependency: transitive description: @@ -213,6 +362,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: c49895c1ecb0ee2a0ec568d39de882e2c299ba26355aa6744ab1001f98cebd15 + url: "https://pub.dev" + source: hosted + version: "8.0.2" glob: dependency: transitive description: @@ -221,6 +378,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + google_fonts: + dependency: transitive + description: + name: google_fonts + sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 + url: "https://pub.dev" + source: hosted + version: "6.2.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" http: dependency: transitive description: @@ -265,10 +438,18 @@ packages: dependency: transitive description: name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" leak_tracker: dependency: transitive description: @@ -301,14 +482,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - lucide_icons_flutter: - dependency: transitive - description: - name: lucide_icons_flutter - sha256: c1b4250f23ab64e2db3c456db0633077aed7b2afd0dd4a6d3bb38c88cb3d666c - url: "https://pub.dev" - source: hosted - version: "1.2.1" macros: dependency: transitive description: @@ -365,6 +538,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + nitrogen_flutter_svg: + dependency: transitive + description: + name: nitrogen_flutter_svg + sha256: "2c473caaeeeddb11a437e72f9d112622619493ce22dcd6b41f7364cb999b8e2b" + url: "https://pub.dev" + source: hosted + version: "0.3.0+1" + nitrogen_types: + dependency: transitive + description: + name: nitrogen_types + sha256: "04c3e921fe59a47710b81f6bfd3c4dfeb819ca16e25ad6824dcc5b44ca39ed46" + url: "https://pub.dev" + source: hosted + version: "0.3.0+1" node_preamble: dependency: transitive description: @@ -373,6 +562,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + objectbox: + dependency: "direct main" + description: + name: objectbox + sha256: ea823f4bf1d0a636e7aa50b43daabb64dd0fbd80b85a033016ccc1bc4f76f432 + url: "https://pub.dev" + source: hosted + version: "4.0.3" + objectbox_flutter_libs: + dependency: "direct main" + description: + name: objectbox_flutter_libs + sha256: c91350bbbce5e6c2038255760b5be988faead004c814f833c2cd137445c6ae70 + url: "https://pub.dev" + source: hosted + version: "4.0.3" + objectbox_generator: + dependency: "direct dev" + description: + name: objectbox_generator + sha256: "96da521f2cef455cd524f8854e31d64495c50711ad5f1e2cf3142a8e527bc75f" + url: "https://pub.dev" + source: hosted + version: "4.0.3" package_config: dependency: transitive description: @@ -382,7 +595,7 @@ packages: source: hosted version: "2.1.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" @@ -398,13 +611,13 @@ packages: source: hosted version: "1.0.1" path_provider: - dependency: transitive + dependency: "direct main" description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_android: dependency: transitive description: @@ -445,6 +658,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + url: "https://pub.dev" + source: hosted + version: "11.3.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "71bbecfee799e65aff7c744761a57e817e73b738fedf62ab7afd5593da21f9f1" + url: "https://pub.dev" + source: hosted + version: "12.0.13" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 + url: "https://pub.dev" + source: hosted + version: "9.4.5" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851 + url: "https://pub.dev" + source: hosted + version: "0.1.3+2" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: e9c8eadee926c4532d0305dff94b85bf961f16759c3af791486613152af4b4f9 + url: "https://pub.dev" + source: hosted + version: "4.2.3" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" petitparser: dependency: transitive description: @@ -469,6 +730,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" pool: dependency: transitive description: @@ -493,14 +762,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - shadcn_ui: - dependency: "direct main" + pubspec_parse: + dependency: transitive description: - name: shadcn_ui - sha256: "4932db4b88303e517657c7e02af12b034713962ff171ef4402829f98de56b46d" + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.3.0" shelf: dependency: transitive description: @@ -538,6 +807,14 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" source_map_stack_trace: dependency: transitive description: @@ -578,6 +855,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" stream_with_value: dependency: transitive description: @@ -594,6 +879,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + sugar: + dependency: transitive + description: + name: sugar + sha256: "9bfbba7793b5e3650003fca22a857a1d8485e99bf17558cad406a74ba5c4aa3c" + url: "https://pub.dev" + source: hosted + version: "3.1.0" term_glyph: dependency: transitive description: @@ -626,14 +919,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.4" - two_dimensional_scrollables: + timing: dependency: transitive description: - name: two_dimensional_scrollables - sha256: b6028c80e782e58a5d18f9491737aae4f70d72dc08050ac92006905c7c0b5e21 + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "1.0.1" typed_data: dependency: transitive description: @@ -642,6 +935,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0b9149c6ddb013818075b072b9ddc1b89a5122fff1275d4648d297086b46c4f0" + url: "https://pub.dev" + source: hosted + version: "1.1.12" vector_graphics_codec: dependency: transitive description: @@ -650,22 +951,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.11+1" - vector_graphics_compiler_plus: + vector_graphics_compiler: dependency: transitive description: - name: vector_graphics_compiler_plus - sha256: d7dba09b427f65cf7718ae8102e8fbc8ea3b5aabbf4551d070dd2f533581f23f + name: vector_graphics_compiler + sha256: f3b9b6e4591c11394d4be4806c63e72d3a41778547b2c1e2a8a04fadcfd7d173 url: "https://pub.dev" source: hosted version: "1.1.12" - vector_graphics_plus: - dependency: transitive - description: - name: vector_graphics_plus - sha256: fbe58ab75d28de33496781a5222224a821e5a4a08f7cd013418f0acc457af50e - url: "https://pub.dev" - source: hosted - version: "1.1.13" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a27ea58..0db0366 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,21 +7,35 @@ environment: sdk: ^3.5.0 dependencies: + auto_route: ^9.2.2 + beacon_distance: ^0.0.3 bloc: ^8.1.4 + ditredi: ^2.0.2 + equatable: ^2.0.5 flutter: sdk: flutter flutter_bloc: ^8.1.6 flutter_blue_plus_windows: ^1.24.15 flutter_localizations: sdk: flutter + forui: ^0.6.1 + forui_assets: ^0.3.0 + get_it: ^8.0.2 intl: ^0.19.0 - shadcn_ui: ^0.13.5 + objectbox: ^4.0.3 + objectbox_flutter_libs: any + path: ^1.9.0 + path_provider: ^2.1.5 + permission_handler: ^11.3.1 dev_dependencies: + auto_route_generator: ^9.0.0 bloc_test: ^9.1.7 + build_runner: ^2.4.13 flutter_test: sdk: flutter mocktail: ^1.0.4 + objectbox_generator: any very_good_analysis: ^6.0.0 flutter: diff --git a/xiao_controller_code/.vscode/settings.json b/xiao_controller_code/.vscode/settings.json new file mode 100644 index 0000000..44a8686 --- /dev/null +++ b/xiao_controller_code/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "go.toolsEnvVars": { + "GOOS": "linux", + "GOARCH": "arm", + "GOROOT": "/Users/fabian/Library/Caches/tinygo/goroot-a02c847ffd7efbf1e1c759b3cf7d01927ed38f0106b48dbfb04faff6caf9ce40", + "GOFLAGS": "-tags=cortexm,baremetal,linux,arm,nrf52840,nrf,softdevice,s140v7,nrf52840_reset_uf2,xiao_ble,tinygo,purego,osusergo,math_big_pure_go,gc.conservative,scheduler.tasks,serial.usb" + }, + "go.buildTags": "softdevice", +} \ No newline at end of file diff --git a/xiao_controller_code/Makefile b/xiao_controller_code/Makefile index 37a1cd1..1e9da4d 100644 --- a/xiao_controller_code/Makefile +++ b/xiao_controller_code/Makefile @@ -1,17 +1,7 @@ -arduino: - tinygo flash -target=arduino +xiao: flash -esp32: - tinygo flash -target=esp32-mini32 -port=/dev/cu.usbserial-1110 +prepare: + ./flashing_time.py -odroid: - tinygo flash -target=esp32-mini32 -port=/dev/tty.SLAB_USBtoUART - -xiao: +flash: tinygo flash -target=xiao-ble - -debug: - tinygo gdb -target=xiao-ble - -test: - tinygo build -target=xiao-ble -o test.uf2 diff --git a/xiao_controller_code/flashing_time.py b/xiao_controller_code/flashing_time.py new file mode 100755 index 0000000..7784ed7 --- /dev/null +++ b/xiao_controller_code/flashing_time.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +from subprocess import run + +# requires pySerial: +# python -m pip install pyserial +import serial + +# grab the port for the seeed nrf52 (only connect one at a time) +data = run("ls /dev/ | grep 'cu.usbmodem'", capture_output=True, shell=True, text=True) + +ser = serial.Serial("/dev/" + data.stdout.strip(), 1200) +# send 16 null characters as reset signal to enter the bootloader +ser.write(b"\x00" * 16) +ser.close() diff --git a/xiao_controller_code/main.go b/xiao_controller_code/main.go index be32d3c..5f7e6c5 100644 --- a/xiao_controller_code/main.go +++ b/xiao_controller_code/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/binary" "fmt" "machine" "math/rand" @@ -10,27 +11,32 @@ import ( "tinygo.org/x/drivers/lsm6ds3tr" ) +// TinyGo Drivers Docs: +// https://github.com/tinygo-org/drivers + +// TinyGo Bluetooth Docs: +// https://github.com/tinygo-org/bluetooth + var adapter = bluetooth.DefaultAdapter -var ledColor = [3]byte{0xff, 0x00, 0x00} +var ledColor = [3]byte{0x00, 0x00, 0xff} var leds = [3]machine.Pin{machine.LED_RED, machine.LED_GREEN, machine.LED_BLUE} var hasColorChange = true -var heartRate uint8 = 75 // 75bpm - var senseAccelerationData string = "-0.000 -0.000 -0.000" +var senseRotationData string = "-0.000 -0.000 -0.000" + +var bleConnected bool = false + var ( - // a0b40001-926d-4d61-98df-8c5c62ee53b3 - serviceUUID = [16]byte{0xa0, 0xb4, 0x00, 0x01, 0x92, 0x6d, 0x4d, 0x61, 0x98, 0xdf, 0x8c, 0x5c, 0x62, 0xee, 0x53, 0xb3} - senseServiceUUID = [16]byte{0xa0, 0xb4, 0x00, 0x03, 0x92, 0x6d, 0x4d, 0x61, 0x98, 0xdf, 0x8c, 0x5c, 0x62, 0xee, 0x53, 0xb3} - charUUID = [16]byte{0xa0, 0xb4, 0x00, 0x02, 0x92, 0x6d, 0x4d, 0x61, 0x98, 0xdf, 0x8c, 0x5c, 0x62, 0xee, 0x53, 0xb3} - senseCharUUID = [16]byte{0xa0, 0xb4, 0x00, 0x04, 0x92, 0x6d, 0x4d, 0x61, 0x98, 0xdf, 0x8c, 0x5c, 0x62, 0xee, 0x53, 0xb3} + LSM6DS3TRService = [16]byte{0x4C, 0x53, 0x4D, 0x36, 0x44, 0x53, 0x33, 0x54, 0x52, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65} + accelerationData = [16]byte{0x61, 0x63, 0x63, 0x65, 0x6C, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x61, 0x74, 0x61} + tempSenseService = [16]byte{0x74, 0x65, 0x6D, 0x70, 0x53, 0x65, 0x6E, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65} + temperatureSense = [16]byte{0x74, 0x65, 0x6D, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x6E, 0x73, 0x65} ) func main() { - println("starting") - // Configure LSM6DS3TR machine.I2C0.Configure(machine.I2CConfig{}) @@ -42,6 +48,10 @@ func main() { time.Sleep(time.Second) } } + // + // for _, led := range leds { + // led.Configure(machine.PinConfig{Mode: machine.PinOutput}) + // } // Configure Bluetooth must("enable BLE stack", adapter.Enable()) @@ -49,6 +59,9 @@ func main() { must("config adv", adv.Configure(bluetooth.AdvertisementOptions{ LocalName: "Go Bluetooth", ManufacturerData: []bluetooth.ManufacturerDataElement{ + // 0xFFFF: Special Use/Default ID + // Bluetooth Company Identifiers: + // https://gist.github.com/angorb/f92f76108b98bb0d81c74f60671e9c67 {CompanyID: 0xffff, Data: []byte{0x01, 0x02}}, }, })) @@ -56,124 +69,96 @@ func main() { adapter.SetConnectHandler(func(device bluetooth.Device, connected bool) { if connected { println("connected, not advertising...") + // leds[0].Low() + // leds[1].High() + // ledColor[0] = 0 + // ledColor[1] = 1 + // ledColor[2] = 0 + // hasColorChange = true + bleConnected = true } else { println("disconnected, advertising...") + // leds[0].High() + // leds[1].Low() + // ledColor[0] = 0 + // ledColor[1] = 0 + // ledColor[2] = 1 + // hasColorChange = true + bleConnected = false } }) - + // + // Start Bluetooth advertisment must("start adv", adv.Start()) - println("advertising...") - // address, _ := adapter.Address() - - var ledColorCharacteristic bluetooth.Characteristic - must("add led service", adapter.AddService(&bluetooth.Service{ - UUID: bluetooth.NewUUID(serviceUUID), - Characteristics: []bluetooth.CharacteristicConfig{ - { - Handle: &ledColorCharacteristic, - UUID: bluetooth.NewUUID(charUUID), - Value: ledColor[:], - Flags: bluetooth.CharacteristicReadPermission | bluetooth.CharacteristicWritePermission | bluetooth.CharacteristicWriteWithoutResponsePermission, - WriteEvent: func(client bluetooth.Connection, offset int, value []byte) { - if offset != 0 || len(value) != 3 { - return - } - ledColor[0] = value[0] - ledColor[1] = value[1] - ledColor[2] = value[2] - hasColorChange = true - }, - }, - }, - })) - var senseCharacteristic bluetooth.Characteristic must("add sense service", adapter.AddService(&bluetooth.Service{ - UUID: bluetooth.NewUUID(senseServiceUUID), + UUID: bluetooth.NewUUID(LSM6DS3TRService), Characteristics: []bluetooth.CharacteristicConfig{ { Handle: &senseCharacteristic, - UUID: bluetooth.NewUUID(senseCharUUID), + UUID: bluetooth.NewUUID(accelerationData), Value: []byte(senseAccelerationData), Flags: bluetooth.CharacteristicNotifyPermission | bluetooth.CharacteristicReadPermission | bluetooth.CharacteristicWritePermission | bluetooth.CharacteristicWriteWithoutResponsePermission, }, }, })) - for _, led := range leds { - led.Configure(machine.PinConfig{Mode: machine.PinOutput}) - } + // var tempCharacteristic bluetooth.Characteristic + // must("add temperature service", adapter.AddService(&bluetooth.Service{ + // UUID: bluetooth.NewUUID(tempSenseService), + // Characteristics: []bluetooth.CharacteristicConfig{ + // { + // Handle: &tempCharacteristic, + // UUID: bluetooth.NewUUID(temperatureSense), + // Value: []byte(tempData), + // Flags: bluetooth.CharacteristicNotifyPermission | bluetooth.CharacteristicReadPermission, + // }, + // }, + // })) - // Loop - //nextBeat := time.Now() + // Main Loop for { - time.Sleep(500 * time.Millisecond) - //nextBeat = nextBeat.Add(time.Minute / time.Duration(heartRate)) - //println("tick", time.Now().Format("04:05.000")) - //time.Sleep(nextBeat.Sub(time.Now())) + time.Sleep(100 * time.Millisecond) + // for !hasColorChange { + // for i, led := range leds { + // led.Set(ledColor[i] == 0) + // } // time.Sleep(10 * time.Millisecond) // } // hasColorChange = false - // for i, led := range leds { - // led.Set(ledColor[i] == 0) - // } - // random variation in heartrate - // heartRate = randomInt(65, 85) - //heartRate = 85 + // Only read and update sensor data + // with an active bluetooth connection + if bleConnected { + X, Y, Z, _ := accel.ReadRotation() + rotX := fmt.Sprintf("rX=%f", float32(X)/100000000) + rotY := fmt.Sprintf("rY=%f", float32(Y)/100000000) + rotZ := fmt.Sprintf("rZ=%f", float32(Z)/100000000) - // and push the next notification + x, y, z, _ := accel.ReadAcceleration() + accel := fmt.Sprintf("%.3f,%.3f,%.3f", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) + //senseAccelerationData = dataTest - x, y, z, _ := accel.ReadAcceleration() - dataTest := fmt.Sprintf("%.3f %.3f %.3f", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - senseAccelerationData = dataTest + //tempTest, _ := accel.ReadTemperature() + //tempTestBytes := []byte{} + //tempData = fmt.Sprintf("%i", tempTest) - senseCharacteristic.Write([]byte(senseAccelerationData)) + //senseCharacteristic.Write([]byte(dataRotation)) + //senseCharacteristic.Write([]byte("-0.0,-1.2,-5.6")) + senseCharacteristic.Write([]byte(rotX)) + senseCharacteristic.Write([]byte(rotY)) + senseCharacteristic.Write([]byte(rotZ)) + senseCharacteristic.Write([]byte(accel)) - println(senseAccelerationData) + // bs := make([]byte, 4) + // binary.LittleEndian.PutUint32(bs, X) - //x, _, _, _ := accel.ReadAcceleration() - - //heartRate = uint8(x) - - //dataTest := fmt.Sprintf("%d, %d, %d", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - //dataSense = dataTest - // dataTest := fmt.Sprintf("%d, %d, %d", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - //var test = []byte(dataTest) - //senseCharacteristic.Write([]byte(dataSense)) - // println("DATA:") - //println(test) - //println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) + //binary.LittleEndian.AppendUint32(tempTestBytes, uint32(tempTest)) + //tempCharacteristic.Write(tempTestBytes) + } } - - // for { - // if !accel.Connected() { - // println("LSM6DS3TR not connected") - // time.Sleep(time.Second) - // continue - // } - // x, y, z, _ := accel.ReadAcceleration() - // println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - // x, y, z, _ = accel.ReadRotation() - // println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000) - // x, _ = accel.ReadTemperature() - // println("Degrees C", float32(x)/1000, "\n\n") - // time.Sleep(time.Millisecond * 100) - // } - - // led := machine.LED - // led.Configure(machine.PinConfig{Mode: machine.PinOutput}) - // for { - // led.Low() - // time.Sleep(time.Millisecond * 2000) - // println("OFF") - - // led.High() - // time.Sleep(time.Millisecond * 2000) - // println("ON") - // } } func must(action string, err error) {