2023-09-21 00:12:01 +02:00
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 {
2023-09-21 16:05:34 +02:00
final bool small ;
const Compass ( this . small , { super . key } ) ;
2023-09-21 00:12:01 +02:00
@ override
2023-09-21 16:05:34 +02:00
// ignore: no_logic_in_create_state
State < StatefulWidget > createState ( ) = > _CompassState ( small ) ;
2023-09-21 00:12:01 +02:00
}
class _CompassState extends State < Compass > {
2023-09-21 16:05:34 +02:00
final bool small ;
_CompassState ( this . small ) : super ( ) ;
2023-09-21 00:12:01 +02:00
USerial serial = getSerial ( ) ;
2023-09-21 16:05:34 +02:00
Timer ? timer ;
2023-09-21 00:12:01 +02:00
int _magX = 0 , _magY = 0 , _magZ = 0 , _magAngle = 0 ;
2023-09-21 16:05:34 +02:00
bool available = true ;
2023-09-21 00:12:01 +02:00
@ override
void initState ( ) {
super . initState ( ) ;
SensorReader . listen ( serialListen ) ;
2023-09-21 16:05:34 +02:00
if ( small ) {
timer = Timer . periodic ( const Duration ( milliseconds: 500 ) , ( _ ) async {
if ( available ) serial . sprintln ( " <rfSystemSensor>2200 " , system: true ) ;
} ) ;
}
2023-09-21 00:12:01 +02:00
}
@ override
void dispose ( ) {
SensorReader . removeListen ( serialListen ) ;
2023-09-21 16:05:34 +02:00
timer ? . cancel ( ) ;
2023-09-21 00:12:01 +02:00
super . dispose ( ) ;
}
void serialListen ( int type , int command , Pointer < ArrayCStruct > ptr ) {
2023-09-21 16:05:34 +02:00
if ( type = = 0x22 & & command = = 0xff ) {
setState ( ( ) {
available = false ;
} ) ;
return ;
}
2023-09-21 00:12:01 +02:00
if ( type ! = 0x22 | | command ! = 0x00 ) return ;
var loc = ptr as Pointer < GnssLocData > ;
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
2023-09-21 16:05:34 +02:00
Widget build ( BuildContext context ) = > small
? GestureDetector (
onTap: ( ) {
if ( available ) {
Navigator . push (
context ,
MaterialPageRoute ( builder: ( context ) = > const Compass ( false ) ) ,
) ;
} else {
available = true ;
}
} ,
child: buildLoc ( context ) )
: Scaffold (
appBar: AppBar (
backgroundColor: Theme . of ( context ) . colorScheme . inversePrimary ,
title: const Text (
" Compass " ,
style: TextStyle (
fontSize: 16 ,
2023-09-21 00:12:01 +02:00
) ,
2023-09-21 16:05:34 +02:00
) ,
toolbarHeight: 40 ,
2023-09-21 00:12:01 +02:00
) ,
2023-09-21 16:05:34 +02:00
body: Container (
padding: const EdgeInsets . all ( 0.3 * 2 * 20 ) ,
child: buildLoc ( context ) ) ,
) ;
Widget buildLoc ( BuildContext context ) = > ! available
? const Center (
child: Column (
mainAxisAlignment: MainAxisAlignment . center ,
crossAxisAlignment: CrossAxisAlignment . center ,
children: [ Text ( " Compass is not available! " ) , Icon ( Icons . block ) ] ) )
: Stack (
children: [
Center ( child: SvgPicture . asset ( ' assets/compass.svg ' ) ) ,
Center (
child: 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 " ) ,
if ( ! small )
Expanded (
child: Align (
alignment: Alignment . bottomLeft ,
child: FilledButton (
child: const Icon ( Icons . calculate ) ,
onPressed: ( ) {
showDialog < String > (
context: context ,
builder: ( BuildContext context ) = > AlertDialog (
title: const Text ( ' Callibrate Compass ' ) ,
content: const Text (
' When clicking okay the compass will be calibrated, \n completely blocking all radio communication for 10 sec. \n While calibrating rotate the sensor in ever direction. ' ) ,
actions: < Widget > [
TextButton (
onPressed: ( ) = >
Navigator . pop ( context , ' Cancel ' ) ,
child: const Text ( ' Cancel ' ) ,
) ,
TextButton (
onPressed: ( ) {
serial . sprintln ( " <rfSystemSensor>2201 " ,
system: true ) ;
Navigator . pop ( context , ' OK ' ) ;
} ,
child: const Text ( ' OK ' ) ,
) ,
] ,
) ,
) ;
//
} ,
) ,
) ,
) ,
] ,
) ,
Align (
alignment: Alignment . topRight ,
child: Text (
" t: ${ ( sqrt ( _magX * _magX + _magY * _magY + _magZ * _magZ ) * 8.0 / 32768.0 * 100.0 ) . toStringAsFixed ( 2 ) } µT " ) ,
)
] ,
) ;
2023-09-21 00:12:01 +02:00
}