diff --git a/NOnStar.ConsoleApp/NOnStar.ConsoleApp.csproj b/NOnStar.ConsoleApp/NOnStar.ConsoleApp.csproj
new file mode 100644
index 0000000..1622ce3
--- /dev/null
+++ b/NOnStar.ConsoleApp/NOnStar.ConsoleApp.csproj
@@ -0,0 +1,12 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
diff --git a/NOnStar.ConsoleApp/Program.cs b/NOnStar.ConsoleApp/Program.cs
new file mode 100644
index 0000000..0bae94a
--- /dev/null
+++ b/NOnStar.ConsoleApp/Program.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace NOnStar.ConsoleApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ //must specify email address, password & PIN used for OnStar
+ var client = new OnStarClient("your_email_address", "onstar_password", "pin");
+
+ //Uncomment and try one:
+ //client.UnlockVehical().GetAwaiter().GetResult();
+ //client.LockVehical().GetAwaiter().GetResult();
+ //client.StartVehical().GetAwaiter().GetResult();
+ //client.StopVehical().GetAwaiter().GetResult();
+
+ Console.WriteLine("Done");
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/NOnStar.sln b/NOnStar.sln
new file mode 100644
index 0000000..a9198aa
--- /dev/null
+++ b/NOnStar.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2035
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NOnStar", "NOnStar\NOnStar.csproj", "{B2E505EC-2F16-4DF1-9AA9-80176658D455}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NOnStar.ConsoleApp", "NOnStar.ConsoleApp\NOnStar.ConsoleApp.csproj", "{F9E9AE6A-1D1F-4D25-8ECF-41A16E17707D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2E505EC-2F16-4DF1-9AA9-80176658D455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B2E505EC-2F16-4DF1-9AA9-80176658D455}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B2E505EC-2F16-4DF1-9AA9-80176658D455}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B2E505EC-2F16-4DF1-9AA9-80176658D455}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F9E9AE6A-1D1F-4D25-8ECF-41A16E17707D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F9E9AE6A-1D1F-4D25-8ECF-41A16E17707D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F9E9AE6A-1D1F-4D25-8ECF-41A16E17707D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F9E9AE6A-1D1F-4D25-8ECF-41A16E17707D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A727B3BB-C9A5-4273-A4B8-705522DE1F87}
+ EndGlobalSection
+EndGlobal
diff --git a/NOnStar/Auth.cs b/NOnStar/Auth.cs
new file mode 100644
index 0000000..a1f5756
--- /dev/null
+++ b/NOnStar/Auth.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar
+{
+ abstract class BaseAuth
+ {
+ public string nonce = GetNonce();
+ public string timestamp = GetTimestamp();
+
+ protected static string GetNonce()
+ {
+ return Guid.NewGuid().ToString("N").ToLower();
+ }
+
+ protected static string GetTimestamp()
+ {
+ return DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+ }
+ }
+
+ class DeviceAuth : BaseAuth
+ {
+ public string client_id;
+ public string device_id;
+ public string grant_type;
+ public string username;
+ public string password;
+ public string scope = "onstar gmoc commerce msso";
+ }
+
+
+ class PinAuth : BaseAuth
+ {
+ public string credential;
+ public string device_id;
+ public string scope = "onstar commerce";
+ public string credential_type = "PIN";
+ public string client_id;
+ }
+}
diff --git a/NOnStar/CommandAndControl/Body.cs b/NOnStar/CommandAndControl/Body.cs
new file mode 100644
index 0000000..b16c166
--- /dev/null
+++ b/NOnStar/CommandAndControl/Body.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.CommandAndControl
+{
+ class Body
+ {
+ public Error error { get; set; }
+ }
+}
diff --git a/NOnStar/CommandAndControl/CommandRequestStatus.cs b/NOnStar/CommandAndControl/CommandRequestStatus.cs
new file mode 100644
index 0000000..7d0c422
--- /dev/null
+++ b/NOnStar/CommandAndControl/CommandRequestStatus.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.CommandAndControl
+{
+ public class CommandRequestStatus
+ {
+ public bool Successful { get; internal set; }
+ public string ErrorMessage { get; internal set; }
+
+ public static CommandRequestStatus GetSuccessful()
+ {
+ return new CommandRequestStatus() { Successful = true };
+ }
+
+ public static CommandRequestStatus GetFailed(string errorMessage)
+ {
+ return new CommandRequestStatus() { Successful = false, ErrorMessage = errorMessage };
+ }
+ }
+
+ public class CommandRequestStatus : CommandRequestStatus
+ {
+ public T Content { get; internal set; }
+
+ public static CommandRequestStatus GetSuccessful(T content)
+ {
+ return new CommandRequestStatus() { Successful = true, Content = content };
+ }
+
+ public static new CommandRequestStatus GetFailed(string errorMessage)
+ {
+ return new CommandRequestStatus() { Successful = false, ErrorMessage = errorMessage };
+ }
+ }
+}
diff --git a/NOnStar/CommandAndControl/CommandResponse.cs b/NOnStar/CommandAndControl/CommandResponse.cs
new file mode 100644
index 0000000..9dbd7e9
--- /dev/null
+++ b/NOnStar/CommandAndControl/CommandResponse.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.CommandAndControl
+{
+ class CommandResponse
+ {
+ public DateTime requestTime { get; set; }
+ public DateTime completionTime { get; set; }
+ public string url { get; set; }
+ public string status { get; set; }
+ public string type { get; set; }
+ public Body body { get; set; }
+ }
+}
diff --git a/NOnStar/CommandAndControl/Error.cs b/NOnStar/CommandAndControl/Error.cs
new file mode 100644
index 0000000..2f22a56
--- /dev/null
+++ b/NOnStar/CommandAndControl/Error.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.CommandAndControl
+{
+ class Error
+ {
+ public string code { get; set; }
+ public string description { get; set; }
+ public string subCode { get; set; }
+ public string subCodeDescription { get; set; }
+ }
+}
diff --git a/NOnStar/CommandAndControl/OuterCommandResponse.cs b/NOnStar/CommandAndControl/OuterCommandResponse.cs
new file mode 100644
index 0000000..3d931a2
--- /dev/null
+++ b/NOnStar/CommandAndControl/OuterCommandResponse.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.CommandAndControl
+{
+ class OuterCommandResponse
+ {
+ public CommandResponse commandResponse { get; set; }
+ }
+}
diff --git a/NOnStar/ExtensionMethods.cs b/NOnStar/ExtensionMethods.cs
new file mode 100644
index 0000000..79f37e0
--- /dev/null
+++ b/NOnStar/ExtensionMethods.cs
@@ -0,0 +1,35 @@
+using JWT.Builder;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar
+{
+ static class ExtensionMethods
+ {
+ public static JwtBuilder AddClaims(this JwtBuilder builder, DeviceAuth deviceAuth)
+ {
+ return builder
+ .AddClaim("client_id", deviceAuth.client_id)
+ .AddClaim("device_id", deviceAuth.device_id)
+ .AddClaim("username", deviceAuth.username)
+ .AddClaim("password", deviceAuth.password)
+ .AddClaim("nonce", deviceAuth.nonce)
+ .AddClaim("timestamp", deviceAuth.timestamp)
+ .AddClaim("scope", deviceAuth.scope)
+ .AddClaim("grant_type", deviceAuth.grant_type);
+ }
+
+ public static JwtBuilder AddClaims(this JwtBuilder builder, PinAuth pinPayload)
+ {
+ return builder
+ .AddClaim("client_id", pinPayload.client_id)
+ .AddClaim("device_id", pinPayload.device_id)
+ .AddClaim("credential", pinPayload.credential)
+ .AddClaim("credential_type", pinPayload.credential_type)
+ .AddClaim("nonce", pinPayload.nonce)
+ .AddClaim("timestamp", pinPayload.timestamp)
+ .AddClaim("scope", pinPayload.scope);
+ }
+ }
+}
diff --git a/NOnStar/NOnStar.csproj b/NOnStar/NOnStar.csproj
new file mode 100644
index 0000000..5511535
--- /dev/null
+++ b/NOnStar/NOnStar.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netcoreapp2.0
+ NOnStar
+
+
+
+
+
+
+
diff --git a/NOnStar/OnStarClient.cs b/NOnStar/OnStarClient.cs
new file mode 100644
index 0000000..9c3bda9
--- /dev/null
+++ b/NOnStar/OnStarClient.cs
@@ -0,0 +1,266 @@
+using NOnStar.Types;
+using JWT;
+using JWT.Algorithms;
+using JWT.Builder;
+using JWT.Serializers;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using System.Linq;
+using NOnStar.CommandAndControl;
+
+namespace NOnStar
+{
+ public class OnStarClient
+ {
+ static string ClientId = "OMB_CVY_AND_3D0";
+ static string JwtSecretKey = "TAEJztOzgCYl4RyOtNvJ";
+ static string DeviceId = "bf479a40-1f6a-4677-a6de-88b45a46fbae"; //Make up your own GUID
+ string username;
+ string password;
+ string pin;
+
+ IJsonSerializer serializer;
+ IDateTimeProvider provider;
+ IJwtValidator validator;
+ IBase64UrlEncoder urlEncoder;
+ IJwtDecoder decoder;
+ HttpClient client;
+ Action logger = (message) => Console.WriteLine(message);
+
+ public OnStarClient(string username, string password, string pin)
+ {
+ this.username = username;
+ this.password = password;
+ this.pin = pin;
+
+ serializer = new JsonNetSerializer();
+ provider = new UtcDateTimeProvider();
+ validator = new JwtValidator(serializer, provider);
+ urlEncoder = new JwtBase64UrlEncoder();
+ decoder = new JwtDecoder(serializer, validator, urlEncoder);
+ }
+
+ public void SetupLogging(Action logger)
+ {
+ this.logger = logger;
+ }
+
+ #region Public Interface
+ public async Task StartVehical()
+ {
+ return await RequestCommand(KnownCommand.Start);
+ }
+
+ public async Task StopVehical()
+ {
+ return await RequestCommand(KnownCommand.CancelStart);
+ }
+
+ public async Task LockVehical()
+ {
+ return await RequestCommand(KnownCommand.LockDoor);
+ }
+
+ public async Task UnlockVehical()
+ {
+ return await RequestCommand(KnownCommand.UnlockDoor);
+ }
+
+ #endregion
+
+ //Model: Request command maps input command to type received from server, then Triggers command which involves monitoring it's success
+ private async Task RequestCommand(KnownCommand command)
+ {
+ try
+ {
+ var loginResponse = await LogInAndGetDetailedVehicalInfo();
+ var detailedVehicalInfoStatus = loginResponse as CommandRequestStatus;
+
+ if (detailedVehicalInfoStatus == null || detailedVehicalInfoStatus.Successful == false)
+ {
+ return loginResponse;
+ }
+ else
+ {
+ var startCommand = detailedVehicalInfoStatus.Content.vehicle.commands.command.FirstOrDefault(c => c.name == command);
+ await TriggerCommand(startCommand);
+ }
+ }
+ catch (Exception ex)
+ {
+ logger($"Failure executing command {command.Key} - {ex}");
+ }
+
+ return CommandRequestStatus.GetSuccessful();
+ }
+
+ private async Task> LogInAndGetDetailedVehicalInfo()
+ {
+ var authObject = new DeviceAuth()
+ {
+ client_id = ClientId,
+ device_id = DeviceId,
+ grant_type = "password",
+ username = username,
+ password = password,
+ };
+
+ CreateHttClient();
+
+ var loginResponse = await Login(authObject);
+ if (loginResponse.Successful == false)
+ {
+ return CommandRequestStatus.GetFailed(loginResponse.ErrorMessage);
+ }
+
+ logger("Getting vehicals...");
+ var getResponse = await client.GetAsync("https://api.gm.com/api/v1/account/vehicles");
+ var responseBody = await getResponse.Content.ReadAsStringAsync();
+ var vehicals = serializer.Deserialize(responseBody);
+
+ var firstCar = vehicals.vehicles.vehicle.First();
+
+ logger($"Getting detailed info on {firstCar.vin}");
+ var vehicalDetailsReply = await client.GetAsync($"https://api.gm.com/api/v1/account/vehicles/{firstCar.vin}?includeCommands=true&includeFeatures=true&includeDealers=true&includeCarrierAccount=true");
+ var vehicalDetailsString = await vehicalDetailsReply.Content.ReadAsStringAsync();
+ var detailedVehicalInfo = serializer.Deserialize(vehicalDetailsString);
+ foreach (var item in detailedVehicalInfo.vehicle.commands.command)
+ {
+ logger(item.name);
+ logger(item.description);
+ }
+
+ return CommandRequestStatus.GetSuccessful(detailedVehicalInfo);
+ }
+
+ private async Task TriggerCommand(Command command)
+ {
+ if (command.isPrivSessionRequired == true)
+ {
+ await Upgrade();
+ }
+
+ var monitoringUrl = await ExecuteCommand(command);
+
+ await MonitorCommand(monitoringUrl);
+ }
+
+ private async Task ExecuteCommand(Command command)
+ {
+ var content = GetStringContentBasedOnCommandType(command);
+ var startResult = await client.PostAsync(command.url, content);
+ var startResultStr = await startResult.Content.ReadAsStringAsync();
+
+ logger($"Command reply: {startResultStr}");
+
+ var commandResponse = serializer.Deserialize(startResultStr);
+
+ return commandResponse.commandResponse.url;
+ }
+
+ private async Task MonitorCommand(string monitoringUrl)
+ {
+ OuterCommandResponse commandResponse = null;
+ do
+ {
+ System.Threading.Thread.Sleep(5 * 1000);
+ var commandQueryResponse = await client.GetAsync(monitoringUrl);
+ var commandQueryResponseStr = await commandQueryResponse.Content.ReadAsStringAsync();
+ logger(commandQueryResponseStr);
+ commandResponse = serializer.Deserialize(commandQueryResponseStr);
+ } while (commandResponse.commandResponse.status == "inProgress");
+
+ if( commandResponse.commandResponse.status == "failure")
+ {
+ logger(commandResponse.commandResponse.body.error.description);
+
+ return CommandRequestStatus.GetFailed(commandResponse.commandResponse.body.error.description);
+ }
+ else
+ {
+ return CommandRequestStatus.GetSuccessful();
+ }
+ }
+
+ private StringContent GetStringContentBasedOnCommandType(Command command)
+ {
+ switch(command.name)
+ {
+ case "start":
+ case "cancelStart":
+ return new StringContent("{}");
+ case "lockDoor":
+ return new StringContent("{\"lockDoorRequest\":{\"delay\":0}}");
+ case "unlockDoor":
+ return new StringContent("{\"unlockDoorRequest\":{\"delay\":0}}");
+ default:
+ return new StringContent("{}");
+ }
+ }
+
+ private async Task Upgrade()
+ {
+ var pinPayload = new PinAuth() { client_id = ClientId, credential = pin, device_id = DeviceId };
+ var pinToken = new JwtBuilder()
+ .WithAlgorithm(new HMACSHA256Algorithm())
+ .AddClaims(pinPayload)
+ .WithSecret(JwtSecretKey)
+ .Build();
+
+ var pinUpgradeResult = await client.PostAsync("https://api.gm.com/api/v1/oauth/token/upgrade", new StringContent(pinToken));
+ var pinUpgradeResultStr = await pinUpgradeResult.Content.ReadAsStringAsync();
+ }
+
+ private async Task Login( DeviceAuth authObject)
+ {
+ var loginToken = new JwtBuilder()
+ .WithAlgorithm(new HMACSHA256Algorithm())
+ .AddClaims(authObject)
+ .WithSecret(JwtSecretKey)
+ .Build();
+
+ logger("Logging in...");
+ var result = await client.PostAsync("https://api.gm.com/api/v1/oauth/token", new StringContent(loginToken));
+
+ var loginResponse = await result.Content.ReadAsStringAsync();
+ logger($"Response Token: {loginResponse}");
+
+ if(loginResponse.Contains("error"))
+ {
+ var loginErrorResponse = serializer.Deserialize(loginResponse);
+ return new CommandRequestStatus() { Successful = false, ErrorMessage = loginErrorResponse.error };
+ }
+
+ logger(decoder.Decode(loginResponse, JwtSecretKey, verify: true));
+ var json = decoder.DecodeToObject(loginResponse, JwtSecretKey, verify: true);
+
+ AddAccessToken(json);
+
+ return new CommandRequestStatus() { Successful = true};
+ }
+
+ private void AddAccessToken(LoginReply json)
+ {
+ logger($"Token found: {json.access_token}");
+ client.DefaultRequestHeaders.Add("Authorization", $"Bearer {json.access_token}");
+ }
+
+ private void CreateHttClient()
+ {
+ client = new HttpClient();
+ client.DefaultRequestHeaders.Clear();
+ client.DefaultRequestHeaders.Add("Accept", "application/json");
+ client.DefaultRequestHeaders.Add("Accept-Language", "en");
+ client.DefaultRequestHeaders.Add("Host", "api.gm.com");
+ client.DefaultRequestHeaders.Add("Connection", "close");
+ client.DefaultRequestHeaders.Add("User-Agent", "okhttp/3.9.0");
+
+ ServicePointManager.Expect100Continue = true;
+ ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
+ }
+ }
+}
diff --git a/NOnStar/Types/Address.cs b/NOnStar/Types/Address.cs
new file mode 100644
index 0000000..848b30b
--- /dev/null
+++ b/NOnStar/Types/Address.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Address
+ {
+ public string addressLine1 { get; set; }
+ public string city { get; set; }
+ public string provinceOrStateCode { get; set; }
+ public string countryCode { get; set; }
+ public string postalCode { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Command.cs b/NOnStar/Types/Command.cs
new file mode 100644
index 0000000..906f288
--- /dev/null
+++ b/NOnStar/Types/Command.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Command
+ {
+ public string name { get; set; }
+ public string description { get; set; }
+ public string url { get; set; }
+ public bool isPrivSessionRequired { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Commands.cs b/NOnStar/Types/Commands.cs
new file mode 100644
index 0000000..475d20d
--- /dev/null
+++ b/NOnStar/Types/Commands.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Commands
+ {
+ public List command { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Dealer.cs b/NOnStar/Types/Dealer.cs
new file mode 100644
index 0000000..9920a45
--- /dev/null
+++ b/NOnStar/Types/Dealer.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Dealer
+ {
+ public string type { get; set; }
+ public string name { get; set; }
+ public string businessAssociateCode { get; set; }
+ public string active { get; set; }
+ public string phoneNo { get; set; }
+ public string faxNo { get; set; }
+ public string websiteURL { get; set; }
+ public Address address { get; set; }
+ public string dealerID { get; set; }
+ public string dealerCode { get; set; }
+ public string divisionCode { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Dealers.cs b/NOnStar/Types/Dealers.cs
new file mode 100644
index 0000000..f2fccbc
--- /dev/null
+++ b/NOnStar/Types/Dealers.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Dealers
+ {
+ public List dealer { get; set; }
+ }
+}
diff --git a/NOnStar/Types/DetailedVehialInfo.cs b/NOnStar/Types/DetailedVehialInfo.cs
new file mode 100644
index 0000000..60d44e0
--- /dev/null
+++ b/NOnStar/Types/DetailedVehialInfo.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class DetailedVehialInfo
+ {
+ public Vehicle vehicle { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Features.cs b/NOnStar/Types/Features.cs
new file mode 100644
index 0000000..2d31c43
--- /dev/null
+++ b/NOnStar/Types/Features.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Features
+ {
+ public List feature { get; set; }
+ }
+}
diff --git a/NOnStar/Types/InsuranceAgent.cs b/NOnStar/Types/InsuranceAgent.cs
new file mode 100644
index 0000000..d947f56
--- /dev/null
+++ b/NOnStar/Types/InsuranceAgent.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class InsuranceAgent
+ {
+ public Phone phone { get; set; }
+ }
+}
diff --git a/NOnStar/Types/InsuranceInfo.cs b/NOnStar/Types/InsuranceInfo.cs
new file mode 100644
index 0000000..7e31649
--- /dev/null
+++ b/NOnStar/Types/InsuranceInfo.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class InsuranceInfo
+ {
+ public InsuranceAgent insuranceAgent { get; set; }
+ }
+}
diff --git a/NOnStar/Types/KnownCommand.cs b/NOnStar/Types/KnownCommand.cs
new file mode 100644
index 0000000..03ecacb
--- /dev/null
+++ b/NOnStar/Types/KnownCommand.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class KnownCommand
+ {
+ public static KnownCommand CancelAlert = new KnownCommand("cancelAlert", "Cancel a vehicle alert(honk horns/flash lights).");
+ public static KnownCommand LockDoor = new KnownCommand("lockDoor", "Locks the doors.");
+ public static KnownCommand UnlockDoor = new KnownCommand("unlockDoor", "Unlocks the doors.");
+ public static KnownCommand Alert = new KnownCommand("alert", "Triggers a vehicle alert (honk horns/flash lights).");
+ public static KnownCommand Start = new KnownCommand("start", "Remotely starts the vehicle.");
+ public static KnownCommand CancelStart = new KnownCommand("cancelStart", "Cancels previous remote start command.");
+ public static KnownCommand SendNavDestination = new KnownCommand("sendNavDestination", "Calculate route and send it to the vehicle's nav unit.");
+ public static KnownCommand Connect = new KnownCommand("connect", "Initiates a connection to the vehicle");
+ public static KnownCommand EnableTelemetry = new KnownCommand("enableTelemetry", "Enrolls a vehicle in telemetry.");
+ public static KnownCommand DisableTelemetry = new KnownCommand("disableTelemetry", "Unenrolls a vehicle from telemetry..");
+
+ public string Key { get; set; }
+ public string Description { get; set; }
+
+ private KnownCommand(string key, string description)
+ {
+ this.Key = key;
+ this.Description = description;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ public static bool operator==(string key, KnownCommand command)
+ {
+ return key == command.Key;
+ }
+
+ public static bool operator !=(string key, KnownCommand command)
+ {
+ return key != command.Key;
+ }
+
+ public static bool operator ==(KnownCommand command, string key)
+ {
+ return key == command.Key;
+ }
+
+ public static bool operator !=(KnownCommand command, string key)
+ {
+ return key != command.Key;
+ }
+ }
+}
diff --git a/NOnStar/Types/LicensePlate.cs b/NOnStar/Types/LicensePlate.cs
new file mode 100644
index 0000000..634b8b2
--- /dev/null
+++ b/NOnStar/Types/LicensePlate.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class LicensePlate
+ {
+ public string plateNumber { get; set; }
+ public string country { get; set; }
+ public string provinceOrStateCode { get; set; }
+ }
+}
diff --git a/NOnStar/Types/LoginError.cs b/NOnStar/Types/LoginError.cs
new file mode 100644
index 0000000..1b4c02e
--- /dev/null
+++ b/NOnStar/Types/LoginError.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class LoginError
+ {
+ public string error { get; set; }
+ }
+}
diff --git a/NOnStar/Types/LoginReply.cs b/NOnStar/Types/LoginReply.cs
new file mode 100644
index 0000000..35aeced
--- /dev/null
+++ b/NOnStar/Types/LoginReply.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class LoginReply
+ {
+ public string access_token { get; set; }
+ public string token_type { get; set; }
+ public int expires_in { get; set; }
+ public string scope { get; set; }
+ public OnstarAccountInfo onstar_account_info { get; set; }
+ public UserInfo user_info { get; set; }
+ public string id_token { get; set; }
+ }
+}
diff --git a/NOnStar/Types/OnstarAccountInfo.cs b/NOnStar/Types/OnstarAccountInfo.cs
new file mode 100644
index 0000000..b9cb804
--- /dev/null
+++ b/NOnStar/Types/OnstarAccountInfo.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class OnstarAccountInfo
+ {
+ public string country_code { get; set; }
+ public string account_no { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Phone.cs b/NOnStar/Types/Phone.cs
new file mode 100644
index 0000000..e7d08ef
--- /dev/null
+++ b/NOnStar/Types/Phone.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Phone
+ {
+ }
+}
diff --git a/NOnStar/Types/UserInfo.cs b/NOnStar/Types/UserInfo.cs
new file mode 100644
index 0000000..261eb3e
--- /dev/null
+++ b/NOnStar/Types/UserInfo.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class UserInfo
+ {
+ public string RemoteUserId { get; set; }
+ public string country { get; set; }
+ }
+}
diff --git a/NOnStar/Types/VehicalList.cs b/NOnStar/Types/VehicalList.cs
new file mode 100644
index 0000000..ab45362
--- /dev/null
+++ b/NOnStar/Types/VehicalList.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class VehicalList
+ {
+ public Vehicles vehicles { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Vehicle.cs b/NOnStar/Types/Vehicle.cs
new file mode 100644
index 0000000..cc63f4d
--- /dev/null
+++ b/NOnStar/Types/Vehicle.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Vehicle
+ {
+ public string vin { get; set; }
+ public string make { get; set; }
+ public string model { get; set; }
+ public string year { get; set; }
+ public string manufacturer { get; set; }
+ public string phone { get; set; }
+ public string unitType { get; set; }
+ public string onstarStatus { get; set; }
+ public string url { get; set; }
+ public string isInPreActivation { get; set; }
+ public LicensePlate licensePlate { get; set; }
+ public InsuranceInfo insuranceInfo { get; set; }
+ public string enrolledInContinuousCoverage { get; set; }
+ public Commands commands { get; set; }
+ public Features features { get; set; }
+ public Dealers dealers { get; set; }
+ public string propulsionType { get; set; }
+ }
+}
diff --git a/NOnStar/Types/Vehicles.cs b/NOnStar/Types/Vehicles.cs
new file mode 100644
index 0000000..405d165
--- /dev/null
+++ b/NOnStar/Types/Vehicles.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NOnStar.Types
+{
+ class Vehicles
+ {
+ public string size { get; set; }
+ public List vehicle { get; set; }
+ }
+}