qnsdk 0.0.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 61

qnsdk #

qnsdk is yolanda Company smart device communication plug-in.

Usage #

To use this plugin, add qnsdk as a dependency in your pubspec.yaml file.

Getting Started #

Xcode configuration
  • iOS10.0 and above must have Bluetooth instructions in Info.plist, otherwise the system's Bluetooth function cannot be used
  • iOS13.0 and above must be configured with the authorization instructions for Bluetooth in Info.plist, otherwise it will be found to crash.
  • There is a pair in the Info.plist [Privacy - Bluetooth Peripheral Usage Description][privacy - bluetooth always usage description] button.
Android
  • Support Android 4.3 system above
  • Using androidx libraries in your project
  • Android 6.0 above requires authorized location rights

Sample Usage #

Initialising #

 String configFileContent = await rootBundle.loadString('data/123456789.qn');
 qnApi.initSDK('123456789', configFileContent).then((result) => print('initSDK ${result.errorCode}'));

Set up listening #

 qnApi.setBleStateListener(this);
 qnApi.setBleDeviceDiscoveryListener(this);
 qnApi.setBleConnectionChangeListener(this);
 qnApi.setScaleDataListener(this);

Start scanning #

 qnApi.startBleDeviceDiscovery();

Connection #

 qnApi.connectDevice(device,user);

Receive data #

 @override
  void onGetUnsteadyWeight(QNBleDevice device, double weight) {
    unsteadyWeightStream.add(weight);
  }

  @override
  void onGetScaleData(QNBleDevice device, QNScaleData data) {
    scaleDataStream.add(data);
  }

  @override
  void onGetStoredScale(
      QNBleDevice device, List<QNScaleStoreData> storedDataList) {
    for (var item in storedDataList) {
      storedDataStream.add(item);
    }
  }

  @override
  void onScaleStateChange(QNBleDevice device, int scaleState) {
    deviceStateStream.add(scaleState);
  }

0.0.3 #

  • Modify "connectDevice" method

0.0.2 #

  • Modify iOS configuration file

0.0.1 #

  • Initial Release

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:qnsdk_example/bleTool.dart';
import 'package:qnsdk_example/group/deviceListItem.dart';
import 'package:qnsdk_example/group/paddingText.dart';
import 'package:qnsdk_example/group/scaleDataListItem.dart';
import 'package:qnsdk_example/tool/Toast.dart';
import 'package:qnsdk_example/userInfo.dart';
import 'package:qnsdk/qnsdk.dart';
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(MyApp());

enum EventState {
  Unknow,
  Scanning,
  Connecting,
  Connected,
  Unsteady,
  BodyFat,
  HeartRate,
  Completed,
  Disconnecting,
  Disconnected,
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var _bleTool = BleTool();
  var _curEvent = EventState.Unknow;
  var _buttonText = 'start scan';
  var _stateText = 'pending';
  var _userInfoWidget = UserInfo();
  QNBleDevice _curDevice;

  var _dataSource = <Map>[];
  var _deviceList = <QNBleDevice>[];

  @override
  void initState() {
    super.initState();
    _setBleStream();
  }

  void _setBleStream() {
    //QNBleStateListener
    _bleTool.bleStateStream.stream.listen((state) {
      var msg = "Unknown";
      switch (state) {
        case QNBLEState.Resetting:
          msg = 'resetting';
          break;
        case QNBLEState.Unsupported:
          msg = 'usupported';
          break;
        case QNBLEState.Unauthiorized:
          msg = 'unauthiorized';
          break;
        case QNBLEState.PoweredOff:
          msg = 'poweredOff';
          break;
        case QNBLEState.PoweredOn:
          msg = 'poweredOn';
          break;
        default:
      }
      Toast.showCenterToast(msg);
    });

    //QNBleConnectionChangeListener
    _bleTool.connectFailStream.stream.listen((value) {
      Toast.showCenterToast('connect fail');
    });

    //QNBleDeviceDiscoveryListener
    _bleTool.discoverStream.stream.listen((device) {
      for (var item in _deviceList) {
        if (item.mac == device.mac) {
          return;
        }
      }
      setState(() {
        _deviceList.add(device);
      });
    });

    //QNScaleDataListener
    _bleTool.unsteadyWeightStream.stream.listen((weight) {
      setState(() {
        _dataSource = [
          {
            'title': 'weight',
            'value': _bleTool.convertWeightWithTargetUnit(weight)
          }
        ];
      });
    });

    _bleTool.scaleDataStream.stream.listen((scaleData) {
      var result = <Map>[];
      for (var item in scaleData.allItemData) {
        var value;
        if (item.type == 1 ||
            item.type == 8 ||
            item.type == 12 ||
            item.type == 13) {
          value = _bleTool.convertWeightWithTargetUnit(item.value);
        } else {
          value = item.value.toStringAsFixed(2);
        }
        result.add({'title': item.name, 'value': value});
      }
      setState(() {
        _dataSource = result;
      });
    });

    _bleTool.storedDataStream.stream.listen((storedData) {
      var user = _userInfoWidget.user;
      _bleTool
          .generateScaleData(user, storedData.weight, storedData.measureTime,
              storedData.mac, storedData.hmac)
          .then((scaleData) {
        print('receive store data ${scaleData.toString()}');
      });
    });

    _bleTool.deviceStateStream.stream.listen((scaleState) {
      switch (scaleState) {
        case QNScaleState.STATE_Link_LOSS:
          _updateCurEvent(EventState.Unknow);
          break;
        case QNScaleState.STATE_DISCONNECTED:
          _updateCurEvent(EventState.Disconnected);
          break;
        case QNScaleState.STATE_CONNECTED:
          _updateCurEvent(EventState.Connected);
          break;
        case QNScaleState.STATE_CONNECTING:
          _updateCurEvent(EventState.Connecting);
          break;
        case QNScaleState.STATE_DISCONNECTING:
          _updateCurEvent(EventState.Disconnecting);
          break;
        case QNScaleState.STATE_START_MEASURE:
        case QNScaleState.STATE_REAL_TIME:
          _updateCurEvent(EventState.Unsteady);
          break;
        case QNScaleState.STATE_BODYFAT:
          _updateCurEvent(EventState.BodyFat);
          break;
        case QNScaleState.STATE_HEART_RATE:
          _updateCurEvent(EventState.HeartRate);
          break;
        case QNScaleState.STATE_MEASURE_COMPLETED:
          _updateCurEvent(EventState.Completed);
          break;
        default:
      }
    });
  }

  void _updateCurEvent(EventState state) {
    var curStateText = _stateText;
    var curBtnText = _buttonText;
    switch (state) {
      case EventState.Scanning:
        curStateText = 'scanning';
        curBtnText = 'stop scan';
        break;
      case EventState.Connecting:
        curStateText = 'connecting';
        curBtnText = 'stop connect';
        break;
      case EventState.Connected:
        curStateText = 'connected';
        curBtnText = 'stop connect';
        break;
      case EventState.Unsteady:
        curStateText = 'realtime weight';
        curBtnText = 'stop connect';
        break;
      case EventState.BodyFat:
        curStateText = 'measure bodyfat';
        curBtnText = 'stop connect';
        break;
      case EventState.HeartRate:
        curStateText = 'measure hear rate';
        curBtnText = 'stop connect';
        break;
      case EventState.Completed:
        curStateText = 'measure completed';
        curBtnText = 'stop connect';
        break;
      case EventState.Disconnecting:
        curStateText = 'disconnecting';
        curBtnText = 'start scan';
        break;
      case EventState.Disconnected:
        curStateText = 'pending';
        curBtnText = 'start scan';
        break;
      default:
        curStateText = 'pending';
        curBtnText = 'start scan';
    }
    setState(() {
      _curEvent = state;
      _stateText = curStateText;
      _buttonText = curBtnText;
    });
  }

  Future requestPermission() async {
    Map<PermissionGroup, PermissionStatus> permissions =
        await PermissionHandler().requestPermissions([PermissionGroup.location]);
    PermissionStatus permission = await PermissionHandler()
        .checkPermissionStatus(PermissionGroup.location);

    if (permission == PermissionStatus.granted) {
      _bleTool.startScan();
          _updateCurEvent(EventState.Scanning);
    } else {
      Toast.showCenterToast("Location permission is denied and bluetooth cannot find the device");
    }
  }

  void _curEventChange() {
    switch (_curEvent) {
      case EventState.Unknow:
        _deviceList.clear();
        if (Platform.isAndroid) {
          //request permission
          requestPermission();
        } else {
          _bleTool.startScan();
          _updateCurEvent(EventState.Scanning);
        }

        break;
      case EventState.Scanning:
        _bleTool.stopScan();
        _updateCurEvent(EventState.Unknow);
        break;
      case EventState.Connecting:
      case EventState.Connected:
      case EventState.Unsteady:
      case EventState.BodyFat:
      case EventState.HeartRate:
      case EventState.Completed:
        _bleTool.disConnect(_curDevice);
        _updateCurEvent(EventState.Unknow);
        break;
      default:
    }
  }

  void _connectDevice(QNBleDevice device) {
    _bleTool.stopScan();
    _updateCurEvent(EventState.Connecting);
    var user = _userInfoWidget.user;
    _curDevice = device;
    _bleTool.connect(device, user);
  }

  bool isShowDeviceList() {
    return _curEvent == EventState.Scanning ||
        _curEvent == EventState.Disconnected;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: const Text('SDK Demo'),
            ),
            body: GestureDetector(
                behavior: HitTestBehavior.translucent,
                onTap: () {
                  FocusScope.of(context).requestFocus(FocusNode());
                },
                child: Column(
                  children: <Widget>[
                    _userInfoWidget,
                    Row(
                      children: <Widget>[
                        Expanded(
                          flex: 1,
                          child: RaisedButton(
                            child: PaddingText(text: _buttonText),
                            onPressed: _curEventChange,
                          ),
                        )
                      ],
                    ),
                    Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[PaddingText(text: _stateText)]),
                    Expanded(
                      flex: 1,
                      child: _showListView(),
                    )
                  ],
                ))));
  }

  Widget _showListView() {
    return ListView.separated(
      padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
      itemCount: isShowDeviceList() ? _deviceList.length : _dataSource.length,
      itemBuilder: (BuildContext context, int index) {
        if (isShowDeviceList()) {
          var item = _deviceList[index];
          return GestureDetector(
            child: DeviceListItem(device: item),
            onTapUp: (details) {
              _connectDevice(_deviceList[index]);
            },
          );
        }
        Map item = _dataSource[index];
        return ScaleDataListItem(title: item['title'], value: item['value']);
      },
      separatorBuilder: (BuildContext context, int index) => Divider(),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  qnsdk: ^0.0.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:qnsdk/qnsdk.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
31
Health:
Code health derived from static analysis. [more]
92
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
61
Learn more about scoring.

We analyzed this package on Jul 2, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package does not support Flutter platform linux

Because of import path [package:qnsdk/qnsdk.dart] that declares support for platforms: android, ios

Package does not support Flutter platform macos

Because of import path [package:qnsdk/qnsdk.dart] that declares support for platforms: android, ios

Package does not support Flutter platform web

Because of import path [package:qnsdk/qnsdk.dart] that declares support for platforms: android, ios

Package does not support Flutter platform windows

Because of import path [package:qnsdk/qnsdk.dart] that declares support for platforms: android, ios

Package not compatible with SDK dart

because of import path [qnsdk] that is in a package requiring null.

Health suggestions

Fix lib/QNApi.dart. (-6.78 points)

Analysis of lib/QNApi.dart reported 14 hints, including:

line 11 col 1: Prefer using /// for doc comments.

line 28 col 3: Prefer using /// for doc comments.

line 37 col 3: Prefer using /// for doc comments.

line 43 col 3: Prefer using /// for doc comments.

line 49 col 3: Prefer using /// for doc comments.

Fix lib/QNBleDevice.dart. (-0.50 points)

Analysis of lib/QNBleDevice.dart reported 1 hint:

line 31 col 24: The method doesn't override an inherited method.

Fix lib/QNConfig.dart. (-0.50 points)

Analysis of lib/QNConfig.dart reported 1 hint:

line 70 col 24: The method doesn't override an inherited method.

Fix lib/QNUser.dart. (-0.50 points)

Analysis of lib/QNUser.dart reported 1 hint:

line 32 col 24: The method doesn't override an inherited method.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test