Documentation for the Unity C# Library
Loading...
Searching...
No Matches
ApexSystem.cs
Go to the documentation of this file.
1using System;
2using System.Net.Http;
3using UnityEngine;
4using UnityEngine.XR;
8using TinCan;
9using System.Threading.Tasks;
10using System.Text.RegularExpressions;
11using Newtonsoft.Json;
12using System.Collections.Generic;
13#if MANAGE_XR
14using MXR.SDK;
15#endif
16
17namespace PixoVR.Apex
18{
19 public delegate void PlatformResponse(ResponseType type, bool wasSuccessful, object responseData);
20
21 [DefaultExecutionOrder(-50)]
22 public class ApexSystem : ApexSingleton<ApexSystem>
23 {
24 private enum VersionParts : int
25 {
26 Major = 0,
27 Minor,
28 Patch
29 }
30
31 public static string ServerIP
32 {
33 get { return Instance.serverIP; }
34 set { }
35 }
36
37 public static int ModuleID
38 {
39 get { return Instance.moduleID; }
40 set { Instance.moduleID = value; }
41 }
42
43 public static string ModuleName
44 {
45 get { return Instance.moduleName; }
46 set { Instance.moduleName = value; }
47 }
48
49 public static string ModuleVersion
50 {
51 get { return Instance.moduleVersion; }
52 set { Instance.moduleVersion = value; }
53 }
54
55 public static string ScenarioID
56 {
57 get { return Instance.scenarioID; }
58 set { Instance.scenarioID = value; }
59 }
60
62 {
63 get { return Instance.currentActiveLogin; }
64 set { }
65 }
66
67 public static bool RunSetupOnAwake
68 {
69 get { return Instance.runSetupOnAwake; }
70 set { Instance.runSetupOnAwake = value; }
71 }
72
73 public static bool LoginCheckModuleAccess
74 {
75 get { return Instance.loginCheckModuleAccess; }
76 set { }
77 }
78
79 public static string DeviceSerialNumber
80 {
81 get { return Instance.deviceSerialNumber; }
82 set { }
83 }
84
85 public static string PassedLoginToken
86 {
87 get { return Instance.loginToken; }
88 set { }
89 }
90
91 public static string OptionalData
92 {
93 get { return Instance.optionalParameter; }
94 set { Instance.optionalParameter = value; }
95 }
96
97 public static string ReturnTarget
98 {
99 get { return Instance.returnTargetParameter; }
100 set { Instance.returnTargetParameter = value; }
101 }
102
103 public static string TargetType
104 {
105 get { return Instance.targetTypeParameter; }
106 set { Instance.targetTypeParameter = value; }
107 }
108
109
110 [SerializeField, EndpointDisplay]
112
113 [SerializeField]
114 protected string serverIP = "";
115
116 [SerializeField]
117 protected int moduleID = 0;
118 [SerializeField]
119 protected string moduleName = "Generic";
120 [SerializeField]
121 protected string moduleVersion = "0.00.00";
122 [SerializeField]
123 protected string scenarioID = "Generic";
124 [SerializeField]
125 public bool runSetupOnAwake = true;
126 [SerializeField]
127 public bool loginCheckModuleAccess = true;
128 [SerializeField]
129 protected float heartbeatTime = 5.0f;
130
131 protected string webSocketUrl;
132 protected string deviceID;
133 protected string deviceModel;
134 protected string platform;
135 protected string clientIP;
136 protected Guid currentSessionID;
137 protected int heartbeatSessionID;
138 protected float heartbeatTimer;
139 protected bool sessionInProgress;
140 protected bool userAccessVerified = false;
141 protected string deviceSerialNumber = "";
142
143 protected string loginToken = "";
144 protected string optionalParameter = "";
145 protected string returnTargetParameter = "";
146 protected string targetTypeParameter = "";
147
150 protected ApexWebsocket webSocket;
151 protected Task<bool> socketConnectTask;
152 protected Task socketDisconnectTask;
153
156
177
181 public PlatformResponse OnPlatformResponse = null;
185 void Awake()
186 {
189 Debug.Log("[ApexSystem] Running on awake!");
192
193 DontDestroyOnLoad(gameObject);
194#if MANAGE_XR
195 InitMXRSDK();
196#endif
198
199#if MANAGE_XR
200 async void InitMXRSDK()
201 {
202 await MXRManager.InitAsync();
203 MXRManager.System.OnDeviceStatusChange += OnDeviceStatusChanged;
204 deviceSerialNumber = MXRManager.System.DeviceStatus.serial;
207 void OnDeviceStatusChanged(DeviceStatus newDeviceStatus)
209 deviceSerialNumber = newDeviceStatus.serial;
210 }
211#endif
212 void SetupAPI()
214 Debug.Log("Mac Address: " + ApexUtils.GetMacAddress());
215 if (serverIP.Length == 0)
216 {
218 }
219
221
222 if(apexAPIHandler != null)
223 {
224 Debug.Log("[ApexSystem] Apex API Handler is not null!");
225 }
226
227 // TODO: Move to new plugin
230 apexAPIHandler.OnAPIResponse += OnAPIResponse;
231
232 if(webSocket != null)
233 {
235 {
237 }
238 }
239
240 webSocket = new ApexWebsocket();
242 webSocket.OnConnectFailed.AddListener((reason) => OnWebSocketConnectFailed(reason));
243 webSocket.OnReceive.AddListener((data) => OnWebSocketReceive(data));
244 webSocket.OnClosed.AddListener((reason) => OnWebSocketClosed(reason));
245
247
250 }
251
252 void _ExitApplication(string returnTarget, string returnTargetType)
253 {
254 Debug.Log("[ApexSystem] " + returnTarget + " " + returnTargetType);
255
256 string parameters = "";
257
258 if(CurrentActiveLogin != null)
259 {
260 parameters += "pixotoken=" + CurrentActiveLogin.Token;
261 }
262
263 if (optionalParameter.Length > 0)
264 {
265 if (parameters.Length > 0)
266 parameters += "&";
267 parameters += "optional=" + optionalParameter;
268 }
269
270 if (returnTarget.Length > 0)
271 {
272 if (parameters.Length > 0)
273 parameters += "&";
274 parameters += "returntarget=" + returnTarget;
275 }
276
277 if (returnTargetType.Length > 0)
278 {
279 if (parameters.Length > 0)
280 parameters += "&";
281 parameters += "targettype=" + returnTargetType;
283
284 if (returnTargetParameter.Length > 0)
285 {
286 if (targetTypeParameter.Equals("url", StringComparison.OrdinalIgnoreCase))
287 {
288 string returnURL = returnTargetParameter;
289 if (parameters.Length > 0)
290 {
291 returnURL += "?" + parameters;
292 }
293 Debug.Log("Custom Target: " + returnURL);
294 Application.OpenURL(returnURL);
295 }
296 else
297 {
298 List<string> keys = new List<string>(), values = new List<string>();
299
300 if(CurrentActiveLogin != null)
301 {
302 keys.Add("pixotoken");
303 values.Add(CurrentActiveLogin.Token);
304 }
305
306 if (optionalParameter.Length > 0)
307 {
308 keys.Add("optional");
309 values.Add(optionalParameter);
310 }
311
312 if (returnTarget.Length > 0)
313 {
314 keys.Add("returntarget");
315 values.Add(returnTarget);
316 }
317
318 if (returnTargetType.Length > 0)
319 {
320 keys.Add("targettype");
321 values.Add(returnTargetType);
322 }
323
324 PixoAndroidUtils.LaunchApp(returnTargetParameter, keys.ToArray(), values.ToArray());
325 }
326 }
327
329 if (url.Contains("apexsa.") || url.Contains("saudi."))
330 {
331 string returnUrl = "pixovr://com.PixoVR.SA_TrainingAcademy";
332 if(parameters.Length > 0)
333 {
334 returnUrl += "?" + parameters;
335 }
336 Debug.Log("Training Hub: " + returnUrl);
337 Application.OpenURL(returnUrl);
338 }
339 else
340 {
341 string returnUrl = "pixovr://com.PixoVR.SA_TrainingAcademy?" + parameters;
342 if (parameters.Length > 0)
343 {
344 returnUrl += "?" + parameters;
345 }
346 Debug.Log("Hub App: " + returnUrl);
347 Application.OpenURL(returnUrl);
348 }
349 }
350
351 string GetEndpointFromTarget(PlatformServer target)
352 {
353 return target.ToUrlString();
354 }
355
356 string GetWebEndpointFromPlatformTarget(PlatformServer target)
357 {
358 int targetValue = (int)target;
359 WebPlatformServer webTarget = (WebPlatformServer)targetValue;
360
361 return webTarget.ToUrlString();
362 }
363
364 string GetPlatformEndpointFromPlatformTarget(PlatformServer target)
365 {
366 int targetValue = (int)target;
367 APIPlatformServer apiTarget = (APIPlatformServer)targetValue;
368
369 return apiTarget.ToUrlString();
370 }
371
373 {
375
376 if (webSocketUrl.Contains("://"))
377 {
378 webSocketUrl = webSocketUrl.Split(new string[] { "://" }, 2, StringSplitOptions.RemoveEmptyEntries)[1];
379 }
380
381 if (webSocketUrl.Contains("/"))
382 {
383 webSocketUrl = webSocketUrl.Split(new string[] { "/" }, 2, StringSplitOptions.RemoveEmptyEntries)[0];
384 }
385
386 webSocketUrl = "wss://" + webSocketUrl + "/ws";
387 }
388
389 void Start()
390 {
392 {
393 Debug.LogAssertion(moduleVersion + " is an invalid module version.");
395 deviceID = SystemInfo.deviceUniqueIdentifier;
396 deviceModel = SystemInfo.deviceModel;
397 platform = XRSettings.loadedDeviceName.Length > 0 ? XRSettings.loadedDeviceName : Application.platform.ToString();
398 clientIP = Utils.ApexUtils.GetLocalIP();
399 }
400
401 private void FixedUpdate()
403 if(webSocket != null)
404 {
406 }
407
409 {
410 heartbeatTimer -= Time.fixedDeltaTime;
411
412 if(heartbeatTimer <= 0.0f)
413 {
416 }
417 }
418 }
420 void ConnectWebsocket()
421 {
422 socketConnectTask = Task.Run(() => webSocket.Connect(new Uri(webSocketUrl)));
423 }
424
426 {
427 socketDisconnectTask = Task.Run(() => webSocket.CloseSocket());
428 }
429
432 Debug.Log("Websocket connected successfully.");
433 }
434
435 void OnWebSocketConnectFailed(string reason)
436 {
437 Debug.LogError("Websocket failed to connect with error: " + reason);
438 }
439
440 void OnWebSocketReceive(string data)
441 {
442 Debug.Log("Websocket received: " + data);
443 try
444 {
445 if (data.Contains("auth_code"))
446 {
447 var authCode = JsonConvert.DeserializeObject<AuthorizationCode>(data);
448 OnAuthorizationCodeReceived.Invoke(authCode.Code);
449 }
451 if (data.Contains("Token", StringComparison.OrdinalIgnoreCase))
452 {
453 object loginResponse = JsonConvert.DeserializeObject<LoginResponseContent>(data);
454 HandleLogin(true, loginResponse);
456 }
457 catch (Exception ex)
458 {
459 Debug.Log(ex.Message);
461 }
462
463 void OnWebSocketClosed(System.Net.WebSockets.WebSocketCloseStatus reason)
464 {
465 Debug.Log("Websocket closed with reason: " + reason);
466 }
467
469 {
471 return false;
472
473 string[] moduleVersionParts = moduleVersion.Split('.');
474
475 if (moduleVersionParts.Length != 3)
476 return false;
477
478 if (!IsModuleMajorVersionPartValid(moduleVersionParts[(int)VersionParts.Major]))
479 return false;
480
481 if (!IsModuleNonMajorVersionPartValid(moduleVersionParts[(int)VersionParts.Minor]))
482 return false;
483
484 if (!IsModuleNonMajorVersionPartValid(moduleVersionParts[(int)VersionParts.Patch]))
485 return false;
486
487 return true;
488 }
489
490 static readonly Regex VersionValidator = new Regex(@"^[0123456789.]+$");
492 {
494 }
495
496 bool IsModuleNonMajorVersionPartValid(string modulePart)
497 {
498 if (modulePart.Length <= 0)
499 return false;
500
501 if (modulePart.Length > 2)
502 return false;
503
504 return true;
505 }
506
507 bool IsModuleMajorVersionPartValid(string modulePart)
508 {
509 if (modulePart.Length <= 0)
510 return false;
511
512 if (modulePart.StartsWith("0"))
513 return false;
514
515 return true;
516 }
517
518 [Obsolete("ReturnToHub has been deprecated, please use ExitApplication.", true)]
519 public static void ReturnToHub()
521 Instance._ReturnToHub();
522 }
523
524 public static void ExitApplication(string returnTarget, string returnTargetType)
525 {
526 Instance._ExitApplication(returnTarget, returnTargetType);
527 }
528
529 public static string GetAuthenticationToken()
530 {
531 return Instance._GetAuthenticationToken();
532 }
533
534 public static bool RequestAuthorizationCode()
535 {
536 return Instance._RequestAuthorizationCode();
538
539 public static void ChangePlatformServer(PlatformServer newServer)
540 {
541 Instance._ChangePlatformServer(newServer);
542 }
543
544 public static void Ping()
545 {
546 Instance._Ping();
547 }
548
549 public static bool LoginWithToken()
550 {
551 return LoginWithToken(Instance.loginToken);
552 }
553
554 public static bool LoginWithToken(string token)
555 {
556 return Instance._LoginWithToken(token);
557 }
558
559 public static bool Login(LoginData login)
560 {
561 return Instance._Login(login);
562 }
563
564 public static bool Login(string username, string password)
565 {
566 return Instance._Login(username, password);
567 }
568
569 public static bool CheckModuleAccess(int targetModuleID = -1)
570 {
571 return Instance._CheckModuleAccess(targetModuleID);
572 }
573
574 public static bool JoinSession(string scenarioID = null, Extension contextExtension = null)
575 {
576 return Instance._JoinSession(scenarioID, contextExtension);
577 }
578
579 public static bool CompleteSession(SessionData currentSessionData, Extension contextExtension = null, Extension resultExtension = null)
580 {
581 return Instance._CompleteSession(currentSessionData, contextExtension, resultExtension);
582 }
583
584 public static bool SendSimpleSessionEvent(string action, string targetObject, Extension contextExtension)
585 {
586 return Instance._SendSimpleSessionEvent(action, targetObject, contextExtension);
587 }
588
589 public static bool SendSessionEvent(Statement eventStatement)
590 {
591 return Instance._SendSessionEvent(eventStatement);
592 }
593
594 public static bool GetCurrentUser()
595 {
596 return GetUser();
597 }
598
599 public static bool GetUser(int userId = -1)
600 {
601 return Instance._GetUser(userId);
602 }
603
604 public static bool GetCurrentUserModules()
605 {
606 return GetUserModules();
607 }
608
609 public static bool GetUserModules(int userId = -1)
610 {
611 return Instance._GetUserModules(userId);
612 }
613
614 public static bool GetModulesList()
615 {
616 return Instance._GetModuleList();
617 }
618
619 protected void _ChangePlatformServer(PlatformServer newServer)
620 {
621 PlatformTargetServer = newServer;
622
623 SetupAPI();
625
626 protected void _Ping()
627 {
630
631 public bool _LoginWithToken(string token)
632 {
633 if(token.Length <= 0)
635 return false;
636 }
637
640 return true;
641 }
642
643 protected bool _Login(LoginData login)
645 Debug.Log("[ApexSystem] _Login called.");
646 if (login.Login.Length <= 0)
647 {
648 Debug.Log("[Login] No user name.");
649 return false;
650 }
651
652 if(login.Password.Length <= 0)
653 {
654 Debug.Log("[Login] No password.");
655 login.Password = "<empty>";
657
658 if(apexAPIHandler == null)
659 {
660 Debug.Log("[ApexSystem] API Handler is null.");
662
663 apexAPIHandler.Login(login);
664
665 Debug.Log("[ApexSystem] Login called.");
666
667 return true;
668 }
669
670 protected bool _Login(string username, string password)
671 {
672 return _Login(new LoginData(username, password));
674
675 public void _ParsePassedData()
676 {
677 AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
678
679 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
680
681 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");
682
683 string urlData = intent.Call<string>("getDataString");
684
685 Debug.Log("[ApexSystem] Parsed Passed Data.");
686 if(urlData != null && urlData.Length > 0)
687 {
688 Debug.Log("[ApexSystem] Parse from URL.");
689 _ParseUrlData(urlData);
690 }
691 else
692 {
693 Debug.Log("[ApexSystem] Parsing from extras.");
694 optionalParameter = intent.Call<string>("getStringExtra", "optional");
695 returnTargetParameter = intent.Call<string>("getStringExtra", "returntarget");
696 targetTypeParameter = intent.Call<string>("getStringExtra", "targettype");
697 }
698 }
699
700 public void _ParseUrlData(string urlString)
701 {
702 string urlData = urlString.Substring(urlString.IndexOf('?') + 1);
703
704
705 if (urlData.Length <= 0)
706 return;
707
708 string[] dataArray = urlData.Split('&');
709
710 if (dataArray.Length <= 0)
711 return;
712
713 foreach(string dataElement in dataArray)
714 {
715 string[] dataParts = dataElement.Split('=');
716
717 if (dataParts.Length <= 1)
718 continue;
719
720 if(dataParts[0].Equals("optional", StringComparison.OrdinalIgnoreCase))
721 {
722 optionalParameter = dataParts[1];
723 }
724
725 if (dataParts[0].Equals("returntarget", StringComparison.OrdinalIgnoreCase))
726 {
727 returnTargetParameter = dataParts[1];
728 }
729
730 if (dataParts[0].Equals("targettype", StringComparison.OrdinalIgnoreCase))
731 {
732 targetTypeParameter = dataParts[1];
733 }
734 }
735 }
736
737 public string _GetAuthenticationToken()
738 {
739 AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
740
741 AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
742
743 AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");
744
745 string ExtraString = intent.Call<string>("getStringExtra", "pixotoken");
746
747 return ExtraString;
748 }
749
750 public bool _CheckModuleAccess(int targetModuleID = -1)
751 {
752 Debug.Log("[ApexSystem] _CheckModuleAccess called.");
753
754 if (currentActiveLogin == null)
755 {
756 Debug.LogError("[ApexSystem] Cannot check user's module access with no active login.");
757 return false;
758 }
759
760 if (targetModuleID <= -1)
761 {
762 targetModuleID = moduleID;
763 }
764
766
767 return true;
768 }
769
770 protected bool _JoinSession(string newScenarioID = null, Extension contextExtension = null)
771 {
772 if (currentActiveLogin == null)
773 {
774 Debug.LogError("[ApexSystem] Cannot join session with no active login.");
775 return false;
776 }
777
778 if(userAccessVerified == false)
779 {
780 return false;
781 }
782
783 if (newScenarioID != null)
784 {
785 scenarioID = newScenarioID;
786 }
787
788 if (sessionInProgress == true)
789 {
790 Debug.LogError("[ApexSystem] Session is already in progress." +
791 " The previous session didn't complete or a new session was started during an active session.");
792 }
793
794 currentSessionID = Guid.NewGuid();
795
796 Statement sessionStatement = new Statement();
797 Agent sessionActor = new Agent();
798 sessionActor.mbox = currentActiveLogin.Email;
799
800 Verb sessionVerb = new Verb();
801 sessionVerb.id = ApexVerbs.JOINED_SESSION;
802 sessionVerb.display = new LanguageMap();
803 sessionVerb.display.Add("en", "Joined Session");
804
805 Activity sessionActivity = new Activity();
806 sessionActivity.id = string.Format("https://pixovr.com/xapi/objects/{0}/{1}", moduleID, scenarioID);
807
808 Context sessionContext = new Context();
809 sessionContext.registration = currentSessionID;
810 sessionContext.revision = moduleVersion;
811 sessionContext.platform = platform;
812
813 sessionContext.extensions = AppendStandardContextExtension(contextExtension);
814
815 sessionStatement.actor = sessionActor;
816 sessionStatement.verb = sessionVerb;
817 sessionStatement.target = sessionActivity;
818 sessionStatement.context = sessionContext;
819
820 JoinSessionData sessionData = new JoinSessionData();
821 sessionData.DeviceId = deviceID;
822 sessionData.IpAddress = clientIP;
823 sessionData.ModuleId = moduleID;
824 sessionData.Uuid = currentSessionID.ToString();
825 sessionData.EventType = ApexEventTypes.PIXOVR_SESSION_JOINED;
826 sessionData.JsonData = sessionStatement;
827
829
830 return true;
831 }
832
833 protected bool _SendSimpleSessionEvent(string verbName, string targetObject, Extension contextExtension)
834 {
835 if (userAccessVerified == false)
836 return false;
837
838 if (verbName == null)
839 return false;
840
841 if (verbName.Length == 0)
842 return false;
843
844
845 Statement sessionStatement = new Statement();
846 Agent sessionActor = new Agent();
847 sessionActor.mbox = currentActiveLogin.Email;
848
849 Verb sessionVerb = new Verb();
850 sessionVerb.id = new Uri("https://pixovr.com/xapi/verbs/" + verbName.Replace(' ', '_').ToLower());
851 sessionVerb.display = new LanguageMap();
852 sessionVerb.display.Add("en", verbName);
853
854 Activity sessionActivity = new Activity();
855 sessionActivity.id = string.Format("https://pixovr.com/xapi/objects/{0}/{1}/{2}", moduleID, scenarioID, targetObject.Replace(' ', '_').ToLower());
856
857 Context sessionContext = new Context();
858 sessionContext.registration = currentSessionID;
859 sessionContext.revision = moduleVersion;
860 sessionContext.platform = platform;
861
862 sessionContext.extensions = AppendStandardContextExtension(contextExtension);
864 sessionStatement.actor = sessionActor;
865 sessionStatement.verb = sessionVerb;
866 sessionStatement.target = sessionActivity;
867 sessionStatement.context = sessionContext;
868
869 SessionEventData sessionEvent = new SessionEventData();
870 sessionEvent.DeviceId = deviceID;
871 sessionEvent.ModuleId = ModuleID;
872 sessionEvent.Uuid = currentSessionID.ToString();
873 sessionEvent.EventType = ApexEventTypes.PIXOVR_SESSION_EVENT;
874 sessionEvent.JsonData = sessionStatement;
875
877
878 return true;
879 }
880
881 protected bool _SendSessionEvent(Statement eventStatement)
882 {
883 if (userAccessVerified == false)
884 {
885 return false;
886 }
887
888 if (currentActiveLogin == null)
889 {
890 Debug.LogError("[ApexSystem] Cannot send a session event with no active login.");
891 return false;
892 }
893
894 if (sessionInProgress == false)
895 {
896 Debug.LogError("[ApexSystem] No session in progress to send event for.");
897 return false;
898 }
899
900 if(eventStatement == null)
901 {
902 Debug.LogError("[ApexSystem] No event data to send.");
903 return false;
904 }
905
906 if(eventStatement.actor != null)
907 {
908 Debug.LogWarning("[ApexSystem] Actor data should not be filled out.");
909 }
910
911 if(eventStatement.verb == null)
912 {
913 Debug.LogError("[ApexSystem] Verb missing from eventStatement.");
914 return false;
915 }
916
917 if(eventStatement.verb.id == null)
918 {
919 Debug.LogError("[ApexSystem] verb.id missing from eventStatement.");
920 return false;
921 }
922
923 if(eventStatement.target == null)
924 {
925 Debug.LogError("[ApexSystem] Object (target) missing from eventStatement.");
926 return false;
927 }
928
929 eventStatement.actor = new Agent();
930 eventStatement.actor.mbox = currentActiveLogin.Email;
931
932 if (eventStatement.context == null)
933 {
934 eventStatement.context = new Context();
935 }
936
937 eventStatement.context.registration = currentSessionID;
938 eventStatement.context.revision = ModuleVersion;
939 eventStatement.context.platform = platform;
940
941 eventStatement.context.extensions = AppendStandardContextExtension(eventStatement.context.extensions);
942
943 SessionEventData sessionEvent = new SessionEventData();
944 sessionEvent.DeviceId = deviceID;
945 sessionEvent.ModuleId = ModuleID;
946 sessionEvent.Uuid = currentSessionID.ToString();
947 sessionEvent.EventType = ApexEventTypes.PIXOVR_SESSION_EVENT;
948 sessionEvent.JsonData = eventStatement;
949
951
952 return true;
953 }
954
955 protected bool _CompleteSession(SessionData currentSessionData, Extension contextExtension, Extension resultExtension)
956 {
957 if (userAccessVerified == false)
958 {
959 return false;
960 }
961
962 if (currentActiveLogin == null)
963 {
964 Debug.LogError("[ApexSystem] Cannot complete session with no active login.");
965 return false;
966 }
967
968 if (sessionInProgress == false)
969 {
970 Debug.LogError("[ApexSystem] No session in progress to complete.");
971 return false;
972 }
973
974 // Create our actor
975 Agent sessionActor = new Agent();
976 sessionActor.mbox = currentActiveLogin.Email;
977
978 // Create our verb
979 Verb sessionVerb = new Verb();
980 sessionVerb.id = ApexVerbs.COMPLETED_SESSION;
981 sessionVerb.display = new LanguageMap();
982 sessionVerb.display.Add("en", "Completed Session");
983
984 // Create the session activity
985 Activity sessionActivity = new Activity();
986 sessionActivity.id = string.Format("https://pixovr.com/xapi/objects/{0}/{1}", moduleID, scenarioID);
987
988 // Create our context
989 Context sessionContext = new Context();
990 sessionContext.registration = currentSessionID;
991 sessionContext.revision = moduleVersion;
992 sessionContext.platform = platform;
993
994 sessionContext.extensions = AppendStandardContextExtension(contextExtension);
995
996 // Create our results
997 Result sessionResult = new Result();
998 sessionResult.completion = currentSessionData.Complete;
999 sessionResult.success = currentSessionData.Success;
1000 // Add score to the results
1001 sessionResult.score = new Score();
1002 sessionResult.score.min = currentSessionData.MinimumScore;
1003 sessionResult.score.max = currentSessionData.MaximumScore;
1004 sessionResult.score.raw = currentSessionData.Score;
1005 sessionResult.score.scaled = DetermineScaledScore(currentSessionData.ScaledScore, currentSessionData.Score, currentSessionData.MaximumScore);
1006 sessionResult.duration = TimeSpan.FromSeconds(currentSessionData.Duration);
1007 if(resultExtension != null)
1008 {
1009 sessionResult.extensions = new Extensions(resultExtension.ToJObject());
1010 }
1011
1012 // Create our statement and add the pieces
1013 Statement sessionStatement = new Statement();
1014 sessionStatement.actor = sessionActor;
1015 sessionStatement.verb = sessionVerb;
1016 sessionStatement.target = sessionActivity;
1017 sessionStatement.context = sessionContext;
1018 sessionStatement.result = sessionResult;
1019
1020 CompleteSessionData sessionData = new CompleteSessionData();
1021 sessionData.DeviceId = deviceID;
1022 sessionData.ModuleId = moduleID;
1023 sessionData.Uuid = currentSessionID.ToString();
1024 sessionData.EventType = ApexEventTypes.PIXOVR_SESSION_COMPLETE;
1025 sessionData.JsonData = sessionStatement;
1026 sessionData.SessionDuration = currentSessionData.Duration;
1027 sessionData.Score = currentSessionData.Score;
1028 sessionData.ScoreMin = currentSessionData.MinimumScore;
1029 sessionData.ScoreMax = currentSessionData.MaximumScore;
1030 sessionData.ScoreScaled = DetermineScaledScore(currentSessionData.ScaledScore, currentSessionData.Score, currentSessionData.MaximumScore);
1031
1033
1034 return true;
1035 }
1036
1037 protected bool _SendHeartbeat()
1038 {
1039 Debug.Log("Sending heartbeat...");
1040 if (!sessionInProgress)
1041 return false;
1042
1043 if (currentActiveLogin == null)
1044 return false;
1045
1047
1048 return true;
1049 }
1050
1051 protected bool _GetUser(int userId = -1)
1052 {
1053 if (currentActiveLogin == null)
1054 return false;
1055
1056 if (userId < 0)
1057 {
1058 userId = currentActiveLogin.ID;
1059 }
1060
1062 return true;
1063 }
1064
1065 protected bool _GetUserModules(int userId = -1)
1066 {
1068 return false;
1069
1070 if (userId < 0)
1071 {
1072 userId = currentActiveLogin.ID;
1073 }
1074
1076 return true;
1077 }
1078
1079 protected bool _GetModuleList()
1080 {
1082 return false;
1083
1085 return true;
1086 }
1087
1088 private float DetermineScaledScore(float scaledScore, float score, float maxScore)
1089 {
1090 float determinedScaledScore = scaledScore;
1091
1092 if(scaledScore < Mathf.Epsilon && score >= Mathf.Epsilon)
1093 {
1094 determinedScaledScore = (score / maxScore) * 100f;
1096
1097 return determinedScaledScore;
1098 }
1099
1100 private Extensions AppendStandardContextExtension(Extensions currentContextExtensions)
1101 {
1102 return AppendStandardContextExtension(new Extension(currentContextExtensions.ToJObject()));
1103 }
1104
1105 private Extensions AppendStandardContextExtension(Extension currentContextExtension)
1106 {
1107 Extension contextExtension;
1108 if (currentContextExtension != null)
1110 contextExtension = currentContextExtension;
1111 }
1112 else
1113 {
1114 contextExtension = new Extension();
1115 }
1116
1117 contextExtension.Add(ApexExtensionStrings.MODULE_ID, moduleID.ToString());
1118 contextExtension.AddSimple("device_id", deviceID);
1119 contextExtension.AddSimple("device_model", deviceModel);
1120 contextExtension.AddSimple("sdk_version", "unity-" + Utils.ApexUtils.GetSDKVersion());
1121
1122 return new Extensions(contextExtension.ToJObject());
1123 }
1124
1125 protected void OnAPIResponse(ResponseType response, HttpResponseMessage message, object responseData)
1126 {
1127 Debug.Log("[ApexSystem] On API Response");
1128 bool success = message.IsSuccessStatusCode;
1129 if(responseData is FailureResponse)
1131 success = success && (responseData is IFailure) && (!(responseData as FailureResponse).HasErrored());
1132 }
1133
1134 switch (response)
1136 case ResponseType.RT_PING:
1137 {
1138 if(success)
1139 {
1140 Debug.Log("[ApexSystem] Ping successful.");
1141 OnPingSuccess.Invoke(message);
1142 }
1143 else
1144 {
1145 Debug.Log("[ApexSystem] Ping failed.");
1146 OnPingFailed.Invoke(message);
1147 }
1148 break;
1149 }
1150 case ResponseType.RT_LOGIN:
1151 {
1152 Debug.Log("[ApexSystem] Calling to handle login.");
1153 HandleLogin(success, responseData);
1154 break;
1156 case ResponseType.RT_GET_USER:
1157 {
1158 if(success)
1159 {
1160 OnGetUserSuccess.Invoke(responseData as GetUserResponseContent);
1161 }
1162 else
1163 {
1164 FailureResponse failureData = responseData as FailureResponse;
1165 Debug.Log(string.Format("[ApexSystem] Failed to get user.\nError: {0}", failureData.Message));
1166 OnGetUserFailed.Invoke(responseData as FailureResponse);
1167 }
1168 break;
1169 }
1170 case ResponseType.RT_GET_USER_MODULES:
1171 {
1172 if (success)
1173 {
1174 OnGetUserModulesSuccess.Invoke(responseData as GetUserModulesResponse);
1175 }
1176 else
1177 {
1178 FailureResponse failureData = responseData as FailureResponse;
1179 Debug.Log(string.Format("[ApexSystem] Failed to get user.\nError: {0}", failureData.Message));
1180 OnGetUserFailed.Invoke(responseData as FailureResponse);
1181 }
1182 break;
1183 }
1184 case ResponseType.RT_SESSION_JOINED:
1185 {
1186 if(success)
1187 {
1188 JoinSessionResponse joinSessionResponse = responseData as JoinSessionResponse;
1189 Debug.Log(string.Format("[ApexSystem] Session Id is {0}.", joinSessionResponse.SessionId));
1190 heartbeatSessionID = joinSessionResponse.SessionId;
1191 sessionInProgress = true;
1192 OnJoinSessionSuccess.Invoke(message);
1193 }
1194 else
1195 {
1196 FailureResponse failureData = responseData as FailureResponse;
1197 Debug.Log(string.Format("[ApexSystem] Failed to join session.\nError: {0}", failureData.Message));
1198 currentSessionID = Guid.Empty;
1199 sessionInProgress = false;
1200 OnJoinSessionFailed.Invoke(responseData as FailureResponse);
1201 }
1202 break;
1203 }
1204 case ResponseType.RT_SESSION_COMPLETE:
1205 {
1206 if (success)
1207 {
1208 sessionInProgress = false;
1209 currentSessionID = Guid.Empty;
1210 OnCompleteSessionSuccess.Invoke(message);
1211 }
1212 else
1213 {
1214 FailureResponse failureData = responseData as FailureResponse;
1215 Debug.Log(string.Format("[ApexSystem] Failed to complete session.\nError: {0}", failureData.Message));
1216 OnCompleteSessionFailed.Invoke(responseData as FailureResponse);
1217 }
1218 break;
1219 }
1220 case ResponseType.RT_SESSION_EVENT:
1221 {
1222 if (success)
1223 {
1224 Debug.Log("[ApexSystem] Session event sent.");
1225 OnSendEventSuccess.Invoke(message);
1226 }
1227 else
1228 {
1229 FailureResponse failureData = responseData as FailureResponse;
1230 Debug.Log(string.Format("[ApexSystem] Failed to send session event.\nError: {0}", failureData.Message));
1231 OnSendEventFailed.Invoke(responseData as FailureResponse);
1232 }
1233 break;
1234 }
1235 case ResponseType.RT_GET_USER_ACCESS:
1236 {
1237 if (success)
1238 {
1239 var userAccessResponseContent = responseData as UserAccessResponseContent;
1240 if (userAccessResponseContent.Access)
1241 {
1242 if (userAccessResponseContent.PassingScore.HasValue)
1243 {
1244 currentActiveLogin.MinimumPassingScore = userAccessResponseContent.PassingScore.Value;
1245 }
1246
1247 userAccessVerified = true;
1249 }
1250 else
1251 {
1252 currentActiveLogin = null;
1253 userAccessVerified = false;
1255 {
1256 Error = "True",
1257 HttpCode = "401",
1258 Message = "User does not have access to module",
1259 });
1260 }
1261 }
1262 else
1263 {
1264 FailureResponse failureData = responseData as FailureResponse;
1265 Debug.Log(string.Format("[ApexSystem] Failed to get users module access data.\nError: {0}", failureData.Message));
1266
1267 OnModuleAccessFailed.Invoke(responseData as FailureResponse);
1268 }
1269 break;
1270 }
1271 case ResponseType.RT_GET_MODULES_LIST:
1272 {
1273 if(success)
1274 {
1275 OnGetOrganizationModulesSuccess.Invoke(responseData as List<OrgModule>);
1276 }
1277 else
1278 {
1279 FailureResponse failureData = responseData as FailureResponse;
1280 Debug.Log(string.Format("[ApexSystem] Failed to get org modules.\nError: {0}", failureData.Message));
1281
1282 OnGetOrganizationModulesFailed.Invoke(responseData as FailureResponse);
1283 }
1284
1285 break;
1286 }
1287 default:
1288 {
1289 break;
1290 }
1291 }
1292
1293 if(OnPlatformResponse != null)
1294 {
1295 OnPlatformResponse.Invoke(response, success, responseData);
1296 }
1297 }
1298
1299 protected void HandleLogin(bool successful, object responseData)
1300 {
1301 Debug.Log("[ApexSystem] Handling Login");
1302 userAccessVerified = false;
1303
1304 if (successful)
1305 {
1306 currentActiveLogin = responseData as LoginResponseContent;
1307
1308 OnLoginSuccess.Invoke();
1309
1311 {
1313 }
1314 }
1315 else
1316 {
1317 FailureResponse failureData = responseData as FailureResponse;
1318 Debug.Log(string.Format("[ApexSystem] Failed to log in.\nError: {0}", failureData.Message));
1319 OnLoginFailed.Invoke(responseData as FailureResponse);
1320 }
1321 }
1322
1323 void _ReturnToHub()
1324 {
1325 var token = currentActiveLogin.Token;
1326
1327 if(serverIP.Contains("apexsa.", StringComparison.CurrentCultureIgnoreCase) || serverIP.Contains("saudi.", StringComparison.CurrentCultureIgnoreCase))
1328 {
1329 Debug.Log($"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1330 Application.OpenURL($"pixovr://com.PixoVR.SA_TrainingAcademy?pixotoken={token}");
1331 }
1332 else
1333 {
1334 Debug.Log($"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1335 Application.OpenURL($"pixovr://com.PixoVR.PixoHub?pixotoken={token}");
1336 }
1337 }
1338
1340 {
1341 if(!webSocket.IsConnected())
1342 {
1344 }
1346 }
1347
1348 // TODO: Move to new plugin
1349 public static bool GenerateOneTimeLoginForCurrentUser()
1350 {
1351 if (Instance.currentActiveLogin == null)
1352 return false;
1354 return Instance._GenerateOneTimeLoginForUser(Instance.currentActiveLogin.ID);
1355 }
1356
1357 // TODO: Move to new plugin
1359 {
1360 if (currentActiveLogin == null)
1361 {
1362 Debug.LogError("[ApexSystem] No current user logged in.");
1363 return false;
1364 }
1365
1367 }
1368
1369 // TODO: Move to new plugin
1370 bool _GenerateOneTimeLoginForUser(int userId)
1371 {
1372 if (currentActiveLogin == null)
1373 {
1374 Debug.LogError("[ApexSystem] No user logged in to generate code.");
1375 return false;
1376 }
1377
1379 return true;
1380 }
1381 }
1382}
async void SendHeartbeat(string authToken, int sessionId)
async void GenerateAssistedLogin(string authToken, int userId)
async void GetUserModules(string authToken, int userId)
async void JoinSession(string authToken, JoinSessionData joinData)
async void LoginWithToken(string token)
async void CompleteSession(string authToken, CompleteSessionData completionData)
async void Login(LoginData login)
async void SendSessionEvent(string authToken, SessionEventData sessionEvent)
void SetPlatformEndpoint(string endpointUrl)
async void GetUserData(string authToken, int userId)
void SetWebEndpoint(string endpointUrl)
async void GetModuleAccess(int moduleId, int userId, string serialNumber)
async void GetModuleList(string authToken, string platform)
const string PIXOVR_SESSION_COMPLETE
const string PIXOVR_SESSION_EVENT
const string PIXOVR_SESSION_JOINED
static readonly string MODULE_ID
ApexWebsocket webSocket
string _GetAuthenticationToken()
OnHttpResponseEvent OnPingSuccess
Extensions AppendStandardContextExtension(Extensions currentContextExtensions)
bool runSetupOnAwake
[SerializeField]
static string PassedLoginToken
Definition ApexSystem.cs:86
static bool LoginCheckModuleAccess
Definition ApexSystem.cs:74
static bool GetCurrentUser()
static bool RunSetupOnAwake
Definition ApexSystem.cs:68
OnApexFailureEvent OnJoinSessionFailed
string GetPlatformEndpointFromPlatformTarget(PlatformServer target)
void _ChangePlatformServer(PlatformServer newServer)
int moduleID
[SerializeField]
static bool Login(string username, string password)
static string ModuleName
Definition ApexSystem.cs:44
OnHttpResponseEvent OnPingFailed
static bool SendSessionEvent(Statement eventStatement)
string GetWebEndpointFromPlatformTarget(PlatformServer target)
void OnAPIResponse(ResponseType response, HttpResponseMessage message, object responseData)
OnHttpResponseEvent OnJoinSessionSuccess
static void ReturnToHub()
OnApexFailureEvent OnGetUserFailed
OnAuthCodeReceived OnAuthorizationCodeReceived
OnGetOrgModulesSuccessEvent OnGetOrganizationModulesSuccess
bool _JoinSession(string newScenarioID=null, Extension contextExtension=null)
bool _Login(LoginData login)
static bool RequestAuthorizationCode()
bool _CompleteSession(SessionData currentSessionData, Extension contextExtension, Extension resultExtension)
PlatformResponse OnPlatformResponse
static bool GetUser(int userId=-1)
OnHttpResponseEvent OnCompleteSessionSuccess
string moduleVersion
[SerializeField]
string GetEndpointFromTarget(PlatformServer target)
bool _SendSimpleSessionEvent(string verbName, string targetObject, Extension contextExtension)
OnApexFailureEvent OnCompleteSessionFailed
OnLoginSuccessEvent OnLoginSuccess
void OnWebSocketConnectFailed(string reason)
static bool CheckModuleAccess(int targetModuleID=-1)
OnApexFailureEvent OnSendEventFailed
void OnWebSocketReceive(string data)
void HandleLogin(bool successful, object responseData)
static bool GetUserModules(int userId=-1)
static LoginResponseContent CurrentActiveLogin
Definition ApexSystem.cs:62
static bool SendSimpleSessionEvent(string action, string targetObject, Extension contextExtension)
static string ReturnTarget
Definition ApexSystem.cs:98
static string ServerIP
Definition ApexSystem.cs:32
static string TargetType
float DetermineScaledScore(float scaledScore, float score, float maxScore)
APIHandler apexAPIHandler
static bool GetCurrentUserModules()
Task< bool > socketConnectTask
static void ChangePlatformServer(PlatformServer newServer)
static string ModuleVersion
Definition ApexSystem.cs:50
static bool LoginWithToken()
bool _Login(string username, string password)
static bool JoinSession(string scenarioID=null, Extension contextExtension=null)
bool loginCheckModuleAccess
[SerializeField]
bool _GenerateOneTimeLoginForCurrentUser()
OnApexFailureEvent OnGetUserModulesFailed
bool _SendSessionEvent(Statement eventStatement)
OnApexFailureEvent OnLoginFailed
static void ExitApplication(string returnTarget, string returnTargetType)
static string GetAuthenticationToken()
static bool Login(LoginData login)
static string ScenarioID
Definition ApexSystem.cs:56
static string DeviceSerialNumber
Definition ApexSystem.cs:80
LoginResponseContent currentActiveLogin
bool _LoginWithToken(string token)
static readonly Regex VersionValidator
OnApexFailureEvent OnGetOrganizationModulesFailed
bool _GenerateOneTimeLoginForUser(int userId)
float heartbeatTime
[SerializeField]
OnApexFailureEvent OnModuleAccessFailed
void _ParseUrlData(string urlString)
static string OptionalData
Definition ApexSystem.cs:92
string scenarioID
[SerializeField]
OnModuleAccessSuccessEvent OnModuleAccessSuccess
bool _GetUser(int userId=-1)
OnGetUserSuccessEvent OnGetUserSuccess
OnHttpResponseEvent OnSendEventSuccess
static bool GenerateOneTimeLoginForCurrentUser()
bool _CheckModuleAccess(int targetModuleID=-1)
static bool CompleteSession(SessionData currentSessionData, Extension contextExtension=null, Extension resultExtension=null)
bool IsModuleVersionOnlyNumerical()
void _ExitApplication(string returnTarget, string returnTargetType)
string serverIP
[SerializeField]
void OnWebSocketClosed(System.Net.WebSockets.WebSocketCloseStatus reason)
static bool GetModulesList()
static bool LoginWithToken(string token)
PlatformServer PlatformTargetServer
OnGetUserModulesSuccessEvent OnGetUserModulesSuccess
Extensions AppendStandardContextExtension(Extension currentContextExtension)
string moduleName
[SerializeField]
bool IsModuleNonMajorVersionPartValid(string modulePart)
bool _GetUserModules(int userId=-1)
bool IsModuleMajorVersionPartValid(string modulePart)
static readonly Uri JOINED_SESSION
static readonly Uri COMPLETED_SESSION
async Task< bool > Connect(Uri endpoint, int attemptTries=3)
OnWebSocketReceive OnReceive
OnWebSocketConnectFailed OnConnectFailed
OnWebSocketClosed OnClosed
OnWebSocketConnectSuccessful OnConnectSuccess
[Serializable]
Definition ApexTypes.cs:150
static bool LaunchApp(string packageName, string[] extraKeys, string[] extraValues)
static string GetMacAddress()
Definition ApexUtils.cs:21
void Add(Uri key, string value)
void AddSimple(string key, string value)
override JObject ToJObject(TCAPIVersion version)
delegate void PlatformResponse(ResponseType type, bool wasSuccessful, object responseData)