The Skylight Integration API provides the ability to connect your Skylight applications to external systems. The APIs are offered as SDKs and are currently available for C#.
The SDKs are wrappers around APIs generated using OpenAPI Generator that provides functionality for querying information about applications and sessions, as well as event handling for session events.
The SDK takes care of fundamental aspects of Skylight integration code development that would otherwise be repeated between implementations, including:
Authenticating with Skylight
Refreshing access tokens when necessary
Subscribing to MQTT topics
Reconnecting to the MQTT broker when necessary
Providing models for Skylight applications and sessions
While the syntax may differ between the various languages, the concepts and provided methods of the different SDKs strive to be as similar as possible.
To use the C# SDK in your code, follow these steps:
Ensure that .NET Core 3.1 is installed on your machine.
dotnet --version
should return 3.1.301
or higher
dotnet nuget --version
should return 5.6.0.5
or higher
​
Scaffold out your project:
dotnet new console -n myService
cd myService
Connect to the NuGet feed:
https://pkgs.dev.azure.com/UpskillSDK/skylight-sdk/_packaging/release/nuget/v3/index.json -n skylightSdkRelease
For Visual Studio, use the NuGet package manager to connect to this feed.
For Visual Studio Code or other IDEs, connect to this feed by adding this feed in the nuget.config file, or by using the command: dotnet nuget add source https://pkgs.dev.azure.com/UpskillSDK/skylight-sdk/_packaging/release/nuget/v3/index.json -n skylightSdkRelease
Install the Skylight SDK NuGet package:
For Visual Studio, use the NuGet package manager to install the latest version from this feed.
For Visual Studio Code or other IDEs, install the package by running dotnet add package Skylight.Sdk
.
The reference provides documentation on the SDK methods, events, and objects:
The following snippet showcases the self-contained main .cs file of a project that uses the C# SDK.
using System;using System.IO;using System.Timers;using System.Dynamic;using System.Configuration;using System.Threading.Tasks;using System.Collections.Generic;using System.Collections.Specialized;​using System.Net;using System.Net.Http;using System.Net.Http.Headers;​using Skylight.Model;using Skylight.Sdk;using Newtonsoft.Json.Linq;​namespace SkylightSample{class Program : ISessionEventListener{// We'll store an instance of our Skylight.Sdk.Managerstatic Manager _skyManager;​// These variables are used to store credentials and application information in config files. In a production setting, these should likely be stored/read as environment variablesstatic NameValueCollection _credentialsConfig, _applicationConfig;​// This is our main entry pointstatic async Task Main(string[] args){// Retrieve our credentials and application configurationSetupAppConfig();​// Create our manager_skyManager = new Manager(new Program());​// Configure our credentials using one of three methods:_skyManager.SetCredentials(_credentialsConfig["Username"], _credentialsConfig["Password"], _credentialsConfig["Realm"], _credentialsConfig["ApiUrl"], _credentialsConfig["MqttUrl"]);// Configure manager after instantiation, here. Right now, this just sets the verbosity of the SDK._skyManager.SetVerbosity(Logger.Verbosity.Verbose);​// Connect our manager, which will connect us to Skylight APIs and MQTT.await _skyManager.Connect();​// Run our various application and session method examples//await RunApplicationExamples();await RunSessionExamples();​//This keeps our program alive. Note that anything after this line will NOT get called. If we wish to use user input as our method of keeping the program alive, we should replace this line._skyManager.KeepAlive();}​// This retrieves our credentials/application configuration -- in a product setting, this should likely read from environment variablesstatic void SetupAppConfig() {//Open configSystem.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);​//Update appconfig file pathconfig.AppSettings.File = Path.Join("config", "App.config");​//Save the configuration file.config.Save(ConfigurationSaveMode.Modified);​//Force a reload in memory of the changed section.ConfigurationManager.RefreshSection("applicationConfig");ConfigurationManager.RefreshSection("credentialsConfig");_credentialsConfig = ConfigurationManager.GetSection("credentialsConfig") as NameValueCollection;_applicationConfig = ConfigurationManager.GetSection("applicationConfig") as NameValueCollection;}​/*Application and Session Method Examples*/static async Task RunApplicationExamples(){// Get ApplicationsConsole.WriteLine("Get Applications");var applications = await _skyManager.GetApplications();foreach (var applicationFromList in applications){Console.WriteLine(applicationFromList);}​// Get ApplicationConsole.WriteLine("Get Application");var application = await _skyManager.GetApplication(_applicationConfig["Id"]);Console.WriteLine(application);​// Get Application RolesConsole.WriteLine("Get Application Roles");var applicationRoles = await _skyManager.GetApplicationRoles(_applicationConfig["Id"]);foreach (var applicationRole in applicationRoles){Console.WriteLine(applicationRole);}}​static async Task RunSessionExamples(){// Get SessionsConsole.WriteLine("Get Sessions");var sessions = await _skyManager.GetSessions(_applicationConfig["Id"]);foreach (var sessionFromApplication in sessions) {Console.WriteLine(sessionFromApplication);}​// Create SessionConsole.WriteLine("Create Session");var newSessionProperties = new Dictionary<string, string>();newSessionProperties["customKey"] = "customValue";var newSession = await _skyManager.CreateSession(_applicationConfig["Id"], "New Session", "This is a new session.", newSessionProperties);Console.WriteLine(newSession);​// Patch SessionConsole.WriteLine("Patch Session");var sessionPatch = new SessionPatchRequest(){Name = "Patched Session",Description = "This session has been patched."};await _skyManager.PatchSession(_applicationConfig["Id"], newSession.SessionId, sessionPatch);​// Get SessionConsole.WriteLine("Get Session");var patchedSession = await _skyManager.GetSession(_applicationConfig["Id"], newSession.SessionId);Console.WriteLine(patchedSession);​// Update Session NameConsole.WriteLine("Update Session Name");await _skyManager.UpdateSessionName(_applicationConfig["Id"], newSession.SessionId, "Latest Session");​// Update Session DescriptionConsole.WriteLine("Update Session Description");await _skyManager.UpdateSessionDescription(_applicationConfig["Id"], newSession.SessionId, "This session description has been updated.");​// Update Session PropertiesConsole.WriteLine("Update Session Properties");var updatedSessionProperties = new Dictionary<string, string>();updatedSessionProperties["anotherCustomKey"] = "anotherCustomValue";await _skyManager.UpdateSessionProperties(_applicationConfig["Id"], newSession.SessionId, updatedSessionProperties);​// Patch Session DataConsole.WriteLine("Patch Session Data");await _skyManager.PatchSessionData(_applicationConfig["Id"], newSession.SessionId, new Worklist("Worklist 0"));​// Get Session DataConsole.WriteLine("Get Session Data");var worklist = await _skyManager.GetSessionData<Worklist>(_applicationConfig["Id"], newSession.SessionId);Console.WriteLine(worklist);​// Add Session ParticipantConsole.WriteLine("Add Participant");//await _skyManager.AddParticipant(_applicationConfig["Id"], newSession.SessionId, "dummy-group-id", SessionParticipantPostRequest.TypeEnum.Group);​// Close SessionConsole.WriteLine("Close Session");await _skyManager.CloseSession(_applicationConfig["Id"], newSession.SessionId);​}​/*Event Listener Examples*/async Task ISessionEventListener.OnSessionCreated(SessionEventBase sessionEvent){Console.WriteLine("Session created");Console.WriteLine(sessionEvent.ToString());var properties = sessionEvent.Session.Properties;Console.WriteLine(properties.ToString());foreach (KeyValuePair<string, string> kvp in properties){Console.WriteLine("{"+kvp.Key + "," + kvp.Value+"}");}}​async Task ISessionEventListener.OnSessionPropertiesUpdated(SessionEventBase sessionEvent){Console.WriteLine("Session properties updated: " + sessionEvent.SessionId);Console.WriteLine(sessionEvent.ToString());var properties = sessionEvent.Session.Properties;Console.WriteLine(properties.ToString());foreach (KeyValuePair<string, string> kvp in properties){Console.WriteLine("{"+kvp.Key + "," + kvp.Value+"}");}}​async Task ISessionEventListener.OnSessionUpdated(SessionEventBase sessionEvent){Console.WriteLine("Session updated");Console.WriteLine(sessionEvent.ToString());}​async Task ISessionEventListener.OnSessionClosed(SessionEventBase sessionEvent){Console.WriteLine("Session closed: " + sessionEvent.SessionId);Console.WriteLine(sessionEvent.ToString());}​async Task ISessionEventListener.OnSessionDataUpdated(SessionEventBase sessionEvent){Console.WriteLine("Session data updated");Console.WriteLine(sessionEvent.ToString());JObject data = sessionEvent.Data as JObject;Console.WriteLine(data.ToString());​// Example of converting the JSON Object to our own class that we passed into the session data updatetry {Worklist worklist = data.ToObject<Worklist>();Console.WriteLine("Our session data as a worklist object:");Console.WriteLine(worklist.title);} catch (Exception e) {Console.Error.WriteLine(e);}}​async Task ISessionEventListener.OnSessionEventCreated(SessionEventBase sessionEvent){Console.WriteLine("Session event created");Console.WriteLine(sessionEvent.ToString());}}​// This is an example of an object used to represent a worklistclass Worklist {public string title;public List<Step> steps;​public Worklist(string title) {this.title = title;}}​// This is an example of an object used to represent a step in worklistclass Step {public string name;public Step otherStep;public void Hello() {Console.WriteLine("Hi this is a step");}}}