carp_webservices 0.40.2 copy "carp_webservices: ^0.40.2" to clipboard
carp_webservices: ^0.40.2 copied to clipboard

Flutter API for accessing the CARP web services - authentication, file management, data points, and app-specific collections of documents.

CARP Web Service Plugin for Flutter #

A Flutter plugin to access the CARP Web Service API.

pub package

For Flutter plugins for other CARP products, see CARP Mobile Sensing in Flutter.

Note: This plugin is still under development, and some APIs might not be available yet.

Feedback and Pull Requests are most welcome!

Setup #

  1. You need a CARP Web Service host running. See the CARP Web Service API documentation for how to do this. If you're part of the CACHET team, you can use the specified test, staging, and production servers.

  2. Add carp_services as a dependency in your pubspec.yaml file.

In order to show the "Reset Password" button in the login dialog, which will launch the "Reset Password" web page on CARP, add the following parameters on iOS and Android. Note that the "Reset Password" button will not be shown, if the app cannot launch the URL pointing to the web page.

iOS #

Add the following LSApplicationQueriesSchemes entry in your Info.plist file:

	<key>LSApplicationQueriesSchemes</key>
	<array>
  		<string>https</string>
	</array>

Android #

Starting from API 30, Android requires package visibility configuration in your AndroidManifest.xml file in order to launch the "reset password" URL. A <queries> element must be added to your manifest as a child of the root element:

    <!-- To eable that the "reset password" url can be launched -->
    <!-- Provide required visibility configuration for API level 30 and above -->
    <queries>
      <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="https" />
     </intent>
    </queries>

Usage #

import 'package:carp_core/carp_core.dart';
import 'package:carp_mobile_sensing/carp_mobile_sensing.dart';
import 'package:carp_webservices/carp_auth/carp_auth.dart';
import 'package:carp_webservices/carp_services/carp_services.dart';

Configuration #

The CarpService is a singleton and needs to be configured once.

  final String uri = "https://cans.cachet.dk:443";
  CarpApp app;

  app = CarpApp(
    name: 'any_display_friendly_name_is_fine',
    studyId: 'the_study_id',
    studyDeploymentId: 'the_study_deployment_id',
    uri: Uri.parse(uri),
    oauth: OAuthEndPoint(
      clientID: 'the_client_id',
      clientSecret: 'the_client_secret',
    ),
  );

  // Configure the CARP Service with this app.
  CarpService().configure(app);

Note that you need a valid clientID and clientSecret from a CARP Web Service to use it.

Also note that you need the studyId and studyDeploymentId for your study in the CARP Web Service. These can be obtained from an invitation (see below). But if you want to use the CARP Service endpoints directly, you have to specify these IDs in the CarpApp configuration.

The singleton can now be accessed via CarpService().

Authentication #

Basic authentication is using username and password.

CarpUser user;
try {
   user = await CarpService().authenticate(
      username: "a_username", 
      password: "the_password",
   );
} catch (excp) {
   ...;
}

Since the CarpUser can be serialized to JSON, the OAuth token can be stored on the phone. This can then later be used for authentication:

try {
   user = await CarpService().authenticateWithToken(
      username: user.username, 
      token: user.token,
   );
} catch (excp) {
   ...;
}

The user's password can be changed using the changePassword() method:

try {
   user = await CarpService().changePassword(
        currentPassword: 'the_password',
        newPassword: 'a_new_password',
      );
} catch (excp) {
   ...;
}

The plugin also comes with a user interface for authenticating at a CARP server using the authenticateWithDialog() method. For example, the login can be implemeted as part of a TextButton like this:

    child: TextButton.icon(
      onPressed: () => CarpService().authenticateWithDialog(
        context,
        username: 'user@cachet.dk',
      ),
      icon: Icon(Icons.login),
      label: Text(
        'LOGIN',
        style: TextStyle(fontSize: 35),
      ),
   ),

A ConsentDocument can be uploaded and downloaded from CARP.

  try {
    ConsentDocument uploaded = await CarpService().createConsentDocument({
      'text': 'The original terms text.',
      'signature': 'Image Blob',
    });

    ConsentDocument downloaded =
        await CarpService().getConsentDocument(uploaded.id);
  } catch (excp) {
    print(excp);
  }

Data Points #

A DataPointReference is used to manage data points on a CARP web service and have CRUD methods for:

  • post a data point
  • batch upload multiple data points
  • get a data point
  • delete data points
  LightDatum datum = LightDatum(
    maxLux: 12,
    meanLux: 23,
    minLux: 0.3,
    stdLux: 0.4,
  );

  // create a CARP data point
  final CARPDataPoint data =
      CARPDataPoint.fromDatum(study.id, study.userId, datum);

  // post it to the CARP server, which returns the ID of the data point
  int dataPointId =
      await CarpService().getDataPointReference().postDataPoint(data);

  // get the data point back from the server
  CARPDataPoint dataPoint =
      await CarpService().getDataPointReference().getDataPoint(dataPointId);

  // batch upload a list of raw json data points in a file
  final File file = File('test/batch.json');
  await CarpService().getDataPointReference().batchPostDataPoint(file);

  // delete the data point
  await CarpService().getDataPointReference().deleteDataPoint(dataPointId);

Application-specific Collections and Documents #

A CollectionReference is used to manage collections and documents on a CARP web service and have methods for:

  • creating, updating, and deleting documents
  • accessing documents in collections
  // access a document
  //  - if the document id is not specified, a new document (with a new id) is created
  //  - if the collection (users) don't exist, it is created
  DocumentSnapshot document = await CarpService()
      .collection('users')
      .document()
      .setData({'email': username, 'name': 'Administrator'});

  // update the document
  DocumentSnapshot updatedDocument = await CarpService()
      .collection('/users')
      .document(document.name)
      .updateData({'email': username, 'name': 'Super User'});

  // get the document
  DocumentSnapshot newDocument =
      await CarpService().collection('users').document(document.name).get();

  // get the document by its unique ID
  newDocument = await CarpService().documentById(document.id).get();

  // delete the document
  await CarpService().collection('users').document(document.name).delete();

  // get all collections from a document
  List<String> collections = newDocument.collections;

  // get all documents in a collection.
  List<DocumentSnapshot> documents =
      await CarpService().collection('users').documents;

File Management #

A FileStorageReference is used to manage files on a CARP web service and have methods for:

  • uploading a file
  • downloading a file
  • getting a file object
  • getting all file objects
  • deleting a file

When uploading a file, you can add metadata as a Map<String, String>.

  // first upload a file
  final File uploadFile = File('test/img.jpg');
  final FileUploadTask uploadTask = CarpService()
      .getFileStorageReference()
      .upload(uploadFile, {
    'content-type': 'image/jpg',
    'content-language': 'en',
    'activity': 'test'
  });
  CarpFileResponse response = await uploadTask.onComplete;
  int id = response.id;

  // then get its description back from the server
  final CarpFileResponse result =
      await CarpService().getFileStorageReference(id).get();

  // then download the file again
  // note that a local file to download is needed
  final File downloadFile = File('test/img-$id.jpg');
  final FileDownloadTask downloadTask =
      CarpService().getFileStorageReference(id).download(downloadFile);
  int responseCode = await downloadTask.onComplete;

  // now get references to ALL files in this study
  final List<CarpFileResponse> results =
      await CarpService().getFileStorageReference(id).getAll();

  // finally, delete the file
  responseCode = await CarpService().getFileStorageReference(id).delete();

Deployments #

A core notion of CARP is the Deployment subsystem. This subsystem is used for accessing deployment configurations, i.e. configurations that describe how data sampling in a study should take place. The CARP web service have methods for:

  • getting invitations for a specific accountId, i.e. a user - default is the user who is authenticated to the CARP Service.
  • getting a deployment reference, which then can be used to query status, register devices, and get the deployment specification.
  // This example uses the
  //  * CarpDeploymentService
  //  * CarpParticipationService
  // 
  // To use these, we first must configure them and authenticate.
  // However, the [configureFrom] method is a convinient way to do this based
  // on an existing service, which has been configured.

  CarpParticipationService().configureFrom(CarpService());
  CarpDeploymentService().configureFrom(CarpService());

  // get invitations for this account (user)
  List<ActiveParticipationInvitation> invitations =
      await CarpParticipationService().getActiveParticipationInvitations();

  // get a deployment reference for this master device
  DeploymentReference deploymentReference =
      CarpDeploymentService().deployment('the_study_deployment_id');

  // get the status of this deployment
  StudyDeploymentStatus status = await deploymentReference.getStatus();

  // register a device
  status = await deploymentReference.registerDevice(deviceRoleName: 'phone');

  // get the master device deployment
  MasterDeviceDeployment deployment = await deploymentReference.get();

  // mark the deployment as a success
  status = await deploymentReference.success();

There is also support for shwing a modal dialog for the user to select amongst several invitations. This is done using the getStudyInvitation method, like this:

    ActiveParticipationInvitation invitation = await CarpService().getStudyInvitation(context);
    print('Selected CARP Study Invitation: $invitation');

Features and bugs #

Please file feature requests and bug reports at the issue tracker.

License #

This software is copyright (c) Copenhagen Center for Health Technology (CACHET) at the Technical University of Denmark (DTU). This software is made available 'as-is' in a MIT license.

0
likes
80
pub points
74%
popularity

Publisher

verified publishercachet.dk

Flutter API for accessing the CARP web services - authentication, file management, data points, and app-specific collections of documents.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

carp_core, carp_mobile_sensing, carp_serializable, flutter, form_field_validator, http, http_parser, json_annotation, meta, retry, url_launcher, uuid

More

Packages that depend on carp_webservices