How to use SAFE Swift API?
When to use SAFE Swift API?
As the name suggests, the SAFE Swift API produces the result quickly. Unlike the SAFE Application API, it doesn't keep a copy of your uploaded roster data in the SAFE web app. So, you won't be able to view the uploaded roster in the future. This API, however, delivers fatigue score and fatigue risk score as response from the same the endpoints you use to send the roster data. Use this API to quickly generate fatigue score and fatigue risk score from the roster data.
How to work with the API?
This code snippet is written in C# and it is used to upload roster data to the FRMSC SAFE Swift API and get results from the API. The program uses the following libraries:
IdentityModel.Client
Safe_API_Demo_Client.Models
System
System.Collections.Generic
System.Linq
System.Net.Http.Json
System.Text
System..Threading.Tasks
Here are the steps to follow.
Get Fatigue Score
Follow the instructions below to get fatigue score. This code sends HTTP POST
request to a web API endpoint.
Step 1: Generate a token
Generate a Bearer token to use with this endpoint. Follow the instructions given in How to generate a Bearer token? tutorial to generate a bearer token.
Step 2: Set the variable values
Set the values of apiKey
, accessToken
, rosterCSV
, and clientId
variables.
var apiUrl = "https://api-eu.frmsc.com";
var accessToken = "[Your_Accesstoken]";
var rosterCsv = File.ReadAllText("SampleRosters\\ExampleRosterUpload.csv");
var clientId = "[Your_ClientId]";
You can get the accessToken
from the previous step.
The rosterCSV
variable is set to read the roster data from a CSV file. Set the parameter value of the File.ReadAllText()
function to the location of the CSV file with the roster data.
Step 3: Initiate request
Create an HTTP client and set the base address to the API URL. We recommend that you also set the HTTP client to timeout after 1000 seconds. Then, create an HTTP request message with the HTTP method set to POST and the endpoint set to /api/Processor/ProcessFatigue
. The request message should also include the authorization
header with the access token.
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1000);
client.BaseAddress = new Uri(apiUrl);
var request = new HttpRequestMessage(HttpMethod.Post, "/api/Processor/ProcessFatigue");
request.Version = new Version(2, 0);
request.Headers.Add("authorization", $"Bearer {accessToken}");
Step 4: Prepare request body
Create an instance of the FatigueProcessorPayload
class and sets its properties.
var payload = new
{
RosterData = rosterCsv,
SleepData = new List<SleepData>(),
PreferredScale = "SP",
DateFormat = "dmy",
GenerateSleeps = true,
SleepSettings = new List<SleepSetting>()
};
The FatigueProcessorPayload
class has six properties.
-
Set the RosterData property to refer to
rosterCsv
. -
The
PreferredScale
property has been set toSP
in the example. This value can be changed to indicate a different scale, which you want the result to be in. See Step 5: Retry with different PrefferedScale for different values you can assign toPreferredScale
property. -
The
SleepData
property takes an array of the following properties:ScheduleName
, which indicates the schedule nameSleepStart
, which indicates the date and time (Zulu format) when the sleep startedSleepEnd
, which indicates the date and time (Zulu format) when the sleep ended
-
Leave the
SleepData
andSleepSettings
properties empty by assiging empty lists to them. -
The
DateFormat
property is set todmy
, which indicates DD/MM/YYYY date format has been used in roster data. You could change this value tomdy
to indicate MM/DD/YYYY date format. -
The
GenerateSleeps
property has been set totrue
to indicate that SAFE must predict sleeps automatically. You can provideSleepData
and still set theGenerateSleeps
property to true to indicate SAFE must disregard the providedSleepData
and predict sleeps automatically.
Step 5: Make the request
Create a JSON object using the request body and send the request message to the API and wait for it to return the result.
request.Content = JsonContent.Create(payload);
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Result: " + result);
return result;
Step 6: Retry with different PrefferedScale
There are two workflows for this step depending on the response you receive from the previous step.
If the response from the previous step is an error, read the response to locate the cause of the error.
How to read the error?
Each error contains 3 pieces of information separated by a | symbol.
- The first part shows you the row within the csv where the error occured.
- The second part shows the schedule, which the error is for, and
- The third part shows the error message.
Example response error
Resolve any error in the roster data file and retry sending the request.
If you receive the result for the scale you had set in PreferredScale
property, you can send the request again within a different value assigned to the PreferredScale
property. The following values are supported for the PreferredScale
property. Send only one value at a time.
SP
for Samn-Perelli scaleKSS
for Karolinska Sleepiness ScaleKP
for Karolinska Probability scaleVS
for Vigilance Degradation scaleCRD
for Complex Reaction Degradation scalePMR
for Percentage Missed Responses scale
Get Fatigue Risk Score
Follow the instructions below to get fatigue score together with risk score. This code sends HTTP POST
request to a web API endpoint.
Step 1: Generate a token
Generate a Bearer token to use with this endpoint. Follow the instructions given in How to generate a Bearer token? tutorial to generate a bearer token.
Step 2: Set the variable values
Set the values of apiKey
, accessToken
, rosterCSV
, and clientId
variables.
var apiUrl = "https://api-eu.frmsc.com";
var accessToken = "[Your_Accesstoken]";
var rosterCsv = File.ReadAllText("SampleRosters\\ExampleRosterUpload.csv");
var clientId = "[Your_ClientId]";
You can get the accessToken
from the previous step.
The rosterCSV
variable is set to read the roster data from a CSV file. Set the parameter value of the File.ReadAllText()
function to the location of the CSV file with the roster data.
Step 3: Initiate request
Create an HTTP client and set the base address to the API URL. We recommend that you also set the HTTP client to timeout after 1000 seconds. Then, create an HTTP request message with the HTTP method set to POST and the endpoint set to /api/Processor/ProcessFatigueRisk
. The request message should also include the authorization
header with the access token.
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1000);
client.BaseAddress = new Uri(apiUrl);
var request = new HttpRequestMessage(HttpMethod.Post, "/api/Processor/ProcessFatigueRisk");
request.Version = new Version(2, 0);
request.Headers.Add("authorization", $"Bearer {accessToken}");
Step 4: Prepare request body
Create an instance of the FatigueProcessorPayload
class and sets its properties.
var payload = new
{
RosterData = rosterCsv,
SleepData = new List<SleepData>(),
PreferredScale = "SP",
DateFormat = "dmy",
GenerateSleeps = true,
SleepSettings = new List<SleepSetting>()
};
The FatigueProcessorPayload
class has six properties.
-
Set the RosterData property to refer to
rosterCsv
. -
The
PreferredScale
property has been set toSP
in the example. This value can be changed to indicate a different scale, which you want the result to be in. See Step 5: Retry with different PrefferedScale for different values you can assign toPreferredScale
property. -
The
SleepData
property takes an array of the following properties:ScheduleName
, which indicates the schedule nameSleepStart
, which indicates the date and time (Zulu format) when the sleep startedSleepEnd
, which indicates the date and time (Zulu format) when the sleep ended
-
Leave the
SleepData
andSleepSettings
properties empty by assiging empty lists to them. -
The
DateFormat
property is set todmy
, which indicates DD/MM/YYYY date format has been used in roster data. You could change this value tomdy
to indicate MM/DD/YYYY date format. -
The
GenerateSleeps
property has been set totrue
to indicate that SAFE must predict sleeps automatically. You can provideSleepData
and still set theGenerateSleeps
property to true to indicate SAFE must disregard the providedSleepData
and predict sleeps automatically.
Step 5: Make the request
Create a JSON object using the request body and send the request message to the API and wait for it to return the result.
request.Content = JsonContent.Create(payload);
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Result: " + result);
return result;
Step 6: Retry with different PrefferedScale
There are two workflows for this step depending on the response you receive from the previous step.
If the response from the previous step is blank, use the Fatigue endpoint to find the error.
Resolve any error in the roster data file. Then, return to Get Fatigue Risk Score.
If you receive the result for the scale you had set in PreferredScale
property, you can send the request again within a different value assigned to the PreferredScale
property. The following values are supported for the PreferredScale
property. Send only one value at a time.
SP
for Samn-Perelli scaleKSS
for Karolinska Sleepiness ScaleKP
for Karolinska Probability scaleVS
for Vigilance Degradation scaleCRD
for Complex Reaction Degradation scalePMR
for Percentage Missed Responses scale
Complete Code
using IdentityModel.Client;
using Safe_API_Demo_Client.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;
namespace Safe_API_Demo_Client
{
public static class FastApi
{
public static async void Run()
{
var identityUrl = "https://identity-eu.frmsc.com";
var apiUrl = @"https://api-eu.frmsc.com";
var clientId = "[Your_ClientId]";
var clientSecret = "[your_ClientSecret]";
var rosterCsv = File.ReadAllText("SampleRosters\\ExampleRosterUpload.csv");
var accessToken = await Authenticate(identityUrl, clientId, clientSecret, "frmsc_fast_safe_api");
await ProcessFatigue(apiUrl, accessToken, rosterCsv);
var accessToken = await Authenticate(identityUrl, clientId, clientSecret, "frmsc_fast_safe_risk_api");
await ProcessFatigueRisk(apiUrl, accessToken, rosterCsv);
}
static async Task<string> ProcessFatigue(string apiUrl, string accessToken, string rosterData)
{
try
{
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1000);
client.BaseAddress = new Uri(apiUrl);
var request = new HttpRequestMessage(HttpMethod.Post, "/api/Processor/ProcessFatigue");
request.Version = new Version(2, 0);
request.Headers.Add("authorization", $"Bearer {accessToken}");
var payload = new FatigueProcessorPayload
{
RosterData = rosterData,
SleepData = new List<SleepData>(),
PreferredScale = "SP",
DateFormat = "dmy",
GenerateSleeps = true,
SleepSettings = new List<SleepSetting>()
};
request.Content = JsonContent.Create(payload);
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Result: " + result);
return result;
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
throw;
}
}
static async Task<string> ProcessFatigueRisk(string apiUrl, string accessToken, string rosterData)
{
try
{
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1000);
client.BaseAddress = new Uri(apiUrl);
var request = new HttpRequestMessage(HttpMethod.Post, "/api/Processor/ProcessFatigueRisk");
request.Version = new Version(2, 0);
request.Headers.Add("authorization", $"Bearer {accessToken}");
var payload = new FatigueProcessorPayload
{
RosterData = rosterData,
SleepData = new List<SleepData>(),
PreferredScale = "SP",
DateFormat = "dmy",
GenerateSleeps = true,
SleepSettings = new List<SleepSetting>()
};
request.Content = JsonContent.Create(payload);
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Result: " + result);
return result;
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
throw;
}
}
static async Task<string> Authenticate(string identityUrl, string clientId, string clientSecret, string scope)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(identityUrl);
var openIdDiscoveryDocument = client.GetDiscoveryDocumentAsync(identityUrl).GetAwaiter().GetResult();
var request = new ClientCredentialsTokenRequest
{
Address = openIdDiscoveryDocument.TokenEndpoint,
ClientId = clientId,
ClientSecret = clientSecret,
Scope = scope
};
var tokenResponse = await client.RequestClientCredentialsTokenAsync(request);
if (tokenResponse != null)
{
return tokenResponse.AccessToken;
}
else
{
Console.WriteLine("Authentication failed");
throw new Exception("Authentication failed");
}
}
}
}