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 FRMS SAFE Swift API and get results from the API. The program uses the following libraries:
IdentityModel.ClientSafe_API_Demo_Client.ModelsSystemSystem.Collections.GenericSystem.LinqSystem.Net.Http.JsonSystem.TextSystem..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
PreferredScaleproperty has been set toSPin 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 toPreferredScaleproperty. -
The
SleepDataproperty 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
SleepDataandSleepSettingsproperties empty by assiging empty lists to them. -
The
DateFormatproperty is set todmy, which indicates DD/MM/YYYY date format has been used in roster data. You could change this value tomdyto indicate MM/DD/YYYY date format. -
The
GenerateSleepsproperty has been set totrueto indicate that SAFE must predict sleeps automatically. You can provideSleepDataand still set theGenerateSleepsproperty to true to indicate SAFE must disregard the providedSleepDataand 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.
SPfor Samn-Perelli scaleKSSfor Karolinska Sleepiness ScaleKPfor Karolinska Probability scaleVSfor Vigilance Degradation scaleCRDfor Complex Reaction Degradation scalePMRfor 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
PreferredScaleproperty has been set toSPin 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 toPreferredScaleproperty. -
The
SleepDataproperty 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
SleepDataandSleepSettingsproperties empty by assiging empty lists to them. -
The
DateFormatproperty is set todmy, which indicates DD/MM/YYYY date format has been used in roster data. You could change this value tomdyto indicate MM/DD/YYYY date format. -
The
GenerateSleepsproperty has been set totrueto indicate that SAFE must predict sleeps automatically. You can provideSleepDataand still set theGenerateSleepsproperty to true to indicate SAFE must disregard the providedSleepDataand 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.
SPfor Samn-Perelli scaleKSSfor Karolinska Sleepiness ScaleKPfor Karolinska Probability scaleVSfor Vigilance Degradation scaleCRDfor Complex Reaction Degradation scalePMRfor 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");
}
}
}
}