import 'dart:async'; import 'dart:ffi'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:ju_rc_app/lib/boxes.dart'; import 'package:ju_rc_app/lib/sensors.dart'; import 'package:ju_rc_app/lib/serial.dart'; // c-structs base class GnssLocData extends Struct { @Uint8() external int type; @Uint8() external int command; @Int32() external int X; @Int32() external int Y; @Int32() external int Z; @Int32() external int angle; } // end c-structs class Compass extends JuBox { const Compass({super.key}); @override State createState() => _CompassState(); } class _CompassState extends State { USerial serial = getSerial(); late Timer timer; int _magX = 0, _magY = 0, _magZ = 0, _magAngle = 0; @override void initState() { super.initState(); SensorReader.listen(serialListen); timer = Timer.periodic(const Duration(milliseconds: 500), (_) async { serial.sprintln("2200", system: true); }); } @override void dispose() { SensorReader.removeListen(serialListen); timer.cancel(); super.dispose(); } void serialListen(int type, int command, Pointer ptr) { if (type != 0x22 || command != 0x00) return; var loc = ptr as Pointer; setState(() { _magX = loc.ref.X; _magY = loc.ref.Y; _magZ = loc.ref.Z; int newAngle = loc.ref.angle; if (newAngle - _magAngle > 200) newAngle -= 360; if (newAngle - _magAngle < -200) newAngle += 360; _magAngle = newAngle; }); } @override Widget build(BuildContext context) => Stack( children: [ SvgPicture.asset('assets/compass.svg'), AnimatedRotation( turns: _magAngle / 360.0, duration: const Duration(milliseconds: 500), alignment: Alignment.center, // Rotate around the center child: SvgPicture.asset('assets/needle.svg')), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "x: ${(_magX * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), Text( "y: ${(_magY * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), Text( "z: ${(_magZ * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), Expanded( child: Align( alignment: Alignment.bottomLeft, child: FilledButton( child: const Icon(Icons.calculate), onPressed: () { showDialog( context: context, builder: (BuildContext context) => AlertDialog( title: const Text('Callibrate Compass'), content: const Text( 'When clicking okay the compass will be calibrated, \ncompletely blocking all radio communication for 10 sec. \nWhile calibrating rotate the sensor in ever direction.'), actions: [ TextButton( onPressed: () => Navigator.pop(context, 'Cancel'), child: const Text('Cancel'), ), TextButton( onPressed: () { serial.sprintln("2201", system: true); Navigator.pop(context, 'OK'); }, child: const Text('OK'), ), ], ), ); // }, ), ), ), ], ), Expanded( child: Align( alignment: Alignment.topRight, child: Text( "t: ${(sqrt(_magX * _magX + _magY * _magY + _magZ * _magZ) * 8.0 / 32768.0 * 100.0).toStringAsFixed(2)}µT"), )) ], ); }