Skip to main content

SDK for ReactNative

React Native documentation for Android/iOS apps

SDK Guide

This SDK will help you create your training app using heart rate sensors, the following steps cover the basic scenario of SDK usage.

SDK First steps

  1. You have to request an account.
  2. You must install and configure the SDK [Setup environment](#Setup environment)
  3. Read about the entities and rules
    1. User Entity
    2. Sensor Entity
    3. Training definition
  4. Create a User and set his information
  5. Create a Training
  6. Paint the Training
  7. Handle additional scenarios

User Entity

A User

Sensor Entity

A Sensor

Training Entity

A Training:

  • Is the exercise activity recorded with heart rate monitoring
  • Has properties
  • Has records of
    • Heart rate
    • Steps/Jumps
    • Cycling
  • Has summaries of the training and from the records

Create a User and set his information

  1. If you don't have a User, you can create a User

  2. When you create a User you'll get a user_uuid,

    1. This uuid is required to perform every action over the user
  3. With the user created you must set his basic info with updateInformation

  4. Before starting any training for the User you must fill his physiological variables with updatePhysiologicalVariables

  5. At this point the User profile is completed, you can update his profile later if required.

  6. Now you must call getUser to retrieve the User data from the Server and store it on the local database.

Create a Training

Training requires:

  • A User
  • A training type
  • A Sensor
  1. The User was already created and filled in on Create a User and set his information

  2. The Training Type: There are multiple available Training Types available, the procedure to select one for Training is as follows

    1. Get the Training types list with getTrainingTypes from UseRookTrainings
    2. Select one from the returned list
  3. The Sensor: The easiest way to get a Sensor is through the Trainer Hook:

    1. Start the Sensors discovery with startScan from useSensorScanner, this will retrieve a list of ``.
    2. Select one from the list discoveredSensors
  4. Now that we have the three elements User, Sensor, and Training Type

    1. Create a Training with useRookTrainer
    2. Connect the Sensor to the Training with connectSensor from useRookTrainer
    3. Start the Training with StartTraining from useRookTrainer
    4. The Hook will store the measurements in the database.
    5. You can read the useRookTrainer props for the Training Data that you want to display.
  5. You can finish the Training with FinishAndUpload which will upload the training and upload it to the server.

  6. When you want to show the User Trainings List you must:

    1. Get the User's Trainings with retrieveUserTrainings
  7. If you want to show the information of one of the returned Trainings you can get its information with getTrainingInformation

SDKs

The SDK is divided into three packages available in npmjs

Setup environment

Required tools.

  • Android Studio
  • Xcode
  • NodeJS
  • React Native CLI
  • Yarn

Install dependencies

  1. Install dependencies
yarn add yarn add react-native-device-info @nozbe/watermelondb react-native-ble-manager rook-core rook-bluetooth
note

Depending on your project dependencies, you may need to install the following manually:

  • yarn add @types/hoist-non-react-statics
  • yarn add @types/react
  • yarn add @babel/preset-env
info

Currently, Expo Go is not supported due to preference conflict with Expo and react-native-device-info, we're working on that.

note

If you have any issues installing the React-native-ble-manager, follow their instructions

  1. Set Android version requirements
android/build.gradle
buildscript {
ext {
...
buildToolsVersion = "31.0.0"
minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 31
kotlinVersion = '1.6.10'
...
}
dependencies {
...
classpath("com.android.tools.build:gradle:7.2.1")
...

}




RookMotion Core

RookMotion Core is a React Hooks library that will help you with the following tasks:

  • For user:
    • Create a new User and retrieve his uuid
    • Set/Retrieve User's information
    • Set/Retrieve User's physiological variables
  • For trainings
    • Discover nearby bluetooth devices
    • Start a training with the selected device
    • Store the training records and summaries
    • Upload the training when finished
  • Stats and history.
    • Retrieve User's trainings from Server
    • Retrieve User's historical training summaries
    • Retrieve User's historical physiological variables

Hooks

Available hooks are:



Configuration

info

RookMotion SDKs require auth credentials. If you don't have yours, please read this.

  1. Add RookWrapper provider in the highest position of your components tree.
    1. RookWrapper handles the RookMotion auth credentials for the module.
import { RookWrapper } from 'rook-core';

...

<RookWrapper
config={{
authorization: 'YOUR-BEARER-TOKEN',
tokenLevel: 'YOUR-CLIENT-TOKEN',
url: 'BASE URL SANDBOX OR PRODUCTION',
}}>
<YOUR-COMPONENTS />
</RookWrapper>


useRookUser

Description Handles the User creation/deletion, User’s Sensors, Info and Physiological variables.

Definition

`useRookUser: () => useRookUserTools`

Import

import {useRookUser} from 'rook-core';

Return

  • @return bool ready - Indicates the hook is initialized and ready to use.

User

Create User
 registerUserInApi: (props: registerUserInApiProps) => Promise<string>;
  • Creates a new User in RookMotion Server
  • Returns a user_uuid required to execute any User operation
  • If the user email already exists, it only returns user_uuid
  • @param props registerUserInApiProps.
  • @returns string - user_uuid

Props

  1. registerUserInApiProps.email: user_email

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const RegisterUser = () => {
const isDarkMode = useColorScheme() === 'dark';
const [email, setEmail] = useState('');

const {registerUserInApi} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (!email.trim()) {
console.log( 'Enter a valid email')
return;
}

console.log('signing up')

try {
const response = await registerUserInApi({email});

if (response) {
console.log(`User was created correctly with uuid: ${response}`)
} else {
console.log("Error while creating user")
}
} catch (error) {
console.log("Error while creating user")
}
};

return (
<View>
<Text
fontSize="xl"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Register User
</Text>

<Input
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
placeholder="user email"
onChangeText={text => setEmail(text)}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<View>
<Button title = 'Register User's onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});

Delete User
deleteAccount: (props: deleteAccountProps) => Promise<boolean>;
  • Delete user on RookMotion Server
  • @param props {deleteAccountProps}.
  • @returns True if the account was deleted or if provided uuid does not exist, false on error.
  1. props.user_uuid: user_uuid
danger

This will PERMANENTLY delete the user Entity, its information, and trainings.

note

This is used Use when your user has requested to delete his information permanently.

tip

After successful deletion, clean up the local data:

  1. logout() on useRookMotionSession() hook.
  2. Clean up any remaining data that you have stored.

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button, View} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const DeleteAccount = () => {
const isDarkMode = useColorScheme() === 'dark';
const [uuid, setUUID] = useState('');
const {deleteAccount} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (!uuid.trim()) {
console.log('Enter a valid email')
return;
}

console.log('eliminando');

try {
const response = await deleteAccount({user_uuid: uuid});

if (response) {
console.log('the user account was deleted')
} else {
console.log('cannot delete the user account')
}
} catch (error) {
console.log("We can't verify your uuid");
}
};

return (
<View>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Delete account
</Text>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
User uuid
</Text>

<TextInput
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
placeholder="user uuid"
onChangeText={text => setUUID(text)}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<View>
<Button title = 'Delete' onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});

User status
getUserStatusFromApi: (props: getUserStatusFromApiProps) => Promise<UserStatus>;
  • Check if the user email exists on RookMotion Server
  • If the user exists, it retrieves user’s info inside UserStatus
  • @param props {@link getUserStatusFromApiProps}.
  • @returns {@link UserStatus}.
  1. props.email: user_email
  2. UserStatus.user_uuid: user_uuid
  3. UserStatus.active: True if user is registered in web service.
  4. UserStatus.profile_filled_at: Timestamp when the user filled in his basic info
tip

Before creating a user, you can verify if the user already exists with getUserStatusFromApi.

tip

You can find the user_uuid from a user email already registered using getUserStatusFromApi

tip

UserStatus.profile_filled_at is intended to detect if you need to ask the user to fill in or update his information.

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const UserStatus = () => {
const isDarkMode = useColorScheme() === 'dark';
const [email, setEmail] = useState('');

const {getUserStatusFromApi} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (!email.trim()) {
console.log('Enter a valid email');
return;
}

console.log('consultando', duration: 3000);

try {
const response = await getUserStatusFromApi({email});

if (response.active) {
console.log(`The user exists with uuid: ${response.user_uuid}`);
} else {
console.log('User doesn't exists);
}
} catch (error) {
console.log("We can't verify your email");
}
};

return (
<View>
<Text
fontSize="xl"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Get user status
</Text>

<Input
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
placeholder="user email"
onChangeText={text => setEmail(text)}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<View>
<Button title = 'Verify Status' onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});

Get user from Server
getUser: (props: getUserProps) => Promise<User>;
  • Retrieves user information and physiological variables

  • Form RookMotion Server as first attempt and stores the info on local database

  • From local database when internet is not available or the requests fails

  • @param props {@link getUserProps}

  • @returns A {User} instance associated with provided uuid.

  • @throws error if the information is not available from any source

    1. props.user_uuid: user_uuid
    2. user: user

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button, View} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const UserInformation = () => {
const isDarkMode = useColorScheme() === 'dark';
const [id, setID] = useState('');
const {getUser} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (!id.trim()) {
console.log('Enter a valid variables')
return;
}

console.log('updating');

try {
const response = await getUser({user_uuid: id});

if (response) {
console.log(`User has the uuid: ${response.user_uuid} and email ${response.email}`);
} else {
console.log('We cannot get the user');
}
} catch (error) {
console.log('We cannot get the user');
}
};

return (
<View>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
View User
</Text>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
user uuid
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setID(text)}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<View>
<Button title = 'View User's onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});

Get user from local database
getUserFromDatabase: () => Promise<User>;
  • Retrieves user information and physiological variables from local database
  • @returns {@link User}.
  • @throws error if information is not available
  1. user: user_definition
note

Similar to getUser but from local database only

info

Make sure to call logout() on useRookMotionSession() hook, every time the user logs out from your app, this will clean the User information from database. otherwise, the info will remain in the database.

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button, View} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const UserInformationFromDatabase = () => {
const isDarkMode = useColorScheme() === 'dark';
const {getUserFromDatabase} = useRookUser();

const getInformationFromDatabase = async (): Promise<any> => {
try {
const response = await getUserFromDatabase();

if (response) {
console.log(`the user has the next uuid: ${response.user_uuid} and email ${response.email}`);
} else {
console.log('No user in database');
}
} catch (error) {
console.log("getUserFromDatabase error: ${error}");
}
};

return (
<View>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
View User in Database
</Text>

<View>
<Button title = 'View User' onPress={getInformationFromDatabase} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});


User information

User available information: User information

Update user information
 updateInformation: (props: updateInformationProps) => Promise<User>;
  • Updates User's information in RookMotion Server
  • Updates User's information in local database
  • @param props {@link updateInformationProps}.
  • @returns The new {@link User} with the updates applied.
  1. props.user_uuid: user_uuid
  2. props.updateInformationProps: user_information
info

If internet is not available, it will update information only on local database. When the internet is available, you must try to push the information again.

Example


import React, {useState} from 'react';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {StyleSheet, useColorScheme, Text, Input, Button} from 'react-native';
import {useRookUser} from 'rook-core';

export const UpdateUserInformation = () => {
const isDarkMode = useColorScheme() === 'dark';
const [data, setData] = useState({
uuid: '',
name: '',
pseudonym: '',
lastName1: '',
lastName2: '',
birthday: new Date().toString(),
sex: '',
});
const {updateInformation} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (
!data.uuid.trim() ||
!data.name.trim() ||
!data.pseudonym.trim() ||
!data.lastName1.trim()
) {
console.log( 'Enter a valid variables');
return;
}

console.log('updating');

try {
const response = await updateInformation({
user_uuid: data.uuid,
information: {
name: data.name,
pseudonym: data.pseudonym,
last_name_1: data.lastName1,
last_name_2: data.lastName2 || '---',
birthday, // format: YYYY/MM/DD
sex: data.sex === 'male' ? 'male' : 'female',
},
});

if (response) {
console.log( `the user was register updated with the next uuid: ${response.user_uuid}`);
} else {
toast.show('We cannot update de user');
}
} catch (error) {
console.log("We can't update the information");
}
};

return (
<View>
<Text
fontSize="xl"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Update Variables
</Text>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
user uuid
</Text>
<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setData(prev => ({...prev, uuid: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Name
</Text>
<TextInput
placeholder="Rook"
onChangeText={text => setData(prev => ({...prev, name: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Pseudonym
</Text>
<TextInput
placeholder="80"
onChangeText={text => setData(prev => ({...prev, pseudonym: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Last Name 1
</Text>
<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setData(prev => ({...prev, lastName1: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Last Name 2
</Text>
<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setData(prev => ({...prev, lastName2: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Birthday
</Text>
<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setData(prev => ({...prev, birthday: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
<View
justifyContent="center"
alignItems="center"
space={4}
marginTop={4}>
<Text
fontSize="md"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Female or male
</Text>
<TextInput
placeholder="80"
onChangeText={text => setData(prev => ({...prev, sex: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>
</View>
;
<View>
<Button title = 'Update User' onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});


User Physiological variables

Available variables are: user_physiological_variables_definition

info

Physiological variables are required so that RookMotion can perform training calculations for each user. If none are provided, training calculations aren't guaranteed to be correct.

note

Every time physiological variables are updated, a new entry is made on RookMotion Database instead or replaced, so It's possible to retrieve a historical list of variables.

Set User Physiological variables

updatePhysiologicalVariables: (props: updatePhysiologicalVariablesProps) => Promise<User>;
  • Set User's {@link UserPhysiologicalVariables} in RookMotion Server.

  • A new entry is generated on each request so that historical variables are created related to RookMotion Server.

  • Stores the variables on the local Database as the newest values; no history is created on the local database.

  • @param props {UserPhysiologicalVariables}.

  • @returns {user} with the updated variables applied.

    1. props.user_uuid: user_uuid
    2. props.physiological_variables: UserPhysiologicalVariables
info

If internet is not available, it will set the information only on local database. When the internet is available, you must try to push the data again.

Example

import React, {useState} from 'react';
import {StyleSheet, useColorScheme, Text, TextInput, Button, View} from 'react-native';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useRookUser} from 'rook-core';

export const UpdateUserVariables = () => {
const isDarkMode = useColorScheme() === 'dark';
const [data, setData] = useState({
user: '',
height: '',
weight: '',
restingHR: '',
});
const {updatePhysiologicalVariables} = useRookUser();

const verifyStatus = async (): Promise<any> => {
if (
!data.user.trim() ||
Number.isNaN(Number(data.height)) ||
Number.isNaN(Number(data.weight)) ||
Number.isNaN(Number(data.restingHR))
) {
console.log('Enter a valid variables');
return;
}

console.log('updating');

try {
const response = await updatePhysiologicalVariables({
user_uuid: data.user,
physiological_variables: {
weight: data.weight,
height: data.height,
resting_heart_rate: data.restingHR,
},
});

if (response) {
console.log(`the user was register correctly with the next uuid: ${response.user_uuid}`);
} else {
console.log('We cannot register de user');
}
} catch (error) {
console.log("We can't update variables");
}
};

return (
<View>
<Text
fontSize="xl"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Update Variables
</Text>

<Text
fontSize="md"
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
user uuid
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setData(prev => ({...prev, user: text}))}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Weight
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text =>
setData(prev => ({...prev, weight: Number(text).toString()}))
}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Height
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text =>
setData(prev => ({...prev, height: Number(text).toString()}))
}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Resting HR
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text =>
setData(prev => ({...prev, restingHR: Number(text).toString()}))
}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<View>
<Button title = 'Update User's onPress={verifyStatus} />
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});
Retrieve User Physiological variables
getPhysiologicalVariablesByPeriod: (props: getPhysiologicalVariablesByPeriodProps) => Promise<PhysiologicalVariablesByPeriod>;
  • Retrieves {@link getPhysiologicalVariablesByPeriodProps} between a range of dates in the format YYYY-MM-DD.
  • Form RookMotion Server as first attempt and stores the last values on local database
  • @param props {@link getPhysiologicalVariablesByPeriodProps}.
  • @returns {@link PhysiologicalVariablesByPeriod}.
  1. props.user_uuid: user_uuid
  2. props.from_date: Starting date of the period (YYYY-MM-DD)
  3. props.to_date: Ending date of the period (YYYY-MM-DD)
  4. props.page: The page to fetch
  5. props.type: PhysiologicalVariableType
note

To get the user most recent variables, you must use the variables with the newest timestamp.

note

Each call to this method retrieves one variable type (weight, height, or resting heart rate). If you want the three of them, you'll need to call the method three times.

Example

import React, {useState} from 'react';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {useColorScheme, StyleSheet, View, Text, Button, TextInput} from 'react-native';
import {useRookUser, PhysiologicalVariableType} from 'rook-core';

export const UserVariablesInPeriod = () => {
const isDarkMode = useColorScheme() === 'dark';

const [date, setDate] = useState(');
const [secondDate, setSecondDate] = useState(');
const [start, setStart] = useState('');
const [end, setEnd] = useState('');
const [id, setID] = useState('');
const [data, setData] = useState<any>({});

const {getPhysiologicalVariablesByPeriod} = useRookUser();

const verifyVariables = async (): Promise<any> => {
try {

const props = {
user_uuid: id,
from_date: start, // Format: YYYY-MM-DD
to_date: end, // Format: YYYY-MM-DD
page: 1,
};

console.log('fetching . . .');

const [w, h, r] = await Promise.all([
getPhysiologicalVariablesByPeriod({
...props,
type: PhysiologicalVariableType.WEIGHT,
}),
getPhysiologicalVariablesByPeriod({
...props,
type: PhysiologicalVariableType.HEIGHT,
}),
getPhysiologicalVariablesByPeriod({
...props,
type: PhysiologicalVariableType.RESTING_HEART_RATE,
}),
]);

console.log(w.data, h.data, r.data);

setData({
weight: w.data[0]?.value || 0,
height: h.data[0]?.value || 0,
hr: r.data[0]?.value || 0,
});
} catch (error) {
console.log('We cannot show the info')
}
};

return (
<View>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Get variables in period
</Text>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
user uuid
</Text>

<TextInput
keyboardType="numeric"
placeholder="80"
onChangeText={text => setID(text)}
style={{color: isDarkMode ? Colors.white : Colors.black}}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Starting date
</Text>

<TextInput
onChangeText={text => setDate(text)}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
End date
</Text>

<TextInput
onChangeText={endDate => setSecondDate(endDate)}
/>

<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
weight: {data.weight}
</Text>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
height: {data.height}
</Text>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
hr: {data.hr}
</Text>

<View>
<Button
title = 'Verify Status'
onPress={verifyVariables}
/>
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});

User Indexes

note

User indexes have no direct usage for you, but are required to be keep on database for the training calculations.

Retrieve User Indexes
 syncIndexes: (props: syncIndexesProps) => Promise<IndexesSyncResult>;
  • Retrieve user indexes from RookMotion Server
  • Stores the indexes in Database.
  • @param props {syncIndexesProps}.
  • @returns {IndexesSyncResult}.
  1. props.user_uuid: user_uuid
tip

Sync user indexes periodically to keep them updated, ideally before starting a training.

tip

Sync user indexes when the user updates their {@link UserPhysiologicalVariables} or {@link UserAttributes}


Definitions

user_definition

The User

user_uuid_definition
  • user_uuid (string): Unique user identifier UUID4, it is assigned by RookMotion Server on user creation.
user_email_definition
  • user_email (string): User's email; it's unique, according to RFC 5322.
user_information_definition
  1. information.name: User's name
  2. information.pseudonym: User's pseudonym or nickname
  3. information.last_name_1: User's first last name
  4. information.last_name_2: User's second last name
  5. information.birthday: User's birthday (YYYY-MM-DD)
  6. information.sex: User's sex (male || female)
info

sex and birthday are important for training calculations, so real values must be used

user_physiological_variables_definition
  • weight (string): User's weight in kg. (Range: 40-180).
  • height (string): User's height in cm. (Range: 120-220).
  • resting_heart_rate (string): User's resting_heart_rate, (Range: 40-99) (Default: 60).
info

Physiological variables are required so that RookMotion can perform training calculations for each user. If none are provided, training calculations aren't guaranteed to be correct.

user_physiological_variables_types_definition
  • PhysiologicalVariableType.WEIGHT (enum element): Request or returned array are weight values
  • PhysiologicalVariableType.HEIGHT (enum element): Request or returned array are height values
  • PhysiologicalVariableType.RESTING_HEART_RATE (enum element): (enum element): Request or returned array are rest_hr values
user_historical_physiological_variables_definition
  • PhysiologicalVariablesByPeriod.type: PhysiologicalVariableType.
  • PhysiologicalVariablesByPeriod.data: array(PhysiologicalVariable).
  • PhysiologicalVariablesByPeriod.links: Global.Links: Pagination page url.
  • PhysiologicalVariablesByPeriod.meta: Global.Meta: Request metadata, includes pagination counter.


useRookSensor

Description

Handles the training functionalities and Manages the User's sensors.

  • Add User's sensors to Server
  • Retrieve from Server

Definition

`useRookSensors: () => useRookSensorsTools;`

Import

import {useRookSensor} from 'rook-core';

Return

ready

  • Indicates if the hook is ready.

User Sensors

Sensors are stored in RookMotion Server related to a user. They are required for trainings.

Add Sensor to user

saveSensor: (props: saveSensorProps) => Promise<Sensor>;

  • Add a Sensor to the user on the RookMotion Server

  • props: Indicates the user and the Sensor

    1. props.userUUID: user_uuid
    2. props.name: sensor_name
    3. props.mac: sensor_mac

Example

import React, {useState} from 'react';
import {
SafeAreaView,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
} from 'react-native';
import {useRookSensors} from 'rook-core';


export const Sensors = () => {
const {ready, saveSensor} = useRookSensors();

const [userUUID, setUserUUID] = userState('');
const [sensor, setSensor] = useState({
sensor_name: ''
sensor_mac: ''
});

const keepSensor = async (): Promise<any> => {

try {

const resp = await saveSensor({
userUUID: userUUID,
name: sensor.sensor_name,
mac: sensor.sensor_mac,
});

if (resp) {
console.log('saved successfully');
}
else {
console.log('could not save the sensor');
}
}
catch (error) {
console.log(error)
}

};

return (
<SafeAreaView>
<TouchableHighlight onPress={keepSensor}>
<Text>Save</Text>
</TouchableHighlight>

<Text>User uuid</Text>
<TextInput
style={ styles.input }
onChangeText={text => setUserUUID(text)}
/>

<Text>Sensor Name</Text>
<TextInput
style={{...styles.input, color: colors.text}}
onChangeText={text =>
setSensor((prev: any) => ({...prev, sensor_name: text}))
}
/>

<Text>Sensor MAC</Text>
<TextInput
style={{...styles.input, color: colors.text}}
onChangeText={text =>
setSensor((prev: any) => ({...prev, sensor_mac: text}))
}
/>

</SafeAreaView>
);
};

const styles = StyleSheet.create({
input: {
marginTop: 10,
height: 50,
borderWidth: 1,
borderStyle: 'solid',
borderRadius: 5,
},
});
Get user sensors

getSensors: (props: getSensorsProps) => Promise<SensorsFetchResponse>;

  • Retrieve user sensors from RookMotion Server
  • @return SensorsFetchResponse
  1. props.userUUID: user_uuid
  2. props.page: Page for the API request, commonly it's limited to one page, so use 1.
  3. SensorsFetchResponse.data: Array(sensor)
  4. SensorsFetchResponse.links: Request pagination link
  5. SensorsFetchResponse.meta: Request response metadata.

Example

import React, {useState} from 'react';
import {
FlatList,
SafeAreaView,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
} from 'react-native';
import {Sensor, useRookSensors} from 'rook-core';

export const Sensors = () => {
const {ready, getSensors} = useRookSensors();

const [userUUID, setUserUUID] = userState('');
const [data, setData] = useState<Sensor[]>([]);

const handleView = async (): Promise<any> => {
if (!ready) {
console.log('no ready');
return;
}

const resp = await getSensors({
page: 1,
userUUID: userUUID,
});

setData(resp ? resp.data : []);
};

return (
<SafeAreaView>
<TouchableHighlight onPress={handleView}>
<Text>Ver sensores</Text>
</TouchableHighlight>

<Text>User uuid</Text>
<TextInput
style={ styles.input }
onChangeText={text => setUserUUID(text)}
/>
<FlatList
data={data}
keyExtractor={item => item.sensor_uuid}
renderItem={({item}) => (
<Text>
{item.sensor_uuid} - {item.sensor_name}
</Text>
)}
/>
</SafeAreaView>
);
};

const styles = StyleSheet.create({
input: {
marginTop: 10,
height: 50,
borderWidth: 1,
borderStyle: 'solid',
borderRadius: 5,
},
});

Remove Sensor from user

deleteSensor: (props: deleteSensorProps) => Promise<boolean>;

  • Remove a Sensor from the user on the RookMotion Server
  • props: Indicates the user and the Sensor
  1. props.userUUID: user_uuid 2props.name: sensor_uuid

Example

import React, { useState } from 'react'
import { SafeAreaView, Button } from 'react-native'
import { useRookPreference } from 'rook-core'

export const Component = () => {

const { removeLastUsedSensor } = useRookPreference()

const deleteLastSensor = (): Promise<any> => {

try {

const response = await removeLastUsedSensor();

if (response) {
console.log('removed successfully');
}
else {
console.log('could not remove the Sensor');
}

}
catch(error) {
console.log(error);
}

}

return (
<SafeAreaView>
<Button title = 'remove last Sensor' onPress={ deleteLastSensor } />
</SafeAreaView>
)
}

Definitions

sensor_uuid_definition
  • sensor_uuid (string): Unique identifier UUID4, it is assigned by RookMotion Server on Sensor creation.
sensor_name_definition
  • sensor_name (string): Sensor discoverable name usually (brand+ID) e.g. RookC2 123456 it's defined by manufacturer.
sensor_mac_definition
  • sensor_mac (string): Sensor Bluetooth MAC. Defined by the manufacturer.
user_sensor_definition

User Sensor is similar to Sensor but comes from the Server and has the Sensor to user relation.



useRookPreference

Description This hook handles User's preferences

  • Last used Sensor
  • @return bool ready - Indicates the hook is initialized and ready to use.

Definition

`useRookPreferences: () => useRookPreferencesTools;`

Import

import {useRookPreferences} from 'rook-core';

Preference: Last Used Sensor

tip

Last used Sensor is a preference useful to start trainings without asking again for the user to select a Sensor.

Set Last Used Sensor

setLastUsedSensor: (props: setLastUsedSensorProps) => Promise<boolean>

Get Last Used Sensor

getLastUsedSensor: () => Promise<LastUsedSensor>;

  • Retrieves the last Sensor used
  • returns Sensor
  1. Sensor: Sensor

Example

import React, { useState, useEffect } from 'react'
import { SafeAreaView, Text, Input, Button } from 'react-native'
import { LastUsedSensor, useRookPreference } from 'rook-core'

export const Component = () => {

const [sensor, setSensor] = useState<LastUsedSensor>({
sensor_uuid: ''
sensor_mac: ''
sensor_name: ''
})

const { ready, getLastUsedSensor } = useRookPreference();

useEffect(() => {

if (ready) fetchSensor();

}, [ready])

const fetchSensor = async (): Promise<any> => {
try {

const response = await getLastUsedSensor();
setSensor( response );

}
catch(error) {
console.log(error);
}
}

return (
<SafeAreaView>
<Text>Sensor uuid: { sensor.sensor_uuid }</Text>
<Text>Sensor MAC: { sensor.sensor_mac }</Text>
<Text>Sensor name: { sensor.sensor_name }</Text>
</SafeAreaView>
)
}

Preference: Remove Last Used Sensor

removeLastUsedSensor: () => Promise<boolean>;

  • Removes the lastUsedSensor from preferences
Preference: Clear all preferences

clearPreferences: () => Promise<boolean>;

  • Clears the collection of preferences

Example

import React, { useState } from 'react'
import { SafeAreaView, Button } from 'react-native'
import { useRookPreference } from 'rook-core'

export const Component = () => {

const { clearPreferences } = useRookPreference()

const deleteLastSensor = (): Promise<any> => {

try {

const response = await clearPreferences();

if (response) {
console.log('removed successfully');
}
else {
console.log('could not remove the collection');
}

}
catch(error) {
console.log(error);
}

}

return (
<SafeAreaView>
<Button title = 'remove the collection' onPress={ saveSensor } />
</SafeAreaView>
)
}

Definitions

sensor_definition
note

Sensor objects are discovered by the hook useSensorScanner from the rook-bluetooth package

Example

import React, { useState } from 'react'
import { SafeAreaView, Text, Input, Button } from 'react-native'
import { LastUsedSensor, useRookPreference } from 'rook-core'

export const Component = () => {

const [sensor, setSensor] = useState<LastUsedSensor>({
sensor_uuid: ''
sensor_mac: ''
sensor_name: ''
})

const { setLastUsedSensor } = useRookPreference();

const saveSensor = async (): Promise<any> => {
try {

const response = await setLastUsedSensor( sensor );

if (response) {
console.log('saved successfully');
}
else {
console.log('could not save the sensor');
}

}
catch(error) {
console.log(error);
}
}

return (
<SafeAreaView>
<Text>Sensor uuid</Text>
<Input onChangeText={
text => setSensor(prev => ({ ...prev, sensor_uuid: text }))
}
/>
<Text>Sensor MAC</Text>
<Input onChangeText={
text => setSensor(prev => ({ ...prev, sensor_mac: text }))
}
/>
<Text>Sensor name</Text>
<Input onChangeText={
text => setSensor(prev => ({ ...prev, sensor_name: text }))
}
/>
<Button title = 'Save' onPress={ saveSensor } />
</SafeAreaView>
)
}



useRookTrainings

Description

This hook handles

  • The User's trainings

    • Information
    • Deletion
  • The available trainings types.

  • props: Training Configuration

  1. props.bluetoothConfig.emitter: Notify events during the training:
    1. BleManagerDiscoverPeripheral
    2. BleManagerStopScan
    3. BleManagerDisconnectPeripheral
    4. BleManagerDidUpdateValueForCharacteristic
  2. props.bluetoothConfig.showAlerts: Show alerts notifications
  3. `props.trainingConfig.trainingType
    1. props.trainingConfig.trainingType.training_type_uuid: training_type_uuid assigned by RookMotion Server.
    2. props.trainingConfig.trainingType.training_name: training_type_name assigned by RookMotion Server.
    3. props.trainingConfig.trainingType.use_steps: Indicates if the training type records steps.
    4. props.trainingConfig.trainingType.use_heart_rate: Indicates if the training records heart rate.
    5. props.trainingConfig.trainingType.use_gps: Indicates if the gps records heart rate.
    6. props.trainingConfig.trainingType.use_cycling: Indicates if the training records cycling
  4. props.trainingConfig.withBicycleRecords: Indicates if the training cycling records .
info

To perform a training, an existing user must be already on local using: useRookUser.getUser()

Definition

`useRookTrainer = (props: useRookTrainerProps): useRookTrainerTools`

Import

import { useRookTrainer } from 'rook-core'

Return

  • ready: boolean: Indicates if the hook is ready.
  • duration: number: Current training duration (seconds)
  • start: UTC datetime when the training started
  • hrDerivedData: RMHrDerivedRecord; Heart rate records.
    • RMHrDerivedRecord.timestamp: UTC datetime of the HR measurement
    • RMHrDerivedRecord.heart_rate: Heart rate measurement record (bpm)
    • RMHrDerivedRecord.calories: Calories counter record (kcal)
    • RMHrDerivedRecord.effort: Heart Rate Effort record (%)
    • RMHrDerivedRecord.heart_rate_variability: Indicates the heart_rate_variability of the user
  • batteryLevel: number: Sensor battery level
  • steps: StepsData; Steps records.
    • StepsData.steps: Steps counter (steps)
    • StepsData.cadence: Steps cadence (steps/min)

// For remote classes only

  • remoteUsers: List of users training in the same remote class
  • remoteRemainSeconds: Remaining seconds of the remote class
  • classFinished: Has the remote class finished?
  • userBanned: Is the user banned or removed from the remote class?

Training actions

Connect Sensor

connectSensor: (sensor: BLPeripheral) => Promise<boolean>;

  • Connects to Sensor to perform a training
  • Uploads the Sensor to RookMotion Server using saveSensor
  • @param props.sensor (BLPeripheral)
  • @return success (bool)
  1. props.sensor: Sensor to connect returned by useRookScanner.startScanand useRookScanner.discoveredSensors from rook-bluetooth
note

Must be called before to start a training

Start training

startTraining: () => Promise<boolean>;

  • Starts the training previously initialized
info

Additionally to the training configuration, a connection with a Sensor had to be established before with connectSensor

Re-start training

startPendingTraining: (props: startPendingTrainingProps) => Promise<boolean>;

  • Re-starts an unfinished training
  1. props.start: Datetime key of the training to be resumed.
Pause training

pauseTraining: () => void;

  • Pause the current training.
Resume training

resumeTraining: () => void;

  • Resume a paused training
Cancel training

cancelTraining: () => Promise<boolean>; -

  • Cancel the current training and clears the related data.
caution

If a training is canceled all the training information will be lost.

Finish training

finishTraining: () => Promise<void>;

  • Finish the current training
  • A training finish time is stored on database
info

This will finish the training, but won't be uploaded. A call to uploadTrainings will be required to upload the training.

Finish training and upload

finishAndUploadTraining: () => Promise<boolean>;

  • Finish the current training
  • A training finish time is stored on database
  • The training is uploaded to RookMotion Server

Additional measurements

Add cycling record

addBicycleRecord: (props: addBicycleRecordProps) => Promise<boolean>

  • Insert a cycling record for the current timestamp to the training
  • Useful for Apps with bicycle measurements
  1. props.cadence: Current cycling cadence (rpm)
  2. props.resistance: Current cycling resistance
  3. props.power: Current cycling power (W)

Definitions

training_stages_definition

A training has the following stages:

  1. The training is started when [Start training](#Start training) is executed.
    1. start property is set to the start time
    2. end property is null.
    3. uploaded_at property is null
  2. A training is Paused or unfinished when [Pause training](#Pause training) is executed or the training is interrupted
    1. start property was set to the start time
    2. end property is null.
    3. uploaded_at property is null
  3. A training is Resumed when [Resume training](#Resume training) is executed
    1. start property was set to the start time
    2. end property is null.
    3. uploaded_at property is null
  4. The training is finished when [Finish training](#Finish training) is executed
    1. start property was set in the previous stages
    2. end property is set to the finished time
    3. uploaded_at property is null
  5. The training is uploaded when Upload trainings is executed
    1. start property was set in the previous stages.
    2. end property was set in the previous stages.
    3. uploaded_at property is null
training_summary_type

Every training has records obtained each certain time, and we create summaries of that records such like:

  • hr_max
  • hr_min
  • effort_max
  • effort_avg
  • training_duration

A training summary type is composed of

  • name (string): e.g. hr_max
  • uuid (string): Unique summary type identifier UUID4, it is assigned by RookMotion Server, and they're fixed.


useRookTrainer

Description

This hook handles the training functionalities:

  • Bluetooth Sensor interactions

  • Training measurements storage

  • Training summaries generation and storage

  • props: Training Configuration

  1. props.bluetoothConfig.emitter: Notify events during the training:
    1. BleManagerDiscoverPeripheral
    2. BleManagerStopScan
    3. BleManagerDisconnectPeripheral
    4. BleManagerDidUpdateValueForCharacteristic
  2. props.bluetoothConfig.showAlerts: Show alerts notifications
  3. `props.trainingConfig.trainingType
    1. props.trainingConfig.trainingType.training_type_uuid: training_type_uuid assigned by RookMotion Server.
    2. props.trainingConfig.trainingType.training_name: training_type_name assigned by RookMotion Server.
    3. props.trainingConfig.trainingType.use_steps: Indicates if the training type records steps.
    4. props.trainingConfig.trainingType.use_heart_rate: Indicates if the training records heart rate.
    5. props.trainingConfig.trainingType.use_gps: Indicates if the gps records heart rate.
    6. props.trainingConfig.trainingType.use_cycling: Indicates if the training records cycling
  4. props.trainingConfig.withBicycleRecords: Indicates if the training cycling records .
info

To perform a training, an existing user must be already on local using: useRookUser.getUser()

Definition

`useRookTrainer = (props: useRookTrainerProps): useRookTrainerTools`

Import

import { useRookTrainer } from 'rook-core'

Return

  • ready: boolean: Indicates if the hook is ready.
  • duration: number: Current training duration (seconds)
  • start: UTC datetime when the training started
  • hrDerivedData: RMHrDerivedRecord; Heart rate records.
    • RMHrDerivedRecord.timestamp: UTC datetime of the HR measurement
    • RMHrDerivedRecord.heart_rate: Heart rate measurement record (bpm)
    • RMHrDerivedRecord.calories: Calories counter record (kcal)
    • RMHrDerivedRecord.effort: Heart Rate Effort record (%)
    • RMHrDerivedRecord.heart_rate_variability: Indicates the heart_rate_variability of the user
  • batteryLevel: number: Sensor battery level
  • steps: StepsData; Steps records.
    • StepsData.steps: Steps counter (steps)
    • StepsData.cadence: Steps cadence (steps/min)

// For remote classes only

  • remoteUsers: List of users training in the same remote class
  • remoteRemainSeconds: Remaining seconds of the remote class
  • classFinished: Has the remote class finished?
  • userBanned: Is the user banned or removed from the remote class?

Training actions

Connect Sensor

connectSensor: (sensor: BLPeripheral) => Promise<boolean>;

  • Connects to Sensor to perform a training
  • Uploads the Sensor to RookMotion Server using saveSensor
  • @param props.sensor (BLPeripheral)
  • @return success (bool)
  1. props.sensor: Sensor to connect returned by useRookScanner.startScanand useRookScanner.discoveredSensors from rook-bluetooth
note

Must be called before to start a training

note

This will also upload the Sensor to the Server and link it to the User, the returned sensor_uuid will be stored in the local db with the Training

Start training

startTraining: () => Promise<boolean>;

  • Starts the training previously initialized
info

Additionally to the training configuration, a connection with a Sensor had to be established before with connectSensor

Re-start training

startPendingTraining: (props: startPendingTrainingProps) => Promise<boolean>;

  • Re-starts an unfinished training
  1. props.start: Datetime key of the training to be resumed.
Pause training

pauseTraining: () => void;

  • Pause the current training.
Resume training

resumeTraining: () => void;

  • Resume a paused training
Cancel training

cancelTraining: () => Promise<boolean>; -

  • Cancel the current training and clears the related data.
caution

If a training is canceled all the training information will be lost.

Finish training

finishTraining: () => Promise<void>;

  • Finish the current training
  • A training finish time is stored on database
info

This will finish the training, but won't be uploaded. A call to uploadTrainings will be required to upload the training.

Finish training and upload

finishAndUploadTraining: () => Promise<boolean>;

  • Finish the current training
  • A training finish time is stored on database
  • The training is uploaded to RookMotion Server

Additional measurements

Add cycling record

addBicycleRecord: (props: addBicycleRecordProps) => Promise<boolean>

  • Insert a cycling record for the current timestamp to the training
  • Useful for Apps with bicycle measurements
  1. props.cadence: Current cycling cadence (rpm)
  2. props.resistance: Current cycling resistance
  3. props.power: Current cycling power (W)

Definitions

training_stages_definition

A training has the following stages:

  1. The training is started when [Start training](#Start training) is executed.
    1. start property is set to the start time
    2. end property is null.
    3. uploaded_at property is null
  2. A training is Paused or unfinished when [Pause training](#Pause training) is executed or the training is interrupted
    1. start property was set to the start time
    2. end property is null.
    3. uploaded_at property is null
  3. A training is Resumed when [Resume training](#Resume training) is executed
    1. start property was set to the start time
    2. end property is null.
    3. uploaded_at property is null
  4. The training is finished when [Finish training](#Finish training) is executed
    1. start property was set in the previous stages
    2. end property is set to the finished time
    3. uploaded_at property is null
  5. The training is uploaded when Upload trainings is executed
    1. start property was set in the previous stages.
    2. end property was set in the previous stages.
    3. uploaded_at property is null
training_summary_type

Every training has records obtained each certain time, and we create summaries of that records such like:

  • hr_max
  • hr_min
  • effort_max
  • effort_avg
  • training_duration

A training summary type is composed of

  • name (string): e.g. hr_max
  • uuid (string): Unique summary type identifier UUID4, it is assigned by RookMotion Server, and they're fixed.


useRookTrainingUploader

Description

This hook handles stored trainings

  • Upload finished trainings
  • Get finished trainings pending to be uploaded
  • Delete stored trainings
note

A Training can be uploaded only when it has finished. You can check the Training stages here

info

To upload a Training, an existing user must be already on local using: useRookUser.getUser()

For training upload there are different scenarios based on the Training stages:

  • [Upload all finished trainings](#Upload all finished trainings) if you want to upload all the finished trainings in the local database.

    • e.g. the user just finished a training, you want to upload it plus all the pending to upload trainings.
    • e.g. the user performed multiple trainings without internet, they all were correctly finished, and you want to upload all of them:
  • [Finish and upload a Training](#Upload all finished trainings) if you want to upload all the finished trainings in the local database.

    • e.g. the user just finished a training, you want to upload it plus all the pending to upload trainings.
    • e.g. the user performed multiple trainings without internet, they all were correctly finished, and you want to upload all of them:

Definition

const uploader = useRookTrainingUploader();

Import

  import { useRookTrainingUploader } from 'rook-core' 

Return

ready: Indicates if the hook is ready.


Stored Training actions

Upload all finished trainings

uploadPendingTrainings: () => Promise<UploadPendingTrainingsResult>

Example

uploader
.uploadPendingTrainings()
.then(result => {

if (result.pending_trainings === result.uploaded_trainings) {
// If pending_trainings is the same as uploaded_trainings it means all trainings were successfuly uploaded
} else {
// We can loop through the failures array to check which trainings failed and what went wrong

result.failures.forEach(fail =>
console.log(`Error uploading ${fail.start} error: ${fail.error}`)
);
}

})
.catch(error => {
// Manage errors
});
Finish and upload a training

finishAndUploadTraining: (start: string) => Promise<UploadPendingTrainingsResult>

Example


uploader
.getPendingTrainings()
.then(starts => {
if (starts.length > 0) {
uploader.finishAndUploadTraining(starts[0])
.then(result => {

})
.catch(error => {
// Manage errors
});
} else {
// No pending trainings
}
})
.catch(error => {
// Manage errors
});
Get Pending trainings

getPendingTrainings: () => Promise<Array<string>>

  • Retrieves all the finished trainings pending to be uploaded from local database (see training stages)
  • @return array(string: training start key)
Delete Uploaded trainings

deleteUploadedTrainings: () => Promise<void>

  • Deletes from local database all the trainings already uploaded (see training stages)

Example

uploader
.uploadPendingTrainings()
.then(result => {

if (result.pending_trainings === result.uploaded_trainings) {

uploader
.deleteUploadedTrainings()
.then(() => console.log('finished'))
.catch(error => {
// Manage errors
});

} else {
result.failures.forEach(fail =>
console.log(`Error uploading ${fail.start} error: ${fail.error}`)
);
}

})
.catch(error => {
// Manage errors
});

Definitions

upload_trainings_result
  • UploadPendingTrainingsResult.result:
    • ALREADY_UPLOADING: If you try to call the same method, (e.g. uploadPendingTrainings) without waiting for the previous call to end.
    • NO_TRAININGS_TO_UPLOAD: No trainings in Database pending to be uploaded.
    • TRAININGS_SYNCED: Trainings were uploaded. Check the failures array to verify which ones.
  • UploadPendingTrainingsResult.pending_trainings (number): Counter of Trainings attempted to be uploaded.
  • UploadPendingTrainingsResult.uploaded_trainings (number): Counter of Trainings uploaded.
  • failures (TrainingUploadFailure[]): Array of training upload errors.
    • start (string): Start timestamp of the training
    • error (string): Error description


useRookSummaries

Description training_summaries_types_definition

Definition

`useRookSummariesTypes: () => useRookSummariesTypesTools`

Import

import { useRookSummaries } from 'rook-core'

Return

ready: Indicates if the hook is ready.


Training summaries types

Get training summaries types

getSummariesTypes: () => Promise<SummariesTypesResponse>;

Example

import React, {useState} from 'react';
import {SafeAreaView, Button, FlatList, Text, View} from 'react-native';
import {useRookSummariesTypes, SummaryType} from 'rook-core';

export const SummariesTypes = () => {
const {ready, getRewards} = useRookSummariesTypes();

const [data, setData] = useState<SummaryType[]>([]);

const handlePress = async (): Promise<any> => {
if (!ready) {
console.log('not ready');
return;
}

const response = await getSummariesTypes();
if (response && response.data) {
setData(response.data);
setRewards([]);
}
};

return (
<SafeAreaView>
<Button title="Ver Summaries Types" onPress={handleRewards} />

<FlatList
data={data}
keyExtractor={item => `${item.id}`}
renderItem={({item}) => (
<View>
<Text>id: {item.id}</Text>
<Text>Group: {item.group}</Text>
<Text>summary_name: {item.summary_name}</Text>
<Text>summary_type_uuid: {item.summary_type_uuid}</Text>
<Text>units: {item.units}</Text>
</View>
)}
/>
</SafeAreaView>
);
};



useRookRewards

Description

Retrieves the user rewards (RookPoints) obtained for trainings

Definition

`useRookRewards: () => useRookRewardsTools;`

Import

import { useRookRewards } from 'rook-core'

Return

ready: Indicates if the hook is ready.


Rewards

Rewards are the RookPoints earned for training.

Get rewards

getRewards: (props: getRewardProps) => Promise<RewardsResponse>;

  • Retrieve the user rewards
  • props: Indicates de user
  1. props.userUUID: user_uuid_definition
import React, {useState} from 'react';
import {Button, FlatList, Text, View} from 'react-native';
import {SafeAreaView} from 'react-native';
import {useRookSummaries, Reward} from 'rook-core';

export const Summaries = () => {
const {ready, getRewards} = useRookSummaries();

const [ userUUID, setUserUUID ] = useState('')
const [rewards, setRewards] = useState<Reward[]>([]);

const handleRewards = async (): Promise<any> => {
if (!ready) {
console.log('not ready');
return;
}

try {

const response = await getRewards({
userUUID,
});

if (response && response.data) {
setRewards(response.data);
}
}
catch(error) {
console.log(error);
}

};

return (
<SafeAreaView>
<Button title="Ver Rewards" onPress={handleRewards} />

<Text>User uuid<Text>
<TextInput
onChangeText = { text => setUserUUID(text) }
/>

<FlatList
data={rewards}
keyExtractor={item => `${item.training_uuid}`}
renderItem={({item}) => (
<View>
<Text>training_uuid: {item.training_uuid}</Text>
<Text>points: {item.calories_points}</Text>
</View>
)}
/>
</SafeAreaView>
);
};



RookMotion Bluetooth

RookMotion Bluetooth is a React Hook library that will help you with the discovery and connection with sensors.

Installation

note

This package was already installed here: if not, use: yarn add rook-bluetooth

Hooks

Available hooks are:



Configuration_

note

Auth credentials were set already here:



useSensorScanner

Description

  • Discovers for nearby sensors
  • props: Bluetooth configuration
  • useSensorScannerTools: Returned properties
  1. props.emitter: This will notify certain events that happen during the session like BleManagerDiscoverPeripheral, BleManagerStopScan, BleManagerDisconnectPeripheral, BleManagerDidUpdateValueForCharacteristic
  2. props.showAlert: Show notifications by alerts

Definition

`useSensorScanner: (props: useSensorScannerProps)=> useSensorScannerTools`

Import

import { useSensorManager } from 'rook-bluetooth';

Return

  • isReady: boolean;: Indicates when the hook is ready,
  • discoveredSensors: Array<BLPeripheral>;: List of discovered Sensors
  • isScanning: boolean;: Indicates if the hook is scanning for sensors
  • startScan: (timeout: number) => void;: Starts the process of scanning with a timeout

Example

import React, {FC, useEffect} from 'react';
import {Colors} from 'react-native/Libraries/NewAppScreen';
import {
TouchableWithoutFeedback,
Text
FlatList,
NativeEventEmitter,
NativeModules,
Platform,
StyleSheet,
useColorScheme,
} from 'react-native';

import {
BLPeripheral,
executeWithAndroidTrainingPermissions,
useSensorScanner,
} from 'rook-bluetooth';

type BLEScannerProps = {
selectedSensor: (sensor: BLPeripheral) => void;
};

export const BLEScanner: FC<BLEScannerProps> = ({selectedSensor}) => {
const isDarkMode = useColorScheme() === 'dark';

const {isReady, startScan, discoveredSensors, isScanning} = useSensorScanner({
emitter: new NativeEventEmitter(NativeModules.BleManager),
showAlert: true,
});

useEffect(() => {
if (isReady) {
startScanning();
}
}, [isReady]);

const waitForPermission = (): Promise<Boolean> => {
return new Promise((resolve, reject) => {
if (Platform.OS === 'android' && Platform.Version >= 23) {
executeWithAndroidTrainingPermissions(
() => resolve(true),
() => reject(),
);
} else {
// To give some extra time that all services are available
setTimeout(() => {
resolve(true);
}, 200);
}
});
};

const startScanning = async (): Promise<any> => {
try {
const result = await waitForPermission();

if (result) {
startScan(5);
console.log('Buscando . . .');
} else {
console.log('Permission required');
}
} catch (error) {
console.log('Permission required');
}
};

return (
<View>
{ isScanning && (
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Scanning
</Text>
)}

<FlatList
data={discoveredSensors}
keyExtractor={item => item.address}
renderItem={({item}) => {
return (
<TouchableWithoutFeedback
key={item.address}
onPress={() => selectedSensor(item)}>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
{`Connect to -> ${item.name}`}
</Text>
</TouchableWithoutFeedback>
);
}}
/>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});




useSensorManager

Description

  • Connects to specified Bluetooth Sensor
  • props: Bluetooth configuration.
  • useSensorManagerTools: Connection properties
  1. props.emitter: This will notify events during the training like
    1. BleManagerDiscoverPeripheral
    2. BleManagerStopScan
    3. BleManagerDisconnectPeripheral
    4. BleManagerDidUpdateValueForCharacteristic
  2. props.showAlert: Show notifications by alerts
  3. props.stepsEnable: Enable steps during the training

Definition

` useSensorManager: (props : useSensorManagerProps) => useSensorManagerTools;`

Import

import { useSensorManager } from 'rook-bluetooth';

Return batteryLevel: number;

  • Indicate the battery for the connected Sensor

bpm: number;

  • Indicate the beats per minute of the user

connectedPeripheral?: BLPeripheral;

  • Indicate the Sensor that is connected

isReady: boolean;

  • Indicates when the hook is ready

stepCount: number;

  • Indicates the accumulated steps during the training

connect: (peripheral: BLPeripheral) => Promise<boolean>;

  • Connect to a Sensor
  • peripheral: Sensor to connect this could be found by the hook useSensorScanner
  1. boolean: Indicates if the connection was successfully or failed

disconnect: () => Promise<boolean>;

  • Disconnect of the Sensor
  1. boolean: Indicates if the connection was successfully or failed

disconnectFrom: (peripheral: BLPeripheral) => Promise<boolean>;

  • Disconnect of the Sensor
  • peripheral: Sensor to disconnect
  1. boolean: Indicates if the connection was successfully or failed

Example

import React, {FC, useEffect, useState} from 'react';
import {
Text
NativeEventEmitter,
NativeModules,
StyleSheet,
useColorScheme,
Button
} from 'react-native';
import {BLPeripheral, useSensorManager} from 'rook-bluetooth';
import {Colors} from 'react-native/Libraries/NewAppScreen';

type BLEConnectProps = {
sensor: BLPeripheral | null;
};

export const BLEConnect: FC<BLEConnectProps> = ({
sensor,
destroy,
}) => {
const isDarkMode = useColorScheme() === 'dark';

const [connecting, setConnecting] = useState(false);

const {
isReady,
batteryLevel,
bpm,
stepCount,
connectedPeripheral,
connect,
disconnect,
} = useSensorManager({
emitter: new NativeEventEmitter(NativeModules.BleManager),
showAlert: true,
stepsEnable: true,
});

useEffect(() => {
if (isReady) {
setTimeout(() => {
attemptToConnect();
}, 200);
}
}, [isReady, sensor]);

useEffect(() => {
return () => {
prepareDisconnection();
}
}, []);

const attemptToConnect = async (): Promise<any> => {
if (connecting || !sensor) {
return;
}

setConnecting(true);

try {
const result = await connect(sensor);

if (result) {
console.log('Connection successfully');
connected(true);
} else {
throw new Error();
}
} catch (error) {
connected(false);
console.log('Unable to connect');
}
};

const prepareDisconnection = (): void => {
disconnect();
};

return (
<View>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Bpm: {bpm}
</Text>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
Battery: {batteryLevel}
</Text>
<Text
style={[
{
color: isDarkMode ? Colors.white : Colors.black,
},
styles.textCenter,
]}>
steps: {stepCount}
</Text>

<View alignItems="center" marginTop={5}>
<Button
title = 'Disconnect'
onPress={prepareDisconnection}
/>
</View>
</View>
);
};

const styles = StyleSheet.create({
textCenter: {
textAlign: 'center',
marginBottom: 8,
},
});