dgtdriver 0.2.4 copy "dgtdriver: ^0.2.4" to clipboard
dgtdriver: ^0.2.4 copied to clipboard

A DGT-Chessboard Driver written in pure Dart

example/lib/main.dart

import 'dart:typed_data';

import 'package:dgtdriver/DGTCommunicationClient.dart';
import 'package:dgtdriver/models/BatteryStatus.dart';
import 'package:dgtdriver/models/LEDPattern.dart';
import 'package:dgtdriver/models/FieldUpdate.dart';
import 'package:dgtdriver/models/ClockMessage.dart';
import 'package:dgtdriver/protocol/ClockAnswerType.dart';
import 'package:dgtdriver/protocol/ClockButton.dart';
import 'package:flutter/material.dart';
import 'package:dgtdriver/DGTBoard.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:usb_serial/usb_serial.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DGTBoard connectedBoard;
  ClockInfoMessage lastClockInfo;
  List<ClockMessage> lastClockAcks = [];
  List<ClockButton> lastClockButtons = [];

  TextEditingController _clockAsciiTextController = new TextEditingController();

  String _characteristicReadId = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
  String _characteristicWriteId = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
  Duration scanDuration = Duration(seconds: 4);
  List<ScanResult> devices = [];
  bool scanning = false;
  
  FlutterBlue flutterBlue = FlutterBlue.instance;
  BluetoothDevice _port;
  BluetoothCharacteristic _characteristicRead;
  BluetoothCharacteristic _characteristicWrite;


  void connectBle() async {
    if (_port == null) {
      // Start scanning
      flutterBlue.startScan(timeout: scanDuration);

      // Listen to scan results
      _port = (
        await flutterBlue.scanResults.firstWhere((r) => r.where((r) => r.device.name.contains("DGT")).length > 0)
      ).where((r) => r.device.name.contains("DGT")).first.device;

      if (_port == null) return;
    }
    try {
      await _port.connect();
    } catch (_) {}
    
    List<BluetoothService> services = await _port.discoverServices();

    for (BluetoothService s in services) {
      for (BluetoothCharacteristic c in s.characteristics) {
        if (c.uuid.toString() == _characteristicReadId) _characteristicRead = c;
        if (c.uuid.toString() == _characteristicWriteId) _characteristicWrite = c;
        if (c.properties.write) print("Write avaiable on: " + c.uuid.toString());
        if (c.properties.read && c.properties.notify) print("Read/Noitify avaiable on: " + c.uuid.toString());
      }
    }

    await _characteristicRead.setNotifyValue(true);

    DGTCommunicationClient client = DGTCommunicationClient(
      (list) {
        print(list.toList());
        return _characteristicWrite.write(list.toList());
      }
    );
    _characteristicRead.value.listen((list) => client.handleReceive(Uint8List.fromList(list)));
    
    connect(client);
  }

  void connectUsb() async {
    List<UsbDevice> devices = await UsbSerial.listDevices();
    List<UsbDevice> dgtDevices = devices.where((d) => d.vid == 1115).toList();
    if (dgtDevices.length == 0) return;

    UsbPort usbDevice = await dgtDevices[0].create();
    await usbDevice.open();

    DGTCommunicationClient client = DGTCommunicationClient(usbDevice.write);
    usbDevice.inputStream.listen(client.handleReceive);
    
    connect(client);
  }

  void connect(DGTCommunicationClient client) async {
    // connect to board and initialize
    DGTBoard nBoard = new DGTBoard();
    await nBoard.init(client);
    print("DGTBoard connected - SerialNumber: " +
        nBoard.getSerialNumber() +
        " Version: " +
        nBoard.getVersion());

    // set connected board
    setState(() {
      connectedBoard = nBoard;
    });

    // If not pegasus -> Board & Clock Updates.
    // Otherwise only Board Updates
    if (nBoard.isPegasusBoard) {
      await nBoard.setBoardToUpdateBoardMode();
    } else {
      await nBoard.setBoardToUpdateMode();
    }

    // set board to update charge mode
    await nBoard.setBoardToUpdateBatteryMode();
  }

  void _showClockAsciiDialog(context) async {
    String text = await showDialog(context: context, builder: (context) {
      return AlertDialog(
        contentPadding: EdgeInsets.all(16.0),
        content: Row(
          children: <Widget>[
            Expanded(
              child: TextField(
                controller: _clockAsciiTextController,
                autofocus: true,
                decoration: InputDecoration(
                    labelText: 'Text', hintText: 'Write something'),
                ),
            )
          ],
        ),
        actions: <Widget>[
          TextButton(
              child: Text('Send'),
              onPressed: () {
                Navigator.pop(context, _clockAsciiTextController.text);
              })
        ],
      );
    });

    connectedBoard.clockText(text, beep: Duration(milliseconds: 200));
  }

  void _sendClockBeep() {
    connectedBoard.clockBeep(Duration(milliseconds: 200));
  }

  void _testLeds() {
    connectedBoard.setLEDPattern(LEDPattern(
      speed: LEDPatternSpeed.speed7,
      brightness: LEDPatternBrightness.high,
      repeat: LEDPatternRepeat.once,
      fields: [
        connectedBoard.ledPatternFieldFromAlgebra("a1"),
        connectedBoard.ledPatternFieldFromAlgebra("b2"),
        connectedBoard.ledPatternFieldFromAlgebra("c3"),
        connectedBoard.ledPatternFieldFromAlgebra("d4"),
        connectedBoard.ledPatternFieldFromAlgebra("e5"),
        connectedBoard.ledPatternFieldFromAlgebra("f6"),
        connectedBoard.ledPatternFieldFromAlgebra("g7"),
        connectedBoard.ledPatternFieldFromAlgebra("h8"),
      ]
    ));
  }

  void _testSetClock1() {
    connectedBoard.clockSet(
      Duration(minutes: 4, seconds: 20),
      Duration(minutes: 20, seconds: 4),
      false,
      true,
      false,
      true
    );
  }

  void _disconnectBle() {
    _port.disconnect();
    setState(() {
      _port = null;
      connectedBoard = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("dgtdriver example"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ...(
            connectedBoard != null ? [
              Text("Connected")
            ] : [
              TextButton(
                child: Text("Try to connect to USB"),
                onPressed: connectUsb
              ),
              TextButton(
                child: Text("Try to connect to BLE"),
                onPressed: connectBle
              )
            ]
          ),
          Center( child: StreamBuilder(
            stream: connectedBoard?.getBoardDetailedUpdateStream(),
            builder: (context, AsyncSnapshot<DetailedFieldUpdate> snapshot) {
              if (!snapshot.hasData) return Text("-");

              DetailedFieldUpdate fieldUpdate = snapshot.data;
              return Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text("Last Update: "),
                  Text("Square: " + fieldUpdate.field),
                  Text("Action: " + fieldUpdate.action.toString()),
                  Text("Piece: " + fieldUpdate.piece.toString()),
                  Text("Notation: " + fieldUpdate.getNotation()),
                ],
              );
            }
          )),
          ...(connectedBoard != null && connectedBoard.isPegasusBoard ? [
            SizedBox(height: 34),
            Text("Pegasus Board"),
            TextButton(child: Text("Disconnect"), onPressed: () => _disconnectBle()),
            StreamBuilder(
              stream: connectedBoard?.getBatteryUpdateStream(),
              builder: (context, AsyncSnapshot<BatteryStatus> snapshot) {
                if (!snapshot.hasData) return Text("-");

                BatteryStatus status = snapshot.data;
                return Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text("Battery Percentage: " + status.charge.toString()),
                    Text("Charging: " + (status.isCharging ? "Yes" : "No")),
                  ],
                );
              }
            ),
            TextButton(child: Text("Test LED's"), onPressed: () => _testLeds()),
          ] : []),
          ...(connectedBoard != null && !connectedBoard.isPegasusBoard ? [
            SizedBox(height: 34),
            Text("Clock Tests"),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextButton(child: Text("Send Beep"), onPressed: () => _sendClockBeep()),
                TextButton(child: Text("Test Set 1"), onPressed: () => _testSetClock1()),
                TextButton(child: Text("Send Text"), onPressed: () => _showClockAsciiDialog(context))
              ],
            ),
          ] : []),
          Center(child: StreamBuilder(
            stream: connectedBoard?.getClockUpdateStream(),
            builder: (context, AsyncSnapshot<ClockMessage> snapshot) {
              if (!snapshot.hasData) return Text("-");

              ClockMessage message = snapshot.data;
              if (message.type == ClockAnswerType.info) {
                lastClockInfo = message;
              } else {
                lastClockAcks.add(message);
                if (message is ClockButtonMessage) {
                  lastClockButtons.add(message.button);
                }
              }

              if (lastClockInfo == null) return Text("-");

              return Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                    Text("Clock Acks(last): " + (lastClockAcks.isNotEmpty ? lastClockAcks.last.type.toString() : "-")),
                    Text("Clock Connected: " + (lastClockInfo.clockFlags.clockConnected ? "Yes" : "No")),
                    Text("Clock Running: " + (lastClockInfo.clockFlags.clockRunning ? "Yes" : "No")),
                    Text("Clock lever: " + (lastClockInfo.clockFlags.rightHigh ? "Left" : "Right")),
                    Text("Clock Battery: " + (lastClockInfo.clockFlags.batteryLow ? "Low" : "Normal")),
                    Text("Clock LeftToMove: " + (lastClockInfo.clockFlags.leftToMove ? "Yes" : "No")),
                    Text("Clock RightToMove: " + (lastClockInfo.clockFlags.rightToMove ? "Yes" : "No")),
                    Text("Clock Left Player Time: " + lastClockInfo.left.time.toString()),
                    Text("Clock Left Player FinalFlag: " + (lastClockInfo.left.flags.finalFlag ? "Yes" : "No")),
                    Text("Clock Left Player FlagFlag: " + (lastClockInfo.left.flags.flag ? "Yes" : "No")),
                    Text("Clock Left Player TimePerMoveFlag: " + (lastClockInfo.left.flags.timePerMove ? "Yes" : "No")),
                    Text("Clock Right Player Time: " + lastClockInfo.right.time.toString()),
                    Text("Clock Right Player FinalFlag: " + (lastClockInfo.right.flags.finalFlag ? "Yes" : "No")),
                    Text("Clock Right Player FlagFlag: " + (lastClockInfo.right.flags.flag ? "Yes" : "No")),
                    Text("Clock Right Player TimePerMoveFlag: " + (lastClockInfo.right.flags.timePerMove ? "Yes" : "No")),
                    Text("Clock Buttons pressed(last): " + (lastClockButtons.isNotEmpty ? lastClockButtons.last.toString() : "-")),
                ],
              );
            }
          )),
        ],
      ),
    );
  }
}