### Query Home Assistant REST API using C# Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt Accesses the Home Assistant REST API to retrieve system information like timezone, unit systems, and all defined zones. It also demonstrates how to get entity states. Requires a HaRestApi client object with URL and token. Outputs are C# objects representing Home Assistant data. ```csharp // HomeAssistant.cs - Access Home Assistant REST API var haClient = new HaRestApi( url: "http://supervisor/core", token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ); // Get configured timezone string timezone = await haClient.GetTimeZone(); Log.Information("Home Assistant timezone: {0}", timezone); // Get unit system (metric or imperial) var unitSystem = await haClient.GetUnitSystem(); Log.Information("Length: {0}, Temperature: {1}, Pressure: {2}", unitSystem.Length, // "km" or "mi" unitSystem.Temperature, // "°C" or "°F" unitSystem.Pressure // "Pa" or "psi" ); // Get all defined zones var zones = await haClient.GetZones(); foreach (var zone in zones) { Log.Information("Zone: {0}, Lat: {1}, Lon: {2}, Radius: {3}m", zone.FriendlyName, zone.Latitude, zone.Longitude, zone.Radius ); } // Find which zone the car is in (ordered by distance) var carLocation = new Coordinate(51.5074, -0.1278); var matchingZones = await haClient.GetZonesAscending(carLocation); if (matchingZones.Any()) { var closestZone = matchingZones.First(); Log.Information("Car is in zone: {0}", closestZone.FriendlyName); } else { Log.Information("Car is away from all zones"); } // Get all entity states var states = await haClient.GetStates(); var carEntity = states.FirstOrDefault(s => s.EntityId == "sensor.fiat_500e_battery_level"); if (carEntity != null) { Log.Information("Current battery: {0}%", carEntity.State); var lastUpdate = carEntity.Attributes["last_update"]; } ``` -------------------------------- ### Send Remote Commands to Vehicle (C#) Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt Enables sending various remote commands to a vehicle, such as locking/unlocking doors, starting charging, and controlling HVAC. It utilizes the FiatClient to send commands identified by a command string, vehicle VIN, and a 4-digit PIN. Some commands, particularly dangerous ones, may require additional flags to be enabled. ```csharp // FiatClient.cs - Send remote commands to vehicle var fiatClient = new FiatClient("user@example.com", "password", FcaBrand.Fiat); await fiatClient.LoginAndKeepSessionAlive(); string vehicleVin = "WVWZZZ3CZ1234567"; string pin = "1234"; // 4-digit PIN from Uconnect account // Update battery status (DeepRefresh) await fiatClient.SendCommand( vin: vehicleVin, command: "DEEPREFRESH", pin: pin, action: "ev" ); // Update GPS location await fiatClient.SendCommand( vin: vehicleVin, command: "VF", pin: pin, action: "location" ); // Blink lights await fiatClient.SendCommand( vin: vehicleVin, command: "HBLF", pin: pin, action: "remote" ); // Start charging now await fiatClient.SendCommand( vin: vehicleVin, command: "CNOW", pin: pin, action: "ev/chargenow" ); // Unlock trunk await fiatClient.SendCommand( vin: vehicleVin, command: "ROTRUNKUNLOCK", pin: pin, action: "remote" ); // Lock trunk await fiatClient.SendCommand( vin: vehicleVin, command: "ROTRUNKLOCK", pin: pin, action: "remote" ); // HVAC preconditioning ON await fiatClient.SendCommand( vin: vehicleVin, command: "ROPRECOND", pin: pin, action: "remote" ); // Dangerous commands (require EnableDangerousCommands: true) // Unlock doors - RDU // Lock doors - RDL // HVAC preconditioning OFF - ROPRECOND (with IsDangerous flag) ``` -------------------------------- ### Simple MQTT Client Integration (C#) Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt A C# MQTT client demonstrating connection to a broker, publishing retained sensor data and JSON attributes, and subscribing to command topics. It includes automatic reconnection logic and message queuing for robustness when the connection is lost. ```csharp // SimpleMqttClient.cs - Connect and communicate via MQTT var mqttClient = new SimpleMqttClient( server: "192.168.1.100", port: 1883, user: "mqtt_user", pass: "mqtt_pass", clientId: "FiatChamp", useTls: false ); // Connect to MQTT broker with auto-reconnect await mqttClient.Connect(); // Publish sensor data (retained) await mqttClient.Pub( topic: "homeassistant/sensor/car_battery/state", payload: "85" ); // Publish JSON attributes await mqttClient.Pub( topic: "homeassistant/sensor/car_location/attributes", payload: @"{ \"latitude\": 51.5074, \"longitude\": -0.1278, \"source_type\": \"gps\", \"gps_accuracy\": 2 }" ); // Subscribe to command topic await mqttClient.Sub( topic: "homeassistant/button/refresh_battery/set", callback: async (message) => { Log.Information("Received command: {0}", message); await fiatClient.SendCommand(vin, "DEEPREFRESH", pin, "ev"); } ); // The client automatically handles: // - Connection failures with 5-second retry delay // - Message queuing when disconnected // - Retained messages for sensors ``` -------------------------------- ### Create Home Assistant MQTT Entities using C# Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt Defines various Home Assistant entities such as sensors, device trackers, buttons, and switches using MQTT. It requires an MQTT client and a HaDevice object for configuration. Outputs are MQTT messages published to Home Assistant. ```csharp // HomeAssistant.cs - Define Home Assistant entities var haDevice = new HaDevice() { Name = "Fiat 500e", Identifier = "VIN_ABC123DEF456", Manufacturer = "FIAT", Model = "500e", Version = "1.0" }; // Battery sensor with device class var batterySensor = new HaSensor(mqttClient, "battery_level", haDevice) { Value = "85", DeviceClass = "battery", Unit = "%" }; await batterySensor.Announce(); await batterySensor.PublishState(); // Distance sensor with automatic km to miles conversion var odometerSensor = new HaSensor(mqttClient, "odometer", haDevice) { Value = "15000", DeviceClass = "distance", Unit = "km" }; await odometerSensor.Announce(); await odometerSensor.PublishState(); // Device tracker for location var locationTracker = new HaDeviceTracker(mqttClient, "car_location", haDevice) { Lat = 51.5074, Lon = -0.1278, StateValue = "home" // or zone name or "away" }; await locationTracker.Announce(); await locationTracker.PublishState(); // Button for triggering commands var refreshButton = new HaButton(mqttClient, "refresh_battery", haDevice, async button => { await fiatClient.SendCommand(vin, "DEEPREFRESH", pin, "ev"); Log.Information("Battery refresh triggered"); }); await refreshButton.Announce(); // Switch for toggling features var hvacSwitch = new HaSwitch(mqttClient, "hvac", haDevice, async sw => { var command = sw.IsOn ? "ROPRECOND" : "ROPRECOND"; await fiatClient.SendCommand(vin, command, pin, "remote"); Log.Information("HVAC {0}", sw.IsOn ? "enabled" : "disabled"); }); await hvacSwitch.Announce(); // Trunk lock switch var trunkSwitch = new HaSwitch(mqttClient, "trunk", haDevice, async sw => { var command = sw.IsOn ? "ROTRUNKUNLOCK" : "ROTRUNKLOCK"; await fiatClient.SendCommand(vin, command, pin, "remote"); }); await trunkSwitch.Announce(); ``` -------------------------------- ### C# Main Program Loop for Fiatchamp Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt The C# code defines the main execution loop for the Fiatchamp application. It initializes clients for Home Assistant, Fiat, and MQTT, then enters a loop to continuously fetch vehicle data. This includes refreshing battery and location, publishing vehicle location and sensor data, and creating interactive entities. Error handling and configurable refresh intervals are also implemented. ```csharp // Program.cs - Main execution loop var appConfig = builder.Configuration.Get(); var haClient = new HaRestApi(appConfig.HomeAssistantUrl, appConfig.SupervisorToken); var forceLoopResetEvent = new AutoResetEvent(false); IFiatClient fiatClient = new FiatClient( appConfig.FiatUser, appConfig.FiatPw, appConfig.Brand, appConfig.Region ); var mqttClient = new SimpleMqttClient( appConfig.MqttServer, appConfig.MqttPort, appConfig.MqttUser, appConfig.MqttPw, "FiatChamp" ); await mqttClient.Connect(); await fiatClient.LoginAndKeepSessionAlive(); while (!cancellationToken.IsCancellationRequested) { try { // Fetch all vehicles foreach (var vehicle in await fiatClient.Fetch()) { Log.Information("Processing vehicle: {0}", vehicle.Vin); // Auto-refresh if configured if (appConfig.AutoRefreshBattery) { await fiatClient.SendCommand(vehicle.Vin, "DEEPREFRESH", pin, "ev"); } if (appConfig.AutoRefreshLocation) { await fiatClient.SendCommand(vehicle.Vin, "VF", pin, "location"); } await Task.Delay(TimeSpan.FromSeconds(10)); // Create device var haDevice = new HaDevice() { Name = vehicle.Nickname ?? "Car", Identifier = vehicle.Vin, Manufacturer = vehicle.Make, Model = vehicle.ModelDescription, Version = "1.0" }; // Publish location var currentLocation = new Coordinate( vehicle.Location.Latitude, vehicle.Location.Longitude ); var zones = await haClient.GetZonesAscending(currentLocation); var tracker = new HaDeviceTracker(mqttClient, "car_location", haDevice) { Lat = currentLocation.Latitude.ToDouble(), Lon = currentLocation.Longitude.ToDouble(), StateValue = zones.FirstOrDefault()?.FriendlyName ?? "away" }; await tracker.Announce(); await tracker.PublishState(); // Publish all sensors from vehicle details var compactDetails = vehicle.Details.Compact("car"); var sensors = compactDetails.Select(detail => { var sensor = new HaSensor(mqttClient, detail.Key, haDevice) { Value = detail.Value }; // Auto-detect unit and device class if (detail.Key.EndsWith("_value")) { var unitKey = detail.Key.Replace("_value", "_unit"); compactDetails.TryGetValue(unitKey, out var unit); if (unit == "km" && appConfig.ConvertKmToMiles) { sensor.DeviceClass = "distance"; var kmValue = int.Parse(detail.Value); sensor.Value = Math.Round(kmValue * 0.62137, 2).ToString(); sensor.Unit = "mi"; } else { sensor.Unit = unit ?? ""; } } return sensor; }).ToList(); // Announce and publish all sensors await Parallel.ForEachAsync(sensors, async (sensor, _) => { await sensor.Announce(); }); await Task.Delay(TimeSpan.FromSeconds(5)); await Parallel.ForEachAsync(sensors, async (sensor, _) => { await sensor.PublishState(); }); // Create interactive entities (buttons and switches) var buttons = CreateInteractiveEntities(fiatClient, mqttClient, vehicle, haDevice); foreach (var button in buttons) { await button.Announce(); } } } catch (Exception e) { Log.Error("Error in main loop: {0}", e); } Log.Information("Next update in {0} minutes", appConfig.RefreshInterval); // Wait for next interval or manual trigger WaitHandle.WaitAny(new[] { cancellationToken.WaitHandle, forceLoopResetEvent }, TimeSpan.FromMinutes(appConfig.RefreshInterval)); } ``` -------------------------------- ### Standalone FiatChamp Docker Compose Configuration Source: https://github.com/wubbl0rz/fiatchamp/blob/master/README.md This snippet demonstrates how to configure FiatChamp to run in standalone mode using Docker Compose. It requires setting environment variables for user credentials, MQTT connection details, and operational parameters. This method is for advanced users managing Home Assistant as a self-managed Docker container. ```yaml version: "3.9" services: FiatChamp: image: ghcr.io/wubbl0rz/image-amd64-fiat-champ:3.0.4 environment: - 'STANDALONE=True' - 'FiatChamp_FiatUser=user@example.com' - 'FiatChamp_FiatPw=123456' - 'FiatChamp_FiatPin=9999' - 'FiatChamp_SupervisorToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI5NGFmMGJhZTFjYTQ0ODk2YWEzYjgzMGI5YmE4NGQxNiIsImlhdCI6MTY3MDA3Mjc - 'FiatChamp_StartDelaySeconds=1' - 'FiatChamp_Region=Europe' - 'FiatChamp_Brand=Fiat' - 'FiatChamp_CarUnknownLocation=Unknown' - 'FiatChamp_ConvertKmToMiles=False' - 'FiatChamp_MqttUser=mqtt' - 'FiatChamp_MqttPw=123456' - 'FiatChamp_MqttServer=192.168.2.132' - 'FiatChamp_MqttPort=1883' ``` -------------------------------- ### Home Assistant Addon Configuration for FiatChamp Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt This YAML configuration sets up the FiatChamp addon within Home Assistant. It includes essential parameters like user credentials, vehicle brand and region, refresh intervals, and options for enabling dangerous commands and overriding MQTT settings. Ensure sensitive information like passwords and PINs are handled securely. ```yaml # config.yaml - Home Assistant Addon Configuration name: "FiatChamp" version: "3.0.8" slug: "fiat_champ" services: - "mqtt:want" discovery: - "mqtt" options: FiatUser: "your.email@example.com" FiatPw: "yourPassword" FiatPin: "1234" Brand: "Fiat" Region: "Europe" RefreshInterval: 15 ConvertKmToMiles: false Debug: false AutoRefreshBattery: false AutoRefreshLocation: false EnableDangerousCommands: false CarUnknownLocation: "away" StartDelaySeconds: 1 schema: FiatUser: str FiatPw: password FiatPin: password? Brand: list(Fiat|Ram|Jeep|Dodge|AlfaRomeo) Region: list(Europe|America) ConvertKmToMiles: bool RefreshInterval: int Debug: bool AutoRefreshBattery: bool AutoRefreshLocation: bool EnableDangerousCommands: bool OverrideMqttUser: str? OverrideMqttPw: password? OverrideMqttServer: str? OverrideMqttPort: int? CarUnknownLocation: str StartDelaySeconds: int? arch: - amd64 - armv7 ``` -------------------------------- ### Standalone Docker Deployment Configuration for FiatChamp Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt This Docker Compose configuration allows running FiatChamp as a standalone container outside of the Home Assistant OS environment. It specifies the Docker image, environment variables for configuration (including credentials, MQTT settings, and vehicle details), and sets the restart policy. Note the use of environment variables prefixed with 'FiatChamp_' for standalone operation. ```yaml # docker-compose.yml - Standalone Docker Configuration version: "3.9" services: FiatChamp: image: ghcr.io/wubbl0rz/image-amd64-fiat-champ:3.0.4 environment: - 'STANDALONE=True' - 'FiatChamp_FiatUser=user@example.com' - 'FiatChamp_FiatPw=yourPassword123' - 'FiatChamp_FiatPin=9999' - 'FiatChamp_SupervisorToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI5NGFmMGJhZTFjYTQ0ODk2YWEzYjgzMGI5YmE4NGQxNiIsImlhdCI6MTY3MDA3Mjc' - 'FiatChamp_StartDelaySeconds=1' - 'FiatChamp_Region=Europe' - 'FiatChamp_Brand=Fiat' - 'FiatChamp_CarUnknownLocation=Unknown' - 'FiatChamp_ConvertKmToMiles=False' - 'FiatChamp_MqttUser=mqtt' - 'FiatChamp_MqttPw=mqtt123' - 'FiatChamp_MqttServer=192.168.1.100' - 'FiatChamp_MqttPort=1883' restart: unless-stopped ``` -------------------------------- ### C# FiatClient Authentication and Login Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt This C# code snippet demonstrates the core authentication flow for the FiatChamp client, connecting to FCA cloud services. It initializes a `FiatClient` with user credentials, brand, and region, then initiates a login process that includes bootstrapping authentication, obtaining JWT tokens, and exchanging them for AWS Cognito credentials. The session is automatically kept alive. ```csharp // FiatClient.cs - Initialize and authenticate with FCA API using FiatChamp; // Create client instance with credentials var fiatClient = new FiatClient( user: "user@example.com", password: "yourPassword", brand: FcaBrand.Fiat, region: FcaRegion.Europe ); // Supported brands and regions // FcaBrand: Fiat, Ram, Jeep, Dodge, AlfaRomeo // FcaRegion: Europe, America // Login and maintain session (automatically refreshes every 2 minutes) await fiatClient.LoginAndKeepSessionAlive(); // The login process: // 1. Bootstrap authentication with brand-specific API key // 2. Authenticate with user credentials // 3. Obtain JWT token // 4. Exchange JWT for AWS Cognito identity // 5. Get temporary AWS credentials for API access // 6. Automatically refresh session in background // Example: Jeep US configuration var jeepClient = new FiatClient( user: "jeep@example.com", password: "password123", brand: FcaBrand.Jeep, region: FcaRegion.America ); await jeepClient.LoginAndKeepSessionAlive(); ``` -------------------------------- ### Fetch Vehicle Data from FCA API (C#) Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt Retrieves comprehensive vehicle information, including status, battery, location, and telemetry, by calling the FCA API. It requires authentication and uses a FiatClient to fetch an array of Vehicle objects. The details are accessed as a JObject, allowing for flexible extraction of specific data points like battery level, odometer, charging status, and tire pressure. ```csharp // Program.cs - Fetch vehicle data from FCA API IFiatClient fiatClient = new FiatClient("user@example.com", "password", FcaBrand.Fiat); await fiatClient.LoginAndKeepSessionAlive(); // Fetch all vehicles on account Vehicle[] vehicles = await fiatClient.Fetch(); foreach (var vehicle in vehicles) { Log.Information("Found vehicle: {0}", vehicle.Vin); Log.Information("Nickname: {0}", vehicle.Nickname); Log.Information("Make: {0}, Model: {1}", vehicle.Make, vehicle.ModelDescription); // Vehicle details (JObject with nested data) var batteryLevel = vehicle.Details["evInfo"]["battery"]["stateOfCharge"]; var odometer = vehicle.Details["vehicleInfo"]["odometer"]["odometer"]["value"]; var chargingStatus = vehicle.Details["evInfo"]["battery"]["chargingStatus"]; var plugStatus = vehicle.Details["evInfo"]["battery"]["plugInStatus"]; var range = vehicle.Details["evInfo"]["battery"]["totalRange"]; Log.Information("Battery: {0}%, Charging: {1}, Range: {2}km", batteryLevel, chargingStatus, range); // Location data Log.Information("Location: {0}, {1}", vehicle.Location.Latitude, vehicle.Location.Longitude); // Tire pressure (array of 4 tires: FL, FR, RL, RR) var tires = vehicle.Details["vehicleInfo"]["tyrePressure"]; foreach (var tire in tires) { Log.Information("Tire {0}: {1} {2}", tire["type"], tire["pressure"]["value"], tire["pressure"]["unit"]); } } ``` -------------------------------- ### Fiat Remote Command Definitions (C#) Source: https://context7.com/wubbl0rz/fiatchamp/llms.txt Defines a set of static FiatCommand objects representing various remote vehicle operations. Each command has a message, an optional action, and a flag to indicate if it's dangerous. The class includes a utility method to safely send commands, checking the danger flag against application configuration. ```csharp // FiatCommand.cs - All available remote commands public class FiatCommand { // Battery and status refresh public static readonly FiatCommand DEEPREFRESH = new() { Action = "ev", Message = "DEEPREFRESH" }; // Location update public static readonly FiatCommand VF = new() { Action = "location", Message = "VF" }; // Blink headlights public static readonly FiatCommand HBLF = new() { Message = "HBLF" }; // Start charging immediately public static readonly FiatCommand CNOW = new() { Action = "ev/chargenow", Message = "CNOW" }; // HVAC preconditioning on public static readonly FiatCommand ROPRECOND = new() { Message = "ROPRECOND" }; // HVAC preconditioning off (dangerous) public static readonly FiatCommand ROPRECOND_OFF = new() { Message = "ROPRECOND", IsDangerous = true }; // Trunk unlock public static readonly FiatCommand ROTRUNKUNLOCK = new() { Message = "ROTRUNKUNLOCK" }; // Trunk lock public static readonly FiatCommand ROTRUNKLOCK = new() { Message = "ROTRUNKLOCK" }; // Remote door unlock (dangerous) public static readonly FiatCommand RDU = new() { Message = "RDU", IsDangerous = true }; // Remote door lock (dangerous) public static readonly FiatCommand RDL = new() { Message = "RDL", IsDangerous = true }; public bool IsDangerous { get; set; } public required string Message { get; init; } public string Action { get; init; } = "remote"; } // Usage with danger check async Task TrySendCommand(IFiatClient fiatClient, FiatCommand command, string vin) { if (command.IsDangerous && !appConfig.EnableDangerousCommands) { Log.Warning("{0} blocked - EnableDangerousCommands is disabled", command.Message); return false; } try { await fiatClient.SendCommand(vin, command.Message, pin, command.Action); return true; } catch (Exception e) { Log.Error("Command {0} failed: {1}", command.Message, e); return false; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.