Skip to content

Latest commit

 

History

History
366 lines (275 loc) · 8.69 KB

File metadata and controls

366 lines (275 loc) · 8.69 KB
Posseth Toyota Client logo

Getting Started

Table of Contents


Installation

Install the NuGet package:

dotnet add package Posseth.Toyota.Client

Or via NuGet Package Manager:

Install-Package Posseth.Toyota.Client

Standalone Usage (no DI)

If you are building a console app or any project that does not use a DI container, you can create the client directly using the fluent builder API:

using Posseth.Toyota.Client.Services;
using Posseth.Toyota.Client.Interfaces;

IMyToyotaClient client = new MyToyotaClient()
    .UseCredentials("your@email.com", "your-password")
    .UseTimeout(30)
    .UseTokenCaching(true)
    .UseLogger(msg => Console.WriteLine(msg));  // optional

var loginSuccess = await client.LoginAsync();
if (!loginSuccess)
    throw new InvalidOperationException("Login failed");

Get Vehicles

var vehicles = await client.GetVehiclesAsync();
if (vehicles?.Data != null)
{
    foreach (var vehicle in vehicles.Data)
    {
        Console.WriteLine($"VIN: {vehicle.Vin}, Name: {vehicle.Nickname}");
    }
}

Get Vehicle Status

var vin = "JTHJP5C27D5012345";
var location = await client.GetLocationAsync(vin);
Console.WriteLine($"Location: {location?.Data?.Latitude}, {location?.Data?.Longitude}");

var electric = await client.GetElectricAsync(vin);
Console.WriteLine($"Battery Level: {electric?.Data?.BatteryLevel}%");

Dependency Injection

Posseth.Toyota.Client ships with first-class support for the .NET Options pattern and Microsoft.Extensions.DependencyInjection.

The library exposes IMyToyotaClient as the public abstraction and provides AddToyotaClient() extension methods on IServiceCollection.

ASP.NET Core / Generic Host

Add the using directive once in Program.cs:

using Posseth.Toyota.Client.Extensions;

Option A — Inline lambda

Use the lambda overload when you want to configure the client directly in code, e.g. reading from environment variables or a secrets manager:

// Program.cs
builder.Services.AddToyotaClient(options =>
{
    options.Username       = builder.Configuration["Toyota:Username"]!;
    options.Password       = builder.Configuration["Toyota:Password"]!;
    options.TimeoutSeconds = 30;
    options.UseTokenCaching = true;
    options.Logger         = msg => Console.WriteLine(msg); // optional
});

Option B — appsettings.json binding

Add a dedicated section to your appsettings.json:

{
  "ToyotaClient": {
    "Username": "your@email.com",
    "Password": "your-password",
    "TimeoutSeconds": 30,
    "UseTokenCaching": true,
    "TokenCacheFilename": "toyota_token_cache.json"
  }
}

Then pass the section to AddToyotaClient:

// Program.cs
using Posseth.Toyota.Client;
using Posseth.Toyota.Client.Extensions;

builder.Services.AddToyotaClient(
    builder.Configuration.GetSection(ToyotaClientOptions.SectionName));

ToyotaClientOptions.SectionName is the string constant "ToyotaClient".


Injecting the client

Once registered, inject IMyToyotaClient into any service, controller, or minimal-API handler:

Constructor injection (recommended)

using Posseth.Toyota.Client.Interfaces;

public class VehicleService(IMyToyotaClient client)
{
    public async Task<string?> GetFirstVinAsync(CancellationToken ct = default)
    {
        await client.LoginAsync(ct);
        var vehicles = await client.GetVehiclesAsync(ct);
        return vehicles?.Data?.FirstOrDefault()?.Vin;
    }
}

Register the service and wire it up:

builder.Services.AddScoped<VehicleService>();

Minimal API

app.MapGet("/vehicles", async (IMyToyotaClient client, CancellationToken ct) =>
{
    await client.LoginAsync(ct);
    return await client.GetVehiclesAsync(ct);
});

IOptions<ToyotaClientOptions> — reading options directly

If you need to read the configured options elsewhere:

using Microsoft.Extensions.Options;
using Posseth.Toyota.Client;

public class MyDiagnosticsService(IOptions<ToyotaClientOptions> options)
{
    public string GetConfiguredUsername() => options.Value.Username;
}

Credentials management

Environment Recommended approach
Local development .NET Secret Manager
CI / staging Environment variables
Production Azure Key Vault / secrets provider

Never commit credentials to source control.
The token cache file (toyota_credentials_cache_contains_secrets.json by default) should also be added to .gitignore.


Common Tasks

Start Climate Control

var result = await client.StartClimateControlAsync(vin);
if (result?.IsSuccess == true)
    Console.WriteLine("Climate control started");

Lock Vehicle

var result = await client.SendRemoteCommandAsync(vin, RemoteCommandType.Lock);
if (result?.IsSuccess == true)
    Console.WriteLine("Vehicle locked");

Get Trip History

var trips = await client.GetTripsAsync(
    vin,
    from: DateOnly.FromDateTime(DateTime.Now.AddDays(-7)),
    to: DateOnly.FromDateTime(DateTime.Now),
    route: true,
    summary: true,
    limit: 50
);

foreach (var trip in trips?.Data ?? [])
    Console.WriteLine($"Trip: {trip.StartTime} - Distance: {trip.Distance}km");

Refresh Climate Status

var status = await client.RefreshClimateStatusAsync(vin);
Console.WriteLine($"Climate Status: {status?.Data?.Status}");

Configuration Options

Property Type Default Description
Username string MyToyota account e-mail
Password string MyToyota account password
TimeoutSeconds int 60 HTTP request timeout
UseTokenCaching bool true Cache the bearer token to disk
TokenCacheFilename string toyota_credentials_cache_contains_secrets.json Token cache file path
Logger Action<string>? null Optional diagnostic logger

Timeout

options.TimeoutSeconds = 60;

Logging

// Console
options.Logger = message => Console.WriteLine(message);

// Bridge to Microsoft.Extensions.Logging
options.Logger = message => logger.LogDebug("{Message}", message);

Token Caching

options.UseTokenCaching     = true;
options.TokenCacheFilename  = "my_tokens.json";

Cancellation

All async methods accept a CancellationToken:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

try
{
    var vehicles = await client.GetVehiclesAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation was cancelled");
}

Error Handling

try
{
    var result = await client.GetElectricAsync(vin);
}
catch (AuthenticationException ex)
{
    Console.WriteLine($"Authentication failed: {ex.Message}");
}
catch (ApiException ex)
{
    Console.WriteLine($"API error: {ex.Message}");
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation was cancelled");
}
catch (TimeoutException)
{
    Console.WriteLine("Request timeout");
}

Environment Variables

You can read credentials from environment variables to avoid hardcoding them:

// Standalone
var client = new MyToyotaClient()
    .UseCredentials(
        Environment.GetEnvironmentVariable("TOYOTA_USERNAME")
            ?? throw new InvalidOperationException("TOYOTA_USERNAME not set"),
        Environment.GetEnvironmentVariable("TOYOTA_PASSWORD")
            ?? throw new InvalidOperationException("TOYOTA_PASSWORD not set"));

// DI / lambda
builder.Services.AddToyotaClient(options =>
{
    options.Username = Environment.GetEnvironmentVariable("TOYOTA_USERNAME")
        ?? throw new InvalidOperationException("TOYOTA_USERNAME not set");
    options.Password = Environment.GetEnvironmentVariable("TOYOTA_PASSWORD")
        ?? throw new InvalidOperationException("TOYOTA_PASSWORD not set");
});