Masterarbeit Richard Stern. Flutter App, sich mit einem Bluetooth-Gerät verbindet und Berührungen auf einem Sensor visualisiert.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

widgets.dart 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_blue/flutter_blue.dart';
  3. /// scan Results
  4. class ScanResultTile extends StatelessWidget {
  5. final ScanResult result;
  6. final VoidCallback onTap;
  7. final String onlyDeviceToShow;
  8. const ScanResultTile(
  9. {Key key, this.result, this.onlyDeviceToShow, this.onTap})
  10. : super(key: key);
  11. Widget _buildTitle(BuildContext context) {
  12. if (result.device.name.length > 0) {
  13. return Column(
  14. mainAxisAlignment: MainAxisAlignment.start,
  15. crossAxisAlignment: CrossAxisAlignment.start,
  16. children: <Widget>[
  17. Text(result.device.name),
  18. Text(
  19. result.device.id.toString(),
  20. style: Theme.of(context).textTheme.caption,
  21. )
  22. ],
  23. );
  24. } else {
  25. return Text(result.device.id.toString());
  26. }
  27. }
  28. String getNiceHexArray(List<int> bytes) {
  29. return '[${bytes.map((i) => i.toRadixString(16).padLeft(2, '0')).join(', ')}]'
  30. .toUpperCase();
  31. }
  32. String getNiceManufacturerData(Map<int, List<int>> data) {
  33. if (data.isEmpty) {
  34. return null;
  35. }
  36. List<String> res = [];
  37. data.forEach((id, bytes) {
  38. res.add(
  39. '${id.toRadixString(16).toUpperCase()}: ${getNiceHexArray(bytes)}');
  40. });
  41. return res.join(', ');
  42. }
  43. String getNiceServiceData(Map<String, List<int>> data) {
  44. if (data.isEmpty) {
  45. return null;
  46. }
  47. List<String> res = [];
  48. data.forEach((id, bytes) {
  49. res.add('${id.toUpperCase()}: ${getNiceHexArray(bytes)}');
  50. });
  51. return res.join(', ');
  52. }
  53. @override
  54. Widget build(BuildContext context) {
  55. // Test if device = TouchDemonstrator
  56. if (result.advertisementData.localName == onlyDeviceToShow) {
  57. return Container(
  58. // decoration: FlutterLogoDecoration(),
  59. child: Padding(
  60. padding: const EdgeInsets.all(8.0),
  61. child: new Column(
  62. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  63. children: <Widget>[
  64. _buildTitle(context), // Name of devices
  65. RaisedButton(
  66. child: Text('CONNECT'),
  67. color: Colors.black,
  68. textColor: Colors.white,
  69. onPressed:
  70. (result.advertisementData.connectable) ? onTap : null,
  71. ),
  72. ],
  73. ),
  74. ),
  75. );
  76. } else {
  77. return Container();
  78. }
  79. }
  80. }
  81. /// Service tiles
  82. class ServiceTile extends StatelessWidget {
  83. final BluetoothService service;
  84. final List<CharacteristicTile> characteristicTiles;
  85. final String onlyServiceToShow;
  86. const ServiceTile(
  87. {Key key, this.service, this.characteristicTiles, this.onlyServiceToShow})
  88. : super(key: key);
  89. @override
  90. Widget build(BuildContext context) {
  91. if (characteristicTiles.length > 0) {
  92. if (service.uuid.toString().toUpperCase().substring(4, 8) ==
  93. onlyServiceToShow) {
  94. return new ExpansionTile(
  95. initiallyExpanded: true,
  96. title: new Column(
  97. mainAxisAlignment: MainAxisAlignment.center,
  98. crossAxisAlignment: CrossAxisAlignment.start,
  99. children: <Widget>[
  100. const Text('Service (BLEUart)'),
  101. new Text(
  102. 'UUID: 0x${service.uuid.toString().toUpperCase().substring(4, 8)}',
  103. style: Theme.of(context).textTheme.body1.copyWith(
  104. color: Theme.of(context).textTheme.caption.color))
  105. ],
  106. ),
  107. /// characteristic tiles
  108. children: characteristicTiles,
  109. );
  110. } else {
  111. return Container(); //Text("Service not BLEUart");
  112. }
  113. } else {
  114. return new ListTile(
  115. title: const Text('Service'),
  116. subtitle: new Text(
  117. '0x${service.uuid.toString().toUpperCase().substring(4, 8)}'),
  118. );
  119. }
  120. }
  121. }
  122. /// characteristic tile
  123. class CharacteristicTile extends StatelessWidget {
  124. final BluetoothCharacteristic characteristic;
  125. final List<DescriptorTile> descriptorTiles;
  126. //final VoidCallback onReadPressed;
  127. // final VoidCallback onWritePressed;
  128. final VoidCallback onNotificationPressed;
  129. final String onlyCharacteristicToListen;
  130. const CharacteristicTile(
  131. {Key key,
  132. this.characteristic,
  133. this.descriptorTiles,
  134. //this.onReadPressed,
  135. // this.onWritePressed,
  136. this.onNotificationPressed,
  137. @required this.onlyCharacteristicToListen})
  138. : super(key: key);
  139. @override
  140. Widget build(BuildContext context) {
  141. if(onlyCharacteristicToListen == characteristic.uuid.toString().toUpperCase().substring(4,8)){
  142. print("found ${characteristic.uuid.toString().toUpperCase().substring(4,8)} /// $onlyCharacteristicToListen");
  143. }
  144. /// title
  145. var title = new Column(
  146. mainAxisAlignment: MainAxisAlignment.center,
  147. crossAxisAlignment: CrossAxisAlignment.start,
  148. children: <Widget>[
  149. const Text('CharacteristicTile title'),
  150. new Text(
  151. '0x${characteristic.uuid.toString().toUpperCase().substring(4, 8)}',
  152. style: Theme.of(context)
  153. .textTheme
  154. .body1
  155. .copyWith(color: Theme.of(context).textTheme.caption.color))
  156. ],
  157. );
  158. /// subscribe
  159. var actions = new Row(
  160. mainAxisSize: MainAxisSize.min,
  161. children: <Widget>[
  162. new IconButton(
  163. icon: new Icon(
  164. characteristic.isNotifying ? Icons.sync_disabled : Icons.sync,
  165. color: Theme.of(context).iconTheme.color.withOpacity(0.5)),
  166. onPressed: onNotificationPressed,
  167. )
  168. ],
  169. );
  170. return new ListTile(
  171. title: title,
  172. subtitle: new Text(characteristic.value.toString()),
  173. trailing: actions,
  174. );
  175. //onNotificationPressed();
  176. /*if (descriptorTiles.length > 0) {
  177. return new ExpansionTile(
  178. title: new ListTile(
  179. title: title,
  180. subtitle: new Text(characteristic.value.toString()),
  181. contentPadding: EdgeInsets.all(0.0),
  182. ),
  183. trailing: actions,
  184. children: descriptorTiles,
  185. );
  186. } else {*/
  187. }
  188. }
  189. class DescriptorTile extends StatelessWidget {
  190. final BluetoothDescriptor descriptor;
  191. /* final VoidCallback onReadPressed;
  192. final VoidCallback onWritePressed;*/
  193. const DescriptorTile(
  194. {Key key, this.descriptor}) //, this.onReadPressed, this.onWritePressed})
  195. : super(key: key);
  196. @override
  197. Widget build(BuildContext context) {
  198. var title = new Column(
  199. mainAxisAlignment: MainAxisAlignment.center,
  200. crossAxisAlignment: CrossAxisAlignment.start,
  201. children: <Widget>[
  202. const Text('Descriptor'),
  203. new Text(
  204. '0x${descriptor.uuid.toString().toUpperCase().substring(4, 8)}',
  205. style: Theme.of(context)
  206. .textTheme
  207. .body1
  208. .copyWith(color: Theme.of(context).textTheme.caption.color))
  209. ],
  210. );
  211. return new ListTile(
  212. title: title,
  213. subtitle: new Text(descriptor.value.toString()),
  214. /* trailing: new Row(
  215. mainAxisSize: MainAxisSize.min,
  216. children: <Widget>[
  217. new IconButton(
  218. icon: new Icon(
  219. Icons.file_download,
  220. color: Theme.of(context).iconTheme.color.withOpacity(0.5),
  221. ),
  222. onPressed: null,//onReadPressed,
  223. ),
  224. new IconButton(
  225. icon: new Icon(
  226. Icons.file_upload,
  227. color: Theme.of(context).iconTheme.color.withOpacity(0.5),
  228. ),
  229. onPressed: null,//onWritePressed,
  230. )
  231. ],
  232. ),*/
  233. );
  234. }
  235. }