test.dart 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import 'dart:async';
  2. import 'dart:math';
  3. import 'dart:ui';
  4. import 'package:buffer/buffer.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
  7. import 'package:nrf/app_subscription_state.dart';
  8. class Test extends StatefulWidget {
  9. final DiscoveredDevice device;
  10. final QualifiedCharacteristic characteristicNotify;
  11. const Test({Key? key, required this.device, required this.characteristicNotify}) : super(key: key);
  12. @override
  13. State<StatefulWidget> createState() => _State();
  14. }
  15. class _State extends State<Test> with SubscriptionState {
  16. final LABEL = ["left acc x", "acc y", "acc z", "gyro x", "gyro y", "gyro z", "front mag x", "front mag y", "front mag z", "back mag x", "back mag y", "back mag z", "right acc x", "r acc y", "r acc z", "r gyro x", "r gyro y", "r gyro z", "r front mag x", "r front mag y", "r front mag z", "r back mag x", "r back mag y", "r back mag z", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"];
  17. final List<int> FIX = [];
  18. final List<Color> COLORS = [];
  19. final List<List<int>> data = [];
  20. final flutterReactiveBle = FlutterReactiveBle();
  21. Timer? _timer;
  22. @override
  23. void initState() {
  24. super.initState();
  25. FIX.addAll(List.filled(LABEL.length, 1));
  26. COLORS.addAll(List.generate(LABEL.length, (index) => Color.fromRGBO(Random().nextInt(256), Random().nextInt(256),
  27. Random().nextInt(256), 1)));
  28. addSubscription(flutterReactiveBle.subscribeToCharacteristic(widget.characteristicNotify).listen((event) {
  29. ByteDataReader reader = ByteDataReader();
  30. reader.add(event);
  31. int flagAA = reader.readInt8();
  32. int len = reader.readInt8();
  33. reader.readInt8();
  34. int cmd = reader.readInt8();
  35. if(cmd != 4){
  36. return;
  37. }
  38. List<int> array = [];
  39. while (reader.remainingLength > 1) {
  40. array.add(reader.readInt16());
  41. }
  42. if(data.length > 500) {
  43. data.removeAt(0);
  44. }
  45. data.add(array);
  46. }));
  47. _timer = Timer.periodic(const Duration(milliseconds: 16), (timer) {
  48. setState(() {
  49. });
  50. });
  51. }
  52. @override
  53. void dispose() {
  54. _timer?.cancel();
  55. super.dispose();
  56. }
  57. @override
  58. Widget build(BuildContext context) {
  59. return Scaffold(
  60. appBar: AppBar(
  61. title: Text("${widget.device.name}"),
  62. actions: [
  63. IconButton(icon: Icon(Icons.select_all), onPressed: () {
  64. setState(() {
  65. for(var i = 0; i < FIX.length;i++){
  66. FIX[i] = 1;
  67. }
  68. });
  69. },),IconButton(icon: Icon(Icons.clear_all), onPressed: () {
  70. setState(() {
  71. for(var i = 0; i < FIX.length;i++){
  72. FIX[i] = 0;
  73. }
  74. });
  75. },),
  76. IconButton(icon: Text("左"), onPressed: () {
  77. setState(() {
  78. for(var i = 0; i < FIX.length;i++){
  79. FIX[i] = 0;
  80. }
  81. for(var i = 0; i < 12;i++){
  82. FIX[i] = 1;
  83. }
  84. });
  85. },),
  86. IconButton(icon: Text("右"), onPressed: () {
  87. setState(() {
  88. for(var i = 0; i < FIX.length;i++){
  89. FIX[i] = 0;
  90. }
  91. for(var i = 12; i < FIX.length;i++){
  92. FIX[i] = 1;
  93. }
  94. });
  95. },),
  96. ],
  97. ),
  98. body: Row(
  99. children: [
  100. Expanded(
  101. child: Padding(
  102. padding: const EdgeInsets.all(8.0),
  103. child: CustomPaint(
  104. painter: _Painter(data, FIX, COLORS),
  105. child: const SizedBox(
  106. width: double.infinity,
  107. height: double.infinity,
  108. ),
  109. ),
  110. ),
  111. ),
  112. const SizedBox(
  113. width: 20,
  114. ),
  115. Container(
  116. width: 150,
  117. height: double.infinity,
  118. child: SingleChildScrollView(
  119. child: Column(
  120. crossAxisAlignment: CrossAxisAlignment.start,
  121. children: [
  122. for (var i = 0; i < LABEL.length; i++)
  123. InkWell(
  124. onTap: () {
  125. setState(() {
  126. FIX[i] = FIX[i] == 1 ? 0 : 1;
  127. });
  128. },
  129. child: Row(
  130. mainAxisSize: MainAxisSize.min,
  131. children: [
  132. Checkbox(
  133. value: FIX[i] == 1,
  134. onChanged: (bool? value) {},
  135. ),
  136. Text(LABEL[i], style: TextStyle(color: COLORS[i]),)
  137. ],
  138. ),
  139. ),
  140. ],
  141. ),
  142. ),
  143. ),
  144. ],
  145. ),
  146. );
  147. }
  148. }
  149. class _Painter extends CustomPainter {
  150. final _line = Paint()
  151. ..color = const Color(0xffdcdcdc)
  152. ..strokeWidth = 1;
  153. final _line1 = Paint()
  154. ..color = const Color(0xffdcdcdc)
  155. ..strokeWidth = 1;
  156. final List<List<int>> data;
  157. final List<int> fixed;
  158. final List<Color> colors;
  159. _Painter(this.data, this.fixed, this.colors);
  160. @override
  161. void paint(Canvas canvas, Size size) {
  162. List<List<int>> items = data;
  163. int length = items.length;
  164. if(length <= 0)return;
  165. final center = Offset(size.width / 2, size.height / 2);
  166. final centerX = center.dx;
  167. final centerY = center.dy;
  168. const double paddingLeft = 60.0;
  169. canvas.drawLine(Offset(0, centerY), Offset(size.width, centerY), _line);
  170. canvas.drawLine(const Offset(paddingLeft, 0), Offset(paddingLeft, size.width), _line);
  171. double width = (size.width - paddingLeft) / length;
  172. int maxValue = items.map((e) {
  173. int d = 0;
  174. for(var i = 0 ; i < e.length; i++){
  175. d = max(d, fixed[i] == 0 ? 0 : e[i]);
  176. }
  177. return d;
  178. }).reduce(max);
  179. int minValue = items.map((e) {
  180. int d = 0;
  181. for(var i = 0 ; i < e.length; i++){
  182. d = min(d, fixed[i] == 0 ? 0 : e[i]);
  183. }
  184. return d;
  185. }).reduce(min);
  186. int split = 4;
  187. int absMax = max(maxValue, minValue.abs());
  188. double height = size.height / 2;
  189. double yAxisSplitHeight = height / split;
  190. for(var i = 1 ; i <= split; i++){
  191. canvas.drawLine(Offset(paddingLeft, centerY - i * yAxisSplitHeight), Offset(paddingLeft + 10, centerY - i * yAxisSplitHeight), _line);
  192. var text = TextPainter(
  193. text: TextSpan(
  194. style: const TextStyle(fontSize: 12.0, color: Color(0xffdcdcdc)),
  195. text: "${absMax / split * i}",
  196. ),
  197. textAlign: TextAlign.left,
  198. textDirection: TextDirection.ltr,
  199. )
  200. ..layout(minWidth: 100);
  201. text.paint(canvas, Offset(0, centerY - i * yAxisSplitHeight - text.height / 2));
  202. canvas.drawLine(Offset(paddingLeft, centerY + i * yAxisSplitHeight), Offset(paddingLeft + 10, centerY + i * yAxisSplitHeight), _line);
  203. text = TextPainter(
  204. text: TextSpan(
  205. style: const TextStyle(fontSize: 12.0, color: Color(0xffdcdcdc)),
  206. text: "-${absMax / split * i}",
  207. ),
  208. textAlign: TextAlign.left,
  209. textDirection: TextDirection.ltr,
  210. )
  211. ..layout(minWidth: 100);
  212. text.paint(canvas, Offset(0, centerY + i * yAxisSplitHeight - text.height / 2));
  213. }
  214. int maxColumn = items.first.length;
  215. for(var j = 0; j < fixed.length; j ++){
  216. if(fixed[j] == 0) {
  217. continue;
  218. }
  219. if(j >= maxColumn) {
  220. break;
  221. }
  222. Path path = Path();
  223. for(var i = 0; i < length; i++){
  224. var item = items[i];
  225. int value = item[j];
  226. double dx = i*width + paddingLeft;
  227. double dy = value > 0 ? (1 - value / absMax) * height :(value.abs() / absMax) * height + centerY;
  228. if(i == 0){
  229. path.moveTo(dx, dy);
  230. }else{
  231. path.lineTo(dx, dy);
  232. }
  233. }
  234. final paint = Paint()
  235. ..color = colors[j]
  236. ..strokeWidth = 1
  237. ..style = PaintingStyle.stroke;
  238. canvas.drawPath(path, paint);
  239. }
  240. }
  241. @override
  242. bool shouldRepaint(covariant CustomPainter oldDelegate) {
  243. return true;
  244. }
  245. }