From 101cc9bd96300cf0d379f8a080088a31ebfa9455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sat, 2 Jul 2022 11:23:39 +0200 Subject: [PATCH 1/7] feat(Model): Add TeslaMate DB Model --- SmartTeslaAmpSetter.Model/Entities/Address.cs | 36 + SmartTeslaAmpSetter.Model/Entities/Car.cs | 37 + .../Entities/CarSetting.cs | 14 + SmartTeslaAmpSetter.Model/Entities/Charge.cs | 30 + .../Entities/ChargingProcess.cs | 35 + SmartTeslaAmpSetter.Model/Entities/Drive.cs | 43 + .../Entities/Geofence.cs | 26 + .../Entities/Position.cs | 45 ++ .../Entities/SchemaMigration.cs | 8 + SmartTeslaAmpSetter.Model/Entities/Setting.cs | 12 + SmartTeslaAmpSetter.Model/Entities/State.cs | 12 + SmartTeslaAmpSetter.Model/Entities/Token.cs | 11 + SmartTeslaAmpSetter.Model/Entities/Update.cs | 13 + .../SmartTeslaAmpSetter.Model.csproj | 17 + SmartTeslaAmpSetter.Model/TeslamateContext.cs | 754 ++++++++++++++++++ .../SolarEdgePlugin/CurrentValuesService.cs | 4 +- SmartTeslaAmpSetter.sln | 8 +- 17 files changed, 1102 insertions(+), 3 deletions(-) create mode 100644 SmartTeslaAmpSetter.Model/Entities/Address.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Car.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/CarSetting.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Charge.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Drive.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Geofence.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Position.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/SchemaMigration.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Setting.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/State.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Token.cs create mode 100644 SmartTeslaAmpSetter.Model/Entities/Update.cs create mode 100644 SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj create mode 100644 SmartTeslaAmpSetter.Model/TeslamateContext.cs diff --git a/SmartTeslaAmpSetter.Model/Entities/Address.cs b/SmartTeslaAmpSetter.Model/Entities/Address.cs new file mode 100644 index 000000000..9a929ef3f --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Address.cs @@ -0,0 +1,36 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Address + { + public Address() + { + ChargingProcesses = new HashSet(); + DriveEndAddresses = new HashSet(); + DriveStartAddresses = new HashSet(); + } + + public int Id { get; set; } + public string? DisplayName { get; set; } + public decimal? Latitude { get; set; } + public decimal? Longitude { get; set; } + public string? Name { get; set; } + public string? HouseNumber { get; set; } + public string? Road { get; set; } + public string? Neighbourhood { get; set; } + public string? City { get; set; } + public string? County { get; set; } + public string? Postcode { get; set; } + public string? State { get; set; } + public string? StateDistrict { get; set; } + public string? Country { get; set; } + public string? Raw { get; set; } + public DateTime InsertedAt { get; set; } + public DateTime UpdatedAt { get; set; } + public long? OsmId { get; set; } + public string? OsmType { get; set; } + + public virtual ICollection ChargingProcesses { get; set; } + public virtual ICollection DriveEndAddresses { get; set; } + public virtual ICollection DriveStartAddresses { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Car.cs b/SmartTeslaAmpSetter.Model/Entities/Car.cs new file mode 100644 index 000000000..0b8cd2dd4 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Car.cs @@ -0,0 +1,37 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Car + { + public Car() + { + ChargingProcesses = new HashSet(); + Drives = new HashSet(); + Positions = new HashSet(); + States = new HashSet(); + Updates = new HashSet(); + } + + public short Id { get; set; } + public long Eid { get; set; } + public long Vid { get; set; } + public string? Model { get; set; } + public double? Efficiency { get; set; } + public DateTime InsertedAt { get; set; } + public DateTime UpdatedAt { get; set; } + public string? Vin { get; set; } + public string? Name { get; set; } + public string? TrimBadging { get; set; } + public long SettingsId { get; set; } + public string? ExteriorColor { get; set; } + public string? SpoilerType { get; set; } + public string? WheelType { get; set; } + public short DisplayPriority { get; set; } + + public virtual CarSetting Settings { get; set; } = null!; + public virtual ICollection ChargingProcesses { get; set; } + public virtual ICollection Drives { get; set; } + public virtual ICollection Positions { get; set; } + public virtual ICollection States { get; set; } + public virtual ICollection Updates { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/CarSetting.cs b/SmartTeslaAmpSetter.Model/Entities/CarSetting.cs new file mode 100644 index 000000000..4f7188340 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/CarSetting.cs @@ -0,0 +1,14 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class CarSetting + { + public long Id { get; set; } + public int SuspendMin { get; set; } + public int SuspendAfterIdleMin { get; set; } + public bool ReqNotUnlocked { get; set; } + public bool FreeSupercharging { get; set; } + public bool? UseStreamingApi { get; set; } + + public virtual Car Car { get; set; } = null!; + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Charge.cs b/SmartTeslaAmpSetter.Model/Entities/Charge.cs new file mode 100644 index 000000000..c26986112 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Charge.cs @@ -0,0 +1,30 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Charge + { + public int Id { get; set; } + public DateTime Date { get; set; } + public bool? BatteryHeaterOn { get; set; } + public short? BatteryLevel { get; set; } + public decimal ChargeEnergyAdded { get; set; } + public short? ChargerActualCurrent { get; set; } + public short? ChargerPhases { get; set; } + public short? ChargerPilotCurrent { get; set; } + public short ChargerPower { get; set; } + public short? ChargerVoltage { get; set; } + public bool? FastChargerPresent { get; set; } + public string? ConnChargeCable { get; set; } + public string? FastChargerBrand { get; set; } + public string? FastChargerType { get; set; } + public decimal IdealBatteryRangeKm { get; set; } + public bool? NotEnoughPowerToHeat { get; set; } + public decimal? OutsideTemp { get; set; } + public int ChargingProcessId { get; set; } + public bool? BatteryHeater { get; set; } + public bool? BatteryHeaterNoPower { get; set; } + public decimal? RatedBatteryRangeKm { get; set; } + public short? UsableBatteryLevel { get; set; } + + public virtual ChargingProcess ChargingProcess { get; set; } = null!; + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs b/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs new file mode 100644 index 000000000..8a4850ce5 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs @@ -0,0 +1,35 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class ChargingProcess + { + public ChargingProcess() + { + Charges = new HashSet(); + } + + public int Id { get; set; } + public DateTime StartDate { get; set; } + public DateTime? EndDate { get; set; } + public decimal? ChargeEnergyAdded { get; set; } + public decimal? StartIdealRangeKm { get; set; } + public decimal? EndIdealRangeKm { get; set; } + public short? StartBatteryLevel { get; set; } + public short? EndBatteryLevel { get; set; } + public short? DurationMin { get; set; } + public decimal? OutsideTempAvg { get; set; } + public short CarId { get; set; } + public int PositionId { get; set; } + public int? AddressId { get; set; } + public decimal? StartRatedRangeKm { get; set; } + public decimal? EndRatedRangeKm { get; set; } + public int? GeofenceId { get; set; } + public decimal? ChargeEnergyUsed { get; set; } + public decimal? Cost { get; set; } + + public virtual Address? Address { get; set; } + public virtual Car Car { get; set; } = null!; + public virtual Geofence? Geofence { get; set; } + public virtual Position Position { get; set; } = null!; + public virtual ICollection Charges { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Drive.cs b/SmartTeslaAmpSetter.Model/Entities/Drive.cs new file mode 100644 index 000000000..a51c14c9d --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Drive.cs @@ -0,0 +1,43 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Drive + { + public Drive() + { + Positions = new HashSet(); + } + + public int Id { get; set; } + public DateTime StartDate { get; set; } + public DateTime? EndDate { get; set; } + public decimal? OutsideTempAvg { get; set; } + public short? SpeedMax { get; set; } + public short? PowerMax { get; set; } + public short? PowerMin { get; set; } + public decimal? StartIdealRangeKm { get; set; } + public decimal? EndIdealRangeKm { get; set; } + public double? StartKm { get; set; } + public double? EndKm { get; set; } + public double? Distance { get; set; } + public short? DurationMin { get; set; } + public short CarId { get; set; } + public decimal? InsideTempAvg { get; set; } + public int? StartAddressId { get; set; } + public int? EndAddressId { get; set; } + public decimal? StartRatedRangeKm { get; set; } + public decimal? EndRatedRangeKm { get; set; } + public int? StartPositionId { get; set; } + public int? EndPositionId { get; set; } + public int? StartGeofenceId { get; set; } + public int? EndGeofenceId { get; set; } + + public virtual Car Car { get; set; } = null!; + public virtual Address? EndAddress { get; set; } + public virtual Geofence? EndGeofence { get; set; } + public virtual Position? EndPosition { get; set; } + public virtual Address? StartAddress { get; set; } + public virtual Geofence? StartGeofence { get; set; } + public virtual Position? StartPosition { get; set; } + public virtual ICollection Positions { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Geofence.cs b/SmartTeslaAmpSetter.Model/Entities/Geofence.cs new file mode 100644 index 000000000..66f8f4980 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Geofence.cs @@ -0,0 +1,26 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Geofence + { + public Geofence() + { + ChargingProcesses = new HashSet(); + DriveEndGeofences = new HashSet(); + DriveStartGeofences = new HashSet(); + } + + public int Id { get; set; } + public string Name { get; set; } = null!; + public decimal Latitude { get; set; } + public decimal Longitude { get; set; } + public short Radius { get; set; } + public DateTime InsertedAt { get; set; } + public DateTime UpdatedAt { get; set; } + public decimal? CostPerUnit { get; set; } + public decimal? SessionFee { get; set; } + + public virtual ICollection ChargingProcesses { get; set; } + public virtual ICollection DriveEndGeofences { get; set; } + public virtual ICollection DriveStartGeofences { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Position.cs b/SmartTeslaAmpSetter.Model/Entities/Position.cs new file mode 100644 index 000000000..b38a95a4a --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Position.cs @@ -0,0 +1,45 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Position + { + public Position() + { + ChargingProcesses = new HashSet(); + DriveEndPositions = new HashSet(); + DriveStartPositions = new HashSet(); + } + + public int Id { get; set; } + public DateTime Date { get; set; } + public decimal Latitude { get; set; } + public decimal Longitude { get; set; } + public short? Speed { get; set; } + public short? Power { get; set; } + public double? Odometer { get; set; } + public decimal? IdealBatteryRangeKm { get; set; } + public short? BatteryLevel { get; set; } + public decimal? OutsideTemp { get; set; } + public short? Elevation { get; set; } + public int? FanStatus { get; set; } + public decimal? DriverTempSetting { get; set; } + public decimal? PassengerTempSetting { get; set; } + public bool? IsClimateOn { get; set; } + public bool? IsRearDefrosterOn { get; set; } + public bool? IsFrontDefrosterOn { get; set; } + public short CarId { get; set; } + public int? DriveId { get; set; } + public decimal? InsideTemp { get; set; } + public bool? BatteryHeater { get; set; } + public bool? BatteryHeaterOn { get; set; } + public bool? BatteryHeaterNoPower { get; set; } + public decimal? EstBatteryRangeKm { get; set; } + public decimal? RatedBatteryRangeKm { get; set; } + public short? UsableBatteryLevel { get; set; } + + public virtual Car Car { get; set; } = null!; + public virtual Drive? Drive { get; set; } + public virtual ICollection ChargingProcesses { get; set; } + public virtual ICollection DriveEndPositions { get; set; } + public virtual ICollection DriveStartPositions { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/SchemaMigration.cs b/SmartTeslaAmpSetter.Model/Entities/SchemaMigration.cs new file mode 100644 index 000000000..b713c8ff3 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/SchemaMigration.cs @@ -0,0 +1,8 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class SchemaMigration + { + public long Version { get; set; } + public DateTime? InsertedAt { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Setting.cs b/SmartTeslaAmpSetter.Model/Entities/Setting.cs new file mode 100644 index 000000000..93249311b --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Setting.cs @@ -0,0 +1,12 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Setting + { + public long Id { get; set; } + public DateTime InsertedAt { get; set; } + public DateTime UpdatedAt { get; set; } + public string? BaseUrl { get; set; } + public string? GrafanaUrl { get; set; } + public string Language { get; set; } = null!; + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/State.cs b/SmartTeslaAmpSetter.Model/Entities/State.cs new file mode 100644 index 000000000..d64f48b6e --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/State.cs @@ -0,0 +1,12 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class State + { + public int Id { get; set; } + public DateTime StartDate { get; set; } + public DateTime? EndDate { get; set; } + public short CarId { get; set; } + + public virtual Car Car { get; set; } = null!; + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Token.cs b/SmartTeslaAmpSetter.Model/Entities/Token.cs new file mode 100644 index 000000000..6bc394571 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Token.cs @@ -0,0 +1,11 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Token + { + public int Id { get; set; } + public string Access { get; set; } = null!; + public string Refresh { get; set; } = null!; + public DateTime InsertedAt { get; set; } + public DateTime UpdatedAt { get; set; } + } +} diff --git a/SmartTeslaAmpSetter.Model/Entities/Update.cs b/SmartTeslaAmpSetter.Model/Entities/Update.cs new file mode 100644 index 000000000..b04408831 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Entities/Update.cs @@ -0,0 +1,13 @@ +namespace SmartTeslaAmpSetter.Model.Entities +{ + public class Update + { + public int Id { get; set; } + public DateTime StartDate { get; set; } + public DateTime? EndDate { get; set; } + public string? Version { get; set; } + public short CarId { get; set; } + + public virtual Car Car { get; set; } = null!; + } +} diff --git a/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj b/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj new file mode 100644 index 000000000..4b2987ebd --- /dev/null +++ b/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj @@ -0,0 +1,17 @@ + + + + net6.0 + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/SmartTeslaAmpSetter.Model/TeslamateContext.cs b/SmartTeslaAmpSetter.Model/TeslamateContext.cs new file mode 100644 index 000000000..e872ec85b --- /dev/null +++ b/SmartTeslaAmpSetter.Model/TeslamateContext.cs @@ -0,0 +1,754 @@ +using Microsoft.EntityFrameworkCore; +using SmartTeslaAmpSetter.Model.Entities; + +namespace SmartTeslaAmpSetter.Model +{ + public class TeslamateContext : DbContext + { + public TeslamateContext() + { + } + + public TeslamateContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet
Addresses { get; set; } = null!; + public virtual DbSet Cars { get; set; } = null!; + public virtual DbSet CarSettings { get; set; } = null!; + public virtual DbSet Charges { get; set; } = null!; + public virtual DbSet ChargingProcesses { get; set; } = null!; + public virtual DbSet Drives { get; set; } = null!; + public virtual DbSet Geofences { get; set; } = null!; + public virtual DbSet Positions { get; set; } = null!; + public virtual DbSet SchemaMigrations { get; set; } = null!; + public virtual DbSet Settings { get; set; } = null!; + public virtual DbSet States { get; set; } = null!; + public virtual DbSet Tokens { get; set; } = null!; + public virtual DbSet Updates { get; set; } = null!; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + //optionsBuilder.UseNpgsql("Host=192.168.1.50;Port=5433;Database=teslamate;Username=teslamate;Password=secret"); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.HasPostgresEnum("billing_type", new[] { "per_kwh", "per_minute" }) + .HasPostgresEnum("range", new[] { "ideal", "rated" }) + .HasPostgresEnum("states_status", new[] { "online", "offline", "asleep" }) + .HasPostgresEnum("unit_of_length", new[] { "km", "mi" }) + .HasPostgresEnum("unit_of_temperature", new[] { "C", "F" }) + .HasPostgresExtension("cube") + .HasPostgresExtension("earthdistance"); + + modelBuilder.Entity
(entity => + { + entity.ToTable("addresses"); + + entity.HasIndex(e => new { e.OsmId, e.OsmType }, "addresses_osm_id_osm_type_index") + .IsUnique(); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.City) + .HasMaxLength(255) + .HasColumnName("city"); + + entity.Property(e => e.Country) + .HasMaxLength(255) + .HasColumnName("country"); + + entity.Property(e => e.County) + .HasMaxLength(255) + .HasColumnName("county"); + + entity.Property(e => e.DisplayName) + .HasMaxLength(512) + .HasColumnName("display_name"); + + entity.Property(e => e.HouseNumber) + .HasMaxLength(255) + .HasColumnName("house_number"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + + entity.Property(e => e.Latitude) + .HasPrecision(8, 6) + .HasColumnName("latitude"); + + entity.Property(e => e.Longitude) + .HasPrecision(9, 6) + .HasColumnName("longitude"); + + entity.Property(e => e.Name) + .HasMaxLength(255) + .HasColumnName("name"); + + entity.Property(e => e.Neighbourhood) + .HasMaxLength(255) + .HasColumnName("neighbourhood"); + + entity.Property(e => e.OsmId).HasColumnName("osm_id"); + + entity.Property(e => e.OsmType).HasColumnName("osm_type"); + + entity.Property(e => e.Postcode) + .HasMaxLength(255) + .HasColumnName("postcode"); + + entity.Property(e => e.Raw) + .HasColumnType("jsonb") + .HasColumnName("raw"); + + entity.Property(e => e.Road) + .HasMaxLength(255) + .HasColumnName("road"); + + entity.Property(e => e.State) + .HasMaxLength(255) + .HasColumnName("state"); + + entity.Property(e => e.StateDistrict) + .HasMaxLength(255) + .HasColumnName("state_district"); + + entity.Property(e => e.UpdatedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("updated_at"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("cars"); + + entity.HasIndex(e => e.Eid, "cars_eid_index") + .IsUnique(); + + entity.HasIndex(e => e.SettingsId, "cars_settings_id_index") + .IsUnique(); + + entity.HasIndex(e => e.Vid, "cars_vid_index") + .IsUnique(); + + entity.HasIndex(e => e.Vin, "cars_vin_index") + .IsUnique(); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.DisplayPriority) + .HasColumnName("display_priority") + .HasDefaultValueSql("1"); + + entity.Property(e => e.Efficiency).HasColumnName("efficiency"); + + entity.Property(e => e.Eid).HasColumnName("eid"); + + entity.Property(e => e.ExteriorColor).HasColumnName("exterior_color"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + + entity.Property(e => e.Model) + .HasMaxLength(255) + .HasColumnName("model"); + + entity.Property(e => e.Name).HasColumnName("name"); + + entity.Property(e => e.SettingsId).HasColumnName("settings_id"); + + entity.Property(e => e.SpoilerType).HasColumnName("spoiler_type"); + + entity.Property(e => e.TrimBadging).HasColumnName("trim_badging"); + + entity.Property(e => e.UpdatedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("updated_at"); + + entity.Property(e => e.Vid).HasColumnName("vid"); + + entity.Property(e => e.Vin).HasColumnName("vin"); + + entity.Property(e => e.WheelType).HasColumnName("wheel_type"); + + entity.HasOne(d => d.Settings) + .WithOne(p => p.Car) + .HasForeignKey(d => d.SettingsId) + .HasConstraintName("cars_settings_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("car_settings"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.FreeSupercharging).HasColumnName("free_supercharging"); + + entity.Property(e => e.ReqNotUnlocked).HasColumnName("req_not_unlocked"); + + entity.Property(e => e.SuspendAfterIdleMin) + .HasColumnName("suspend_after_idle_min") + .HasDefaultValueSql("15"); + + entity.Property(e => e.SuspendMin) + .HasColumnName("suspend_min") + .HasDefaultValueSql("21"); + + entity.Property(e => e.UseStreamingApi) + .IsRequired() + .HasColumnName("use_streaming_api") + .HasDefaultValueSql("true"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("charges"); + + entity.HasIndex(e => e.ChargingProcessId, "charges_charging_process_id_index"); + + entity.HasIndex(e => e.Date, "charges_date_index"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.BatteryHeater).HasColumnName("battery_heater"); + + entity.Property(e => e.BatteryHeaterNoPower).HasColumnName("battery_heater_no_power"); + + entity.Property(e => e.BatteryHeaterOn).HasColumnName("battery_heater_on"); + + entity.Property(e => e.BatteryLevel).HasColumnName("battery_level"); + + entity.Property(e => e.ChargeEnergyAdded) + .HasPrecision(8, 2) + .HasColumnName("charge_energy_added"); + + entity.Property(e => e.ChargerActualCurrent).HasColumnName("charger_actual_current"); + + entity.Property(e => e.ChargerPhases).HasColumnName("charger_phases"); + + entity.Property(e => e.ChargerPilotCurrent).HasColumnName("charger_pilot_current"); + + entity.Property(e => e.ChargerPower).HasColumnName("charger_power"); + + entity.Property(e => e.ChargerVoltage).HasColumnName("charger_voltage"); + + entity.Property(e => e.ChargingProcessId).HasColumnName("charging_process_id"); + + entity.Property(e => e.ConnChargeCable) + .HasMaxLength(255) + .HasColumnName("conn_charge_cable"); + + entity.Property(e => e.Date) + .HasColumnType("timestamp without time zone") + .HasColumnName("date"); + + entity.Property(e => e.FastChargerBrand) + .HasMaxLength(255) + .HasColumnName("fast_charger_brand"); + + entity.Property(e => e.FastChargerPresent).HasColumnName("fast_charger_present"); + + entity.Property(e => e.FastChargerType) + .HasMaxLength(255) + .HasColumnName("fast_charger_type"); + + entity.Property(e => e.IdealBatteryRangeKm) + .HasPrecision(6, 2) + .HasColumnName("ideal_battery_range_km"); + + entity.Property(e => e.NotEnoughPowerToHeat).HasColumnName("not_enough_power_to_heat"); + + entity.Property(e => e.OutsideTemp) + .HasPrecision(4, 1) + .HasColumnName("outside_temp"); + + entity.Property(e => e.RatedBatteryRangeKm) + .HasPrecision(6, 2) + .HasColumnName("rated_battery_range_km"); + + entity.Property(e => e.UsableBatteryLevel).HasColumnName("usable_battery_level"); + + entity.HasOne(d => d.ChargingProcess) + .WithMany(p => p.Charges) + .HasForeignKey(d => d.ChargingProcessId) + .HasConstraintName("charges_charging_process_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("charging_processes"); + + entity.HasIndex(e => e.AddressId, "charging_processes_address_id_index"); + + entity.HasIndex(e => e.CarId, "charging_processes_car_id_index"); + + entity.HasIndex(e => e.PositionId, "charging_processes_position_id_index"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.AddressId).HasColumnName("address_id"); + + entity.Property(e => e.CarId).HasColumnName("car_id"); + + entity.Property(e => e.ChargeEnergyAdded) + .HasPrecision(8, 2) + .HasColumnName("charge_energy_added"); + + entity.Property(e => e.ChargeEnergyUsed) + .HasPrecision(8, 2) + .HasColumnName("charge_energy_used"); + + entity.Property(e => e.Cost) + .HasPrecision(6, 2) + .HasColumnName("cost"); + + entity.Property(e => e.DurationMin).HasColumnName("duration_min"); + + entity.Property(e => e.EndBatteryLevel).HasColumnName("end_battery_level"); + + entity.Property(e => e.EndDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("end_date"); + + entity.Property(e => e.EndIdealRangeKm) + .HasPrecision(6, 2) + .HasColumnName("end_ideal_range_km"); + + entity.Property(e => e.EndRatedRangeKm) + .HasPrecision(6, 2) + .HasColumnName("end_rated_range_km"); + + entity.Property(e => e.GeofenceId).HasColumnName("geofence_id"); + + entity.Property(e => e.OutsideTempAvg) + .HasPrecision(4, 1) + .HasColumnName("outside_temp_avg"); + + entity.Property(e => e.PositionId).HasColumnName("position_id"); + + entity.Property(e => e.StartBatteryLevel).HasColumnName("start_battery_level"); + + entity.Property(e => e.StartDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("start_date"); + + entity.Property(e => e.StartIdealRangeKm) + .HasPrecision(6, 2) + .HasColumnName("start_ideal_range_km"); + + entity.Property(e => e.StartRatedRangeKm) + .HasPrecision(6, 2) + .HasColumnName("start_rated_range_km"); + + entity.HasOne(d => d.Address) + .WithMany(p => p.ChargingProcesses) + .HasForeignKey(d => d.AddressId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("charging_processes_address_id_fkey"); + + entity.HasOne(d => d.Car) + .WithMany(p => p.ChargingProcesses) + .HasForeignKey(d => d.CarId) + .HasConstraintName("charging_processes_car_id_fkey"); + + entity.HasOne(d => d.Geofence) + .WithMany(p => p.ChargingProcesses) + .HasForeignKey(d => d.GeofenceId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("charging_processes_geofence_id_fkey"); + + entity.HasOne(d => d.Position) + .WithMany(p => p.ChargingProcesses) + .HasForeignKey(d => d.PositionId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("charging_processes_position_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("drives"); + + entity.HasIndex(e => e.EndGeofenceId, "drives_end_geofence_id_index"); + + entity.HasIndex(e => e.EndPositionId, "drives_end_position_id_index"); + + entity.HasIndex(e => e.StartGeofenceId, "drives_start_geofence_id_index"); + + entity.HasIndex(e => e.StartPositionId, "drives_start_position_id_index"); + + entity.HasIndex(e => e.CarId, "trips_car_id_index"); + + entity.HasIndex(e => e.EndAddressId, "trips_end_address_id_index"); + + entity.HasIndex(e => e.StartAddressId, "trips_start_address_id_index"); + + entity.Property(e => e.Id) + .HasColumnName("id") + .HasDefaultValueSql("nextval('trips_id_seq'::regclass)"); + + entity.Property(e => e.CarId).HasColumnName("car_id"); + + entity.Property(e => e.Distance).HasColumnName("distance"); + + entity.Property(e => e.DurationMin).HasColumnName("duration_min"); + + entity.Property(e => e.EndAddressId).HasColumnName("end_address_id"); + + entity.Property(e => e.EndDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("end_date"); + + entity.Property(e => e.EndGeofenceId).HasColumnName("end_geofence_id"); + + entity.Property(e => e.EndIdealRangeKm) + .HasPrecision(6, 2) + .HasColumnName("end_ideal_range_km"); + + entity.Property(e => e.EndKm).HasColumnName("end_km"); + + entity.Property(e => e.EndPositionId).HasColumnName("end_position_id"); + + entity.Property(e => e.EndRatedRangeKm) + .HasPrecision(6, 2) + .HasColumnName("end_rated_range_km"); + + entity.Property(e => e.InsideTempAvg) + .HasPrecision(4, 1) + .HasColumnName("inside_temp_avg"); + + entity.Property(e => e.OutsideTempAvg) + .HasPrecision(4, 1) + .HasColumnName("outside_temp_avg"); + + entity.Property(e => e.PowerMax).HasColumnName("power_max"); + + entity.Property(e => e.PowerMin).HasColumnName("power_min"); + + entity.Property(e => e.SpeedMax).HasColumnName("speed_max"); + + entity.Property(e => e.StartAddressId).HasColumnName("start_address_id"); + + entity.Property(e => e.StartDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("start_date"); + + entity.Property(e => e.StartGeofenceId).HasColumnName("start_geofence_id"); + + entity.Property(e => e.StartIdealRangeKm) + .HasPrecision(6, 2) + .HasColumnName("start_ideal_range_km"); + + entity.Property(e => e.StartKm).HasColumnName("start_km"); + + entity.Property(e => e.StartPositionId).HasColumnName("start_position_id"); + + entity.Property(e => e.StartRatedRangeKm) + .HasPrecision(6, 2) + .HasColumnName("start_rated_range_km"); + + entity.HasOne(d => d.Car) + .WithMany(p => p.Drives) + .HasForeignKey(d => d.CarId) + .HasConstraintName("drives_car_id_fkey"); + + entity.HasOne(d => d.EndAddress) + .WithMany(p => p.DriveEndAddresses) + .HasForeignKey(d => d.EndAddressId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_end_address_id_fkey"); + + entity.HasOne(d => d.EndGeofence) + .WithMany(p => p.DriveEndGeofences) + .HasForeignKey(d => d.EndGeofenceId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_end_geofence_id_fkey"); + + entity.HasOne(d => d.EndPosition) + .WithMany(p => p.DriveEndPositions) + .HasForeignKey(d => d.EndPositionId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_end_position_id_fkey"); + + entity.HasOne(d => d.StartAddress) + .WithMany(p => p.DriveStartAddresses) + .HasForeignKey(d => d.StartAddressId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_start_address_id_fkey"); + + entity.HasOne(d => d.StartGeofence) + .WithMany(p => p.DriveStartGeofences) + .HasForeignKey(d => d.StartGeofenceId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_start_geofence_id_fkey"); + + entity.HasOne(d => d.StartPosition) + .WithMany(p => p.DriveStartPositions) + .HasForeignKey(d => d.StartPositionId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("drives_start_position_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("geofences"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.CostPerUnit) + .HasPrecision(6, 4) + .HasColumnName("cost_per_unit"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + + entity.Property(e => e.Latitude) + .HasPrecision(8, 6) + .HasColumnName("latitude"); + + entity.Property(e => e.Longitude) + .HasPrecision(9, 6) + .HasColumnName("longitude"); + + entity.Property(e => e.Name) + .HasMaxLength(255) + .HasColumnName("name"); + + entity.Property(e => e.Radius) + .HasColumnName("radius") + .HasDefaultValueSql("25"); + + entity.Property(e => e.SessionFee) + .HasPrecision(6, 2) + .HasColumnName("session_fee"); + + entity.Property(e => e.UpdatedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("updated_at"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("positions"); + + entity.HasIndex(e => e.CarId, "positions_car_id_index"); + + entity.HasIndex(e => e.Date, "positions_date_index"); + + entity.HasIndex(e => e.DriveId, "positions_drive_id_index"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.BatteryHeater).HasColumnName("battery_heater"); + + entity.Property(e => e.BatteryHeaterNoPower).HasColumnName("battery_heater_no_power"); + + entity.Property(e => e.BatteryHeaterOn).HasColumnName("battery_heater_on"); + + entity.Property(e => e.BatteryLevel).HasColumnName("battery_level"); + + entity.Property(e => e.CarId).HasColumnName("car_id"); + + entity.Property(e => e.Date) + .HasColumnType("timestamp without time zone") + .HasColumnName("date"); + + entity.Property(e => e.DriveId).HasColumnName("drive_id"); + + entity.Property(e => e.DriverTempSetting) + .HasPrecision(4, 1) + .HasColumnName("driver_temp_setting"); + + entity.Property(e => e.Elevation).HasColumnName("elevation"); + + entity.Property(e => e.EstBatteryRangeKm) + .HasPrecision(6, 2) + .HasColumnName("est_battery_range_km"); + + entity.Property(e => e.FanStatus).HasColumnName("fan_status"); + + entity.Property(e => e.IdealBatteryRangeKm) + .HasPrecision(6, 2) + .HasColumnName("ideal_battery_range_km"); + + entity.Property(e => e.InsideTemp) + .HasPrecision(4, 1) + .HasColumnName("inside_temp"); + + entity.Property(e => e.IsClimateOn).HasColumnName("is_climate_on"); + + entity.Property(e => e.IsFrontDefrosterOn).HasColumnName("is_front_defroster_on"); + + entity.Property(e => e.IsRearDefrosterOn).HasColumnName("is_rear_defroster_on"); + + entity.Property(e => e.Latitude) + .HasPrecision(8, 6) + .HasColumnName("latitude"); + + entity.Property(e => e.Longitude) + .HasPrecision(9, 6) + .HasColumnName("longitude"); + + entity.Property(e => e.Odometer).HasColumnName("odometer"); + + entity.Property(e => e.OutsideTemp) + .HasPrecision(4, 1) + .HasColumnName("outside_temp"); + + entity.Property(e => e.PassengerTempSetting) + .HasPrecision(4, 1) + .HasColumnName("passenger_temp_setting"); + + entity.Property(e => e.Power).HasColumnName("power"); + + entity.Property(e => e.RatedBatteryRangeKm) + .HasPrecision(6, 2) + .HasColumnName("rated_battery_range_km"); + + entity.Property(e => e.Speed).HasColumnName("speed"); + + entity.Property(e => e.UsableBatteryLevel).HasColumnName("usable_battery_level"); + + entity.HasOne(d => d.Car) + .WithMany(p => p.Positions) + .HasForeignKey(d => d.CarId) + .HasConstraintName("positions_car_id_fkey"); + + entity.HasOne(d => d.Drive) + .WithMany(p => p.Positions) + .HasForeignKey(d => d.DriveId) + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("positions_drive_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Version) + .HasName("schema_migrations_pkey"); + + entity.ToTable("schema_migrations"); + + entity.Property(e => e.Version) + .ValueGeneratedNever() + .HasColumnName("version"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("settings"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.BaseUrl) + .HasMaxLength(255) + .HasColumnName("base_url"); + + entity.Property(e => e.GrafanaUrl) + .HasMaxLength(255) + .HasColumnName("grafana_url"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + + entity.Property(e => e.Language) + .HasColumnName("language") + .HasDefaultValueSql("'en'::text"); + + entity.Property(e => e.UpdatedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("updated_at"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("states"); + + entity.HasIndex(e => e.CarId, "states_car_id_index"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.CarId).HasColumnName("car_id"); + + entity.Property(e => e.EndDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("end_date"); + + entity.Property(e => e.StartDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("start_date"); + + entity.HasOne(d => d.Car) + .WithMany(p => p.States) + .HasForeignKey(d => d.CarId) + .HasConstraintName("states_car_id_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("tokens"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.Access).HasColumnName("access"); + + entity.Property(e => e.InsertedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("inserted_at"); + + entity.Property(e => e.Refresh).HasColumnName("refresh"); + + entity.Property(e => e.UpdatedAt) + .HasColumnType("timestamp(0) without time zone") + .HasColumnName("updated_at"); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("updates"); + + entity.HasIndex(e => e.CarId, "updates_car_id_index"); + + entity.Property(e => e.Id).HasColumnName("id"); + + entity.Property(e => e.CarId).HasColumnName("car_id"); + + entity.Property(e => e.EndDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("end_date"); + + entity.Property(e => e.StartDate) + .HasColumnType("timestamp without time zone") + .HasColumnName("start_date"); + + entity.Property(e => e.Version) + .HasMaxLength(255) + .HasColumnName("version"); + + entity.HasOne(d => d.Car) + .WithMany(p => p.Updates) + .HasForeignKey(d => d.CarId) + .HasConstraintName("updates_car_id_fkey"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + private void OnModelCreatingPartial(ModelBuilder modelBuilder) + { + throw new NotImplementedException(); + } + } +} diff --git a/SmartTeslaAmpSetter.Tests/Services/SolarEdgePlugin/CurrentValuesService.cs b/SmartTeslaAmpSetter.Tests/Services/SolarEdgePlugin/CurrentValuesService.cs index d51081190..89d8e53ee 100644 --- a/SmartTeslaAmpSetter.Tests/Services/SolarEdgePlugin/CurrentValuesService.cs +++ b/SmartTeslaAmpSetter.Tests/Services/SolarEdgePlugin/CurrentValuesService.cs @@ -1,5 +1,4 @@ -using Serilog.Events; -using Xunit; +using Xunit; using Xunit.Abstractions; namespace SmartTeslaAmpSetter.Tests.Services.SolarEdgePlugin; @@ -18,5 +17,6 @@ public void CanDeserializeCloudApiValue(string jsonString) var currentValuesService = Mock.Create(); var value = currentValuesService.GetCloudApiValueFromString(jsonString); + Assert.NotNull(value); } } \ No newline at end of file diff --git a/SmartTeslaAmpSetter.sln b/SmartTeslaAmpSetter.sln index 43594c781..3ca90167f 100644 --- a/SmartTeslaAmpSetter.sln +++ b/SmartTeslaAmpSetter.sln @@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.SmaEnergymeter", "P EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmartTeslaAmpSetter.Tests", "SmartTeslaAmpSetter.Tests\SmartTeslaAmpSetter.Tests.csproj", "{98CE240C-CC51-4658-BD0B-5BEE43297B9F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugins.SolarEdge", "Plugins.SolarEdge\Plugins.SolarEdge.csproj", "{9F3C7BDB-B856-4C09-BD17-784312A9B095}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.SolarEdge", "Plugins.SolarEdge\Plugins.SolarEdge.csproj", "{9F3C7BDB-B856-4C09-BD17-784312A9B095}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartTeslaAmpSetter.Model", "SmartTeslaAmpSetter.Model\SmartTeslaAmpSetter.Model.csproj", "{8247068B-4A75-40FB-B5BE-1C557CE20AC9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,6 +47,10 @@ Global {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.Build.0 = Release|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1f620354a1d08759af71c20c97467a686aaa7241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sat, 2 Jul 2022 13:49:03 +0200 Subject: [PATCH 2/7] feat(CarDbUpdateJob): Updating pilotCurrent of cars --- .../Contracts/IDbConnectionStringHelper.cs | 6 ++ .../Contracts/ITeslamateContext.cs | 21 ++++++ .../Entities/ChargingProcess.cs | 10 +-- SmartTeslaAmpSetter.Model/Entities/Drive.cs | 16 ++--- .../Entities/Geofence.cs | 6 +- .../Entities/Position.cs | 10 +-- .../DbConnectionStringHelper.cs | 30 ++++++++ .../{ => EntityFramework}/TeslamateContext.cs | 12 +--- .../SmartTeslaAmpSetter.Model.csproj | 6 +- .../Server/ChargeTimeUpdateService.cs | 1 + .../Services/Server/GridService.cs | 1 + .../Wrappers/ConfigurationWrapper.cs | 16 ++--- .../Server/Contracts/ICarDbUpdateService.cs | 6 ++ SmartTeslaAmpSetter/Server/Program.cs | 16 ++++- .../Server/Scheduling/CarDbUpdateJob.cs | 22 ++++++ .../Server/Scheduling/JobManager.cs | 11 ++- .../Server/Services/CarDbUpdateService.cs | 42 +++++++++++ .../Services/ChargeTimeUpdateService.cs | 1 + .../Server/Services/ChargingService.cs | 1 + .../Server/Services/ConfigJsonService.cs | 1 + .../Server/Services/GridService.cs | 1 + .../Server/Services/MqttService.cs | 1 + .../Server/Services/PvValueService.cs | 1 + .../Server/Services/TelegramService.cs | 1 + .../Server/Services/TeslamateApiService.cs | 1 + .../Server/SmartTeslaAmpSetter.Server.csproj | 2 + .../Server/appsettings.Development.json | 7 +- SmartTeslaAmpSetter/Server/appsettings.json | 7 +- .../Contracts/IConfigurationWrapper.cs | 7 +- .../IDateTimeProvider.cs | 2 +- .../Shared/SmartTeslaAmpSetter.Shared.csproj | 5 +- .../Shared/TimeProviding/DateTimeProvider.cs | 4 +- .../TimeProviding/FakeDateTimeProvider.cs | 4 +- .../Wrappers/ConfigurationWrapper.cs | 72 +++++++++++++++---- 34 files changed, 284 insertions(+), 66 deletions(-) create mode 100644 SmartTeslaAmpSetter.Model/Contracts/IDbConnectionStringHelper.cs create mode 100644 SmartTeslaAmpSetter.Model/Contracts/ITeslamateContext.cs create mode 100644 SmartTeslaAmpSetter.Model/EntityFramework/DbConnectionStringHelper.cs rename SmartTeslaAmpSetter.Model/{ => EntityFramework}/TeslamateContext.cs (99%) create mode 100644 SmartTeslaAmpSetter/Server/Contracts/ICarDbUpdateService.cs create mode 100644 SmartTeslaAmpSetter/Server/Scheduling/CarDbUpdateJob.cs create mode 100644 SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs rename SmartTeslaAmpSetter/{Server => Shared}/Contracts/IConfigurationWrapper.cs (83%) rename SmartTeslaAmpSetter/Shared/{TimeProviding => Contracts}/IDateTimeProvider.cs (51%) rename SmartTeslaAmpSetter/{Server => Shared}/Wrappers/ConfigurationWrapper.cs (79%) diff --git a/SmartTeslaAmpSetter.Model/Contracts/IDbConnectionStringHelper.cs b/SmartTeslaAmpSetter.Model/Contracts/IDbConnectionStringHelper.cs new file mode 100644 index 000000000..57619cfe6 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Contracts/IDbConnectionStringHelper.cs @@ -0,0 +1,6 @@ +namespace SmartTeslaAmpSetter.Model.Contracts; + +public interface IDbConnectionStringHelper +{ + string GetConnectionString(); +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter.Model/Contracts/ITeslamateContext.cs b/SmartTeslaAmpSetter.Model/Contracts/ITeslamateContext.cs new file mode 100644 index 000000000..8a813bf65 --- /dev/null +++ b/SmartTeslaAmpSetter.Model/Contracts/ITeslamateContext.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; +using SmartTeslaAmpSetter.Model.Entities; + +namespace SmartTeslaAmpSetter.Model.Contracts; + +public interface ITeslamateContext +{ + DbSet
Addresses { get; set; } + DbSet Cars { get; set; } + DbSet CarSettings { get; set; } + DbSet Charges { get; set; } + DbSet ChargingProcesses { get; set; } + DbSet Drives { get; set; } + DbSet Geofences { get; set; } + DbSet Positions { get; set; } + DbSet SchemaMigrations { get; set; } + DbSet Settings { get; set; } + DbSet States { get; set; } + DbSet Tokens { get; set; } + DbSet Updates { get; set; } +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs b/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs index 8a4850ce5..8fa99ed26 100644 --- a/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs +++ b/SmartTeslaAmpSetter.Model/Entities/ChargingProcess.cs @@ -26,10 +26,10 @@ public ChargingProcess() public decimal? ChargeEnergyUsed { get; set; } public decimal? Cost { get; set; } - public virtual Address? Address { get; set; } - public virtual Car Car { get; set; } = null!; - public virtual Geofence? Geofence { get; set; } - public virtual Position Position { get; set; } = null!; - public virtual ICollection Charges { get; set; } + public Address? Address { get; set; } + public Car Car { get; set; } = null!; + public Geofence? Geofence { get; set; } + public Position Position { get; set; } = null!; + public ICollection Charges { get; set; } } } diff --git a/SmartTeslaAmpSetter.Model/Entities/Drive.cs b/SmartTeslaAmpSetter.Model/Entities/Drive.cs index a51c14c9d..d8140f516 100644 --- a/SmartTeslaAmpSetter.Model/Entities/Drive.cs +++ b/SmartTeslaAmpSetter.Model/Entities/Drive.cs @@ -31,13 +31,13 @@ public Drive() public int? StartGeofenceId { get; set; } public int? EndGeofenceId { get; set; } - public virtual Car Car { get; set; } = null!; - public virtual Address? EndAddress { get; set; } - public virtual Geofence? EndGeofence { get; set; } - public virtual Position? EndPosition { get; set; } - public virtual Address? StartAddress { get; set; } - public virtual Geofence? StartGeofence { get; set; } - public virtual Position? StartPosition { get; set; } - public virtual ICollection Positions { get; set; } + public Car Car { get; set; } = null!; + public Address? EndAddress { get; set; } + public Geofence? EndGeofence { get; set; } + public Position? EndPosition { get; set; } + public Address? StartAddress { get; set; } + public Geofence? StartGeofence { get; set; } + public Position? StartPosition { get; set; } + public ICollection Positions { get; set; } } } diff --git a/SmartTeslaAmpSetter.Model/Entities/Geofence.cs b/SmartTeslaAmpSetter.Model/Entities/Geofence.cs index 66f8f4980..74671b7ba 100644 --- a/SmartTeslaAmpSetter.Model/Entities/Geofence.cs +++ b/SmartTeslaAmpSetter.Model/Entities/Geofence.cs @@ -19,8 +19,8 @@ public Geofence() public decimal? CostPerUnit { get; set; } public decimal? SessionFee { get; set; } - public virtual ICollection ChargingProcesses { get; set; } - public virtual ICollection DriveEndGeofences { get; set; } - public virtual ICollection DriveStartGeofences { get; set; } + public ICollection ChargingProcesses { get; set; } + public ICollection DriveEndGeofences { get; set; } + public ICollection DriveStartGeofences { get; set; } } } diff --git a/SmartTeslaAmpSetter.Model/Entities/Position.cs b/SmartTeslaAmpSetter.Model/Entities/Position.cs index b38a95a4a..3a067d54c 100644 --- a/SmartTeslaAmpSetter.Model/Entities/Position.cs +++ b/SmartTeslaAmpSetter.Model/Entities/Position.cs @@ -36,10 +36,10 @@ public Position() public decimal? RatedBatteryRangeKm { get; set; } public short? UsableBatteryLevel { get; set; } - public virtual Car Car { get; set; } = null!; - public virtual Drive? Drive { get; set; } - public virtual ICollection ChargingProcesses { get; set; } - public virtual ICollection DriveEndPositions { get; set; } - public virtual ICollection DriveStartPositions { get; set; } + public Car Car { get; set; } = null!; + public Drive? Drive { get; set; } + public ICollection ChargingProcesses { get; set; } + public ICollection DriveEndPositions { get; set; } + public ICollection DriveStartPositions { get; set; } } } diff --git a/SmartTeslaAmpSetter.Model/EntityFramework/DbConnectionStringHelper.cs b/SmartTeslaAmpSetter.Model/EntityFramework/DbConnectionStringHelper.cs new file mode 100644 index 000000000..338e603da --- /dev/null +++ b/SmartTeslaAmpSetter.Model/EntityFramework/DbConnectionStringHelper.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; +using SmartTeslaAmpSetter.Model.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; + +namespace SmartTeslaAmpSetter.Model.EntityFramework; + +public class DbConnectionStringHelper : IDbConnectionStringHelper +{ + private readonly ILogger _logger; + private readonly IConfigurationWrapper _configurationWrapper; + + public DbConnectionStringHelper(ILogger logger, IConfigurationWrapper configurationWrapper) + { + _logger = logger; + _configurationWrapper = configurationWrapper; + } + + public string GetConnectionString() + { + _logger.LogTrace("{method}()", nameof(GetConnectionString)); + var server = _configurationWrapper.TeslaMateDbServer(); + var port = _configurationWrapper.TeslaMateDbPort(); + var databaseName = _configurationWrapper.TeslaMateDbDatabaseName(); + var username = _configurationWrapper.TeslaMateDbUser(); + var password = _configurationWrapper.TeslaMateDbPassword(); + var connectionString = $"Host={server};Port={port};Database={databaseName};Username={username};Password={password}"; + _logger.LogTrace("ConnectionString: {connectionString}", connectionString); + return connectionString; + } +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter.Model/TeslamateContext.cs b/SmartTeslaAmpSetter.Model/EntityFramework/TeslamateContext.cs similarity index 99% rename from SmartTeslaAmpSetter.Model/TeslamateContext.cs rename to SmartTeslaAmpSetter.Model/EntityFramework/TeslamateContext.cs index e872ec85b..91bd0fc85 100644 --- a/SmartTeslaAmpSetter.Model/TeslamateContext.cs +++ b/SmartTeslaAmpSetter.Model/EntityFramework/TeslamateContext.cs @@ -1,9 +1,10 @@ using Microsoft.EntityFrameworkCore; +using SmartTeslaAmpSetter.Model.Contracts; using SmartTeslaAmpSetter.Model.Entities; -namespace SmartTeslaAmpSetter.Model +namespace SmartTeslaAmpSetter.Model.EntityFramework { - public class TeslamateContext : DbContext + public class TeslamateContext : DbContext, ITeslamateContext { public TeslamateContext() { @@ -742,13 +743,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(d => d.CarId) .HasConstraintName("updates_car_id_fkey"); }); - - OnModelCreatingPartial(modelBuilder); - } - - private void OnModelCreatingPartial(ModelBuilder modelBuilder) - { - throw new NotImplementedException(); } } } diff --git a/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj b/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj index 4b2987ebd..12fefbaed 100644 --- a/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj +++ b/SmartTeslaAmpSetter.Model/SmartTeslaAmpSetter.Model.csproj @@ -7,11 +7,15 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/SmartTeslaAmpSetter.Tests/Services/Server/ChargeTimeUpdateService.cs b/SmartTeslaAmpSetter.Tests/Services/Server/ChargeTimeUpdateService.cs index 97294c816..97e1e215d 100644 --- a/SmartTeslaAmpSetter.Tests/Services/Server/ChargeTimeUpdateService.cs +++ b/SmartTeslaAmpSetter.Tests/Services/Server/ChargeTimeUpdateService.cs @@ -1,4 +1,5 @@ using System; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Settings; using SmartTeslaAmpSetter.Shared.TimeProviding; using Xunit; diff --git a/SmartTeslaAmpSetter.Tests/Services/Server/GridService.cs b/SmartTeslaAmpSetter.Tests/Services/Server/GridService.cs index a5e9a8f60..10ff29fa7 100644 --- a/SmartTeslaAmpSetter.Tests/Services/Server/GridService.cs +++ b/SmartTeslaAmpSetter.Tests/Services/Server/GridService.cs @@ -1,5 +1,6 @@ using SmartTeslaAmpSetter.Server.Contracts; using SmartTeslaAmpSetter.Server.Enums; +using SmartTeslaAmpSetter.Shared.Contracts; using Xunit; using Xunit.Abstractions; diff --git a/SmartTeslaAmpSetter.Tests/Wrappers/ConfigurationWrapper.cs b/SmartTeslaAmpSetter.Tests/Wrappers/ConfigurationWrapper.cs index fd1c0f247..462f66127 100644 --- a/SmartTeslaAmpSetter.Tests/Wrappers/ConfigurationWrapper.cs +++ b/SmartTeslaAmpSetter.Tests/Wrappers/ConfigurationWrapper.cs @@ -14,11 +14,11 @@ public ConfigurationWrapper(ITestOutputHelper outputHelper) [Fact] public void Get_Not_Nullable_String() { - var configurationService = Mock.Create(); + var configurationService = Mock.Create(); var existingConfigValue = "TeslaMateApiBaseUrl"; var teslaMateApiBaseUrl = - configurationService.GetNotNullableConfigurationValue(existingConfigValue); + configurationService.GetNotNullableConfigurationValue(existingConfigValue); Assert.Equal("http://192.168.1.50:8097", teslaMateApiBaseUrl); } @@ -28,9 +28,9 @@ public void Get_Not_Nullable_String() [InlineData("notExisiting")] public void Throw_Exception_On_Null_String(string notExisitingConfigValue) { - var configurationService = Mock.Create(); + var configurationService = Mock.Create(); Assert.Throws( - () => configurationService.GetNotNullableConfigurationValue(notExisitingConfigValue)); + () => configurationService.GetNotNullableConfigurationValue(notExisitingConfigValue)); } [Theory] @@ -38,8 +38,8 @@ public void Throw_Exception_On_Null_String(string notExisitingConfigValue) [InlineData("notExisiting")] public void Returns_Null_On_Non_Exisiting_Values(string notExisitingConfigValue) { - var configurationService = Mock.Create(); - var value = configurationService.GetNullableConfigurationValue(notExisitingConfigValue); + var configurationService = Mock.Create(); + var value = configurationService.GetNullableConfigurationValue(notExisitingConfigValue); Assert.Null(value); } @@ -51,7 +51,7 @@ public void Returns_Null_On_Non_Exisiting_Values(string notExisitingConfigValue) [InlineData("notExisiting")] public void Get_TimeSpan_From_Minutes(string configName) { - var configurationService = Mock.Create(); + var configurationService = Mock.Create(); var timespan = configurationService.GetMinutesConfigurationValueIfGreaterThanMinumum(configName, TimeSpan.FromMinutes(1)); @@ -81,7 +81,7 @@ public void Get_TimeSpan_From_Minutes(string configName) [InlineData("notExisiting")] public void Get_TimeSpan_From_Seconds(string configName) { - var configurationService = Mock.Create(); + var configurationService = Mock.Create(); var minimum = TimeSpan.FromSeconds(1); var timespan = configurationService.GetSecondsConfigurationValueIfGreaterThanMinumum(configName, minimum); diff --git a/SmartTeslaAmpSetter/Server/Contracts/ICarDbUpdateService.cs b/SmartTeslaAmpSetter/Server/Contracts/ICarDbUpdateService.cs new file mode 100644 index 000000000..a3429f4ab --- /dev/null +++ b/SmartTeslaAmpSetter/Server/Contracts/ICarDbUpdateService.cs @@ -0,0 +1,6 @@ +namespace SmartTeslaAmpSetter.Server.Contracts; + +public interface ICarDbUpdateService +{ + Task UpdateCarsFromDatabase(); +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Server/Program.cs b/SmartTeslaAmpSetter/Server/Program.cs index d30583115..bc7662501 100644 --- a/SmartTeslaAmpSetter/Server/Program.cs +++ b/SmartTeslaAmpSetter/Server/Program.cs @@ -1,16 +1,20 @@ +using Microsoft.EntityFrameworkCore; using MQTTnet; using Quartz; using Quartz.Impl; using Quartz.Spi; using Serilog; +using SmartTeslaAmpSetter.Model.Contracts; +using SmartTeslaAmpSetter.Model.EntityFramework; using SmartTeslaAmpSetter.Server.Contracts; using SmartTeslaAmpSetter.Server.Scheduling; using SmartTeslaAmpSetter.Server.Services; -using SmartTeslaAmpSetter.Server.Wrappers; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Settings; using SmartTeslaAmpSetter.Shared.TimeProviding; +using SmartTeslaAmpSetter.Shared.Wrappers; var builder = WebApplication.CreateBuilder(args); @@ -26,13 +30,13 @@ var mqttFactory = new MqttFactory(); var mqttClient = mqttFactory.CreateMqttClient(); - builder.Services .AddTransient() .AddTransient() .AddTransient() .AddTransient() .AddTransient() + .AddTransient() .AddTransient() .AddTransient() .AddTransient() @@ -51,6 +55,14 @@ .AddTransient() .AddTransient() .AddTransient() + .AddTransient() + .AddDbContext((provider, options) => + { + options.UseNpgsql(provider.GetRequiredService().GetConnectionString()); + options.EnableSensitiveDataLogging(); + options.EnableDetailedErrors(); + }, ServiceLifetime.Transient, ServiceLifetime.Transient) + .AddTransient() ; builder.Host.UseSerilog((context, configuration) => configuration diff --git a/SmartTeslaAmpSetter/Server/Scheduling/CarDbUpdateJob.cs b/SmartTeslaAmpSetter/Server/Scheduling/CarDbUpdateJob.cs new file mode 100644 index 000000000..68090b67e --- /dev/null +++ b/SmartTeslaAmpSetter/Server/Scheduling/CarDbUpdateJob.cs @@ -0,0 +1,22 @@ +using Quartz; +using SmartTeslaAmpSetter.Server.Contracts; + +namespace SmartTeslaAmpSetter.Server.Scheduling; + +[DisallowConcurrentExecution] +public class CarDbUpdateJob : IJob +{ + private readonly ILogger _logger; + private readonly ICarDbUpdateService _carDbUpdateService; + + public CarDbUpdateJob(ILogger logger, ICarDbUpdateService carDbUpdateService) + { + _logger = logger; + _carDbUpdateService = carDbUpdateService; + } + public async Task Execute(IJobExecutionContext context) + { + _logger.LogTrace("Executing job to update cars from database"); + await _carDbUpdateService.UpdateCarsFromDatabase().ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Server/Scheduling/JobManager.cs b/SmartTeslaAmpSetter/Server/Scheduling/JobManager.cs index 852bfd39e..90203cf39 100644 --- a/SmartTeslaAmpSetter/Server/Scheduling/JobManager.cs +++ b/SmartTeslaAmpSetter/Server/Scheduling/JobManager.cs @@ -1,6 +1,6 @@ using Quartz; using Quartz.Spi; -using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; namespace SmartTeslaAmpSetter.Server.Scheduling; @@ -34,10 +34,11 @@ public async void StartJobs() var configJsonUpdateJob = JobBuilder.Create().Build(); var chargeTimeUpdateJob = JobBuilder.Create().Build(); var pvValueJob = JobBuilder.Create().Build(); + var carDbUpdateJob = JobBuilder.Create().Build(); var jobIntervall = _configurationWrapper.ChargingValueJobUpdateIntervall(); - var defaultTrigger = + var chargingValueTrigger = TriggerBuilder.Create().WithSchedule(SimpleScheduleBuilder.RepeatSecondlyForever((int)jobIntervall.TotalSeconds)).Build(); var updateJsonTrigger = TriggerBuilder.Create() @@ -52,12 +53,16 @@ public async void StartJobs() var pvValueTrigger = TriggerBuilder.Create() .WithSchedule(SimpleScheduleBuilder.RepeatSecondlyForever((int)pvValueJobIntervall.TotalSeconds)).Build(); + var carDbUpdateTrigger = TriggerBuilder.Create() + .WithSchedule(SimpleScheduleBuilder.RepeatSecondlyForever(10)).Build(); + var triggersAndJobs = new Dictionary> { - {chargingValueJob, new HashSet { defaultTrigger }}, + {chargingValueJob, new HashSet { chargingValueTrigger }}, {configJsonUpdateJob, new HashSet {updateJsonTrigger}}, {chargeTimeUpdateJob, new HashSet {chargeTimeUpdateTrigger}}, {pvValueJob, new HashSet {pvValueTrigger}}, + {carDbUpdateJob, new HashSet {carDbUpdateTrigger}}, }; await _scheduler.ScheduleJobs(triggersAndJobs, false).ConfigureAwait(false); diff --git a/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs new file mode 100644 index 000000000..ca9364b17 --- /dev/null +++ b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore; +using SmartTeslaAmpSetter.Model.Contracts; +using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Dtos.Contracts; + +namespace SmartTeslaAmpSetter.Server.Services; + +public class CarDbUpdateService : ICarDbUpdateService +{ + private readonly ILogger _logger; + private readonly ISettings _settings; + private readonly ITeslamateContext _teslamateContext; + private readonly ITelegramService _telegramService; + + public CarDbUpdateService(ILogger logger, ISettings settings, ITeslamateContext teslamateContext, ITelegramService telegramService) + { + _logger = logger; + _settings = settings; + _teslamateContext = teslamateContext; + _telegramService = telegramService; + } + + public async Task UpdateCarsFromDatabase() + { + _logger.LogTrace("{method}()", nameof(UpdateCarsFromDatabase)); + foreach (var car in _settings.Cars) + { + var pilotCurrent = await _teslamateContext.Charges + .Where(c => c.ChargingProcess.CarId == car.Id) + .OrderByDescending(c => c.Date) + .Select(c => c.ChargerPilotCurrent) + .FirstOrDefaultAsync(); + _logger.LogTrace("Pilot Current for var {car} is {pilotCurrent}", car.Id, pilotCurrent); + + //ToDo: Remove telegram notification + if (pilotCurrent < 16 && car.CarState.ChargerActualCurrent > 0) + { + await _telegramService.SendMessage($"Pilot Current for var {car.Id} is {pilotCurrent}"); + } + } + } +} \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Server/Services/ChargeTimeUpdateService.cs b/SmartTeslaAmpSetter/Server/Services/ChargeTimeUpdateService.cs index b06ce3b4f..a0192e6b0 100644 --- a/SmartTeslaAmpSetter/Server/Services/ChargeTimeUpdateService.cs +++ b/SmartTeslaAmpSetter/Server/Services/ChargeTimeUpdateService.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Settings; using SmartTeslaAmpSetter.Shared.TimeProviding; diff --git a/SmartTeslaAmpSetter/Server/Services/ChargingService.cs b/SmartTeslaAmpSetter/Server/Services/ChargingService.cs index 8c67a80b8..60b29623d 100644 --- a/SmartTeslaAmpSetter/Server/Services/ChargingService.cs +++ b/SmartTeslaAmpSetter/Server/Services/ChargingService.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using SmartTeslaAmpSetter.Shared.Enums; using SmartTeslaAmpSetter.Shared.TimeProviding; diff --git a/SmartTeslaAmpSetter/Server/Services/ConfigJsonService.cs b/SmartTeslaAmpSetter/Server/Services/ConfigJsonService.cs index 5ae4b600c..75e0390c9 100644 --- a/SmartTeslaAmpSetter/Server/Services/ConfigJsonService.cs +++ b/SmartTeslaAmpSetter/Server/Services/ConfigJsonService.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json; using SmartTeslaAmpSetter.Server.Contracts; using SmartTeslaAmpSetter.Shared; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Settings; using SmartTeslaAmpSetter.Shared.Enums; diff --git a/SmartTeslaAmpSetter/Server/Services/GridService.cs b/SmartTeslaAmpSetter/Server/Services/GridService.cs index bd25fa244..37dfefdc2 100644 --- a/SmartTeslaAmpSetter/Server/Services/GridService.cs +++ b/SmartTeslaAmpSetter/Server/Services/GridService.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json.Linq; using SmartTeslaAmpSetter.Server.Contracts; using SmartTeslaAmpSetter.Server.Enums; +using SmartTeslaAmpSetter.Shared.Contracts; namespace SmartTeslaAmpSetter.Server.Services; diff --git a/SmartTeslaAmpSetter/Server/Services/MqttService.cs b/SmartTeslaAmpSetter/Server/Services/MqttService.cs index 0a1c49f38..73975b1b5 100644 --- a/SmartTeslaAmpSetter/Server/Services/MqttService.cs +++ b/SmartTeslaAmpSetter/Server/Services/MqttService.cs @@ -1,6 +1,7 @@ using MQTTnet; using MQTTnet.Client; using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using CarState = SmartTeslaAmpSetter.Shared.Enums.CarState; diff --git a/SmartTeslaAmpSetter/Server/Services/PvValueService.cs b/SmartTeslaAmpSetter/Server/Services/PvValueService.cs index b75d809ff..2bf40def7 100644 --- a/SmartTeslaAmpSetter/Server/Services/PvValueService.cs +++ b/SmartTeslaAmpSetter/Server/Services/PvValueService.cs @@ -1,4 +1,5 @@ using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; namespace SmartTeslaAmpSetter.Server.Services; diff --git a/SmartTeslaAmpSetter/Server/Services/TelegramService.cs b/SmartTeslaAmpSetter/Server/Services/TelegramService.cs index ffed182ba..e24c976f6 100644 --- a/SmartTeslaAmpSetter/Server/Services/TelegramService.cs +++ b/SmartTeslaAmpSetter/Server/Services/TelegramService.cs @@ -1,5 +1,6 @@ using System.Net; using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; namespace SmartTeslaAmpSetter.Server.Services; diff --git a/SmartTeslaAmpSetter/Server/Services/TeslamateApiService.cs b/SmartTeslaAmpSetter/Server/Services/TeslamateApiService.cs index 53113921e..5989ef495 100644 --- a/SmartTeslaAmpSetter/Server/Services/TeslamateApiService.cs +++ b/SmartTeslaAmpSetter/Server/Services/TeslamateApiService.cs @@ -1,6 +1,7 @@ using System.Text; using Newtonsoft.Json; using SmartTeslaAmpSetter.Server.Contracts; +using SmartTeslaAmpSetter.Shared.Contracts; using SmartTeslaAmpSetter.Shared.Dtos.Contracts; using CarState = SmartTeslaAmpSetter.Shared.Enums.CarState; diff --git a/SmartTeslaAmpSetter/Server/SmartTeslaAmpSetter.Server.csproj b/SmartTeslaAmpSetter/Server/SmartTeslaAmpSetter.Server.csproj index ca6b081bf..20adf705c 100644 --- a/SmartTeslaAmpSetter/Server/SmartTeslaAmpSetter.Server.csproj +++ b/SmartTeslaAmpSetter/Server/SmartTeslaAmpSetter.Server.csproj @@ -28,6 +28,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/SmartTeslaAmpSetter/Server/appsettings.Development.json b/SmartTeslaAmpSetter/Server/appsettings.Development.json index 3cbbc2094..38c3927bc 100644 --- a/SmartTeslaAmpSetter/Server/appsettings.Development.json +++ b/SmartTeslaAmpSetter/Server/appsettings.Development.json @@ -48,5 +48,10 @@ "MinutesUntilSwitchOff": 5, "PowerBuffer": 0, "MqqtClientId": "SmartTeslaAmpSetterDevelopment", - "MosquitoServer": "192.168.1.50" + "MosquitoServer": "192.168.1.50", + "TeslaMateDbServer": "192.168.1.50", + "TeslaMateDbPort": "5433", + "TeslaMateDbDatabaseName": "teslamate", + "TeslaMateDbUser": "teslamate", + "TeslaMateDbPassword": "secret" } \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Server/appsettings.json b/SmartTeslaAmpSetter/Server/appsettings.json index 0d89720df..214c2db4d 100644 --- a/SmartTeslaAmpSetter/Server/appsettings.json +++ b/SmartTeslaAmpSetter/Server/appsettings.json @@ -31,7 +31,12 @@ "UpdateIntervalSeconds": 30, "PvValueUpdateIntervalSeconds": 1, "MqqtClientId": "SmartTeslaAmpSetter", - "MosquitoServer": "mosquitto" + "MosquitoServer": "mosquitto", + "TeslaMateDbServer": "database", + "TeslaMateDbPort": "5432", + "TeslaMateDbDatabaseName": "teslamate", + "TeslaMateDbUser": "teslamate", + "TeslaMateDbPassword": "secret" //"CurrentPowerToGridUrl": "http://192.168.1.50:5007/api/ChargingLog/GetAverageGridPowerOfLastXseconds", //"CurrentInverterPowerUrl": "http://192.168.1.50:5007/api/ChargingLog/GetAverageInverterPowerOfLastXseconds", //"CurrentPowerToGridJsonPattern": "pattern", diff --git a/SmartTeslaAmpSetter/Server/Contracts/IConfigurationWrapper.cs b/SmartTeslaAmpSetter/Shared/Contracts/IConfigurationWrapper.cs similarity index 83% rename from SmartTeslaAmpSetter/Server/Contracts/IConfigurationWrapper.cs rename to SmartTeslaAmpSetter/Shared/Contracts/IConfigurationWrapper.cs index 6b2807e99..340223d92 100644 --- a/SmartTeslaAmpSetter/Server/Contracts/IConfigurationWrapper.cs +++ b/SmartTeslaAmpSetter/Shared/Contracts/IConfigurationWrapper.cs @@ -1,4 +1,4 @@ -namespace SmartTeslaAmpSetter.Server.Contracts; +namespace SmartTeslaAmpSetter.Shared.Contracts; public interface IConfigurationWrapper { @@ -28,4 +28,9 @@ public interface IConfigurationWrapper string? CurrentInverterPowerXmlAttributeHeaderName(); string? CurrentInverterPowerXmlAttributeHeaderValue(); string? CurrentInverterPowerXmlAttributeValueName(); + string TeslaMateDbServer(); + int TeslaMateDbPort(); + string TeslaMateDbDatabaseName(); + string TeslaMateDbUser(); + string TeslaMateDbPassword(); } \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Shared/TimeProviding/IDateTimeProvider.cs b/SmartTeslaAmpSetter/Shared/Contracts/IDateTimeProvider.cs similarity index 51% rename from SmartTeslaAmpSetter/Shared/TimeProviding/IDateTimeProvider.cs rename to SmartTeslaAmpSetter/Shared/Contracts/IDateTimeProvider.cs index 6d9cc1428..ab619c5d8 100644 --- a/SmartTeslaAmpSetter/Shared/TimeProviding/IDateTimeProvider.cs +++ b/SmartTeslaAmpSetter/Shared/Contracts/IDateTimeProvider.cs @@ -1,4 +1,4 @@ -namespace SmartTeslaAmpSetter.Shared.TimeProviding; +namespace SmartTeslaAmpSetter.Shared.Contracts; public interface IDateTimeProvider { diff --git a/SmartTeslaAmpSetter/Shared/SmartTeslaAmpSetter.Shared.csproj b/SmartTeslaAmpSetter/Shared/SmartTeslaAmpSetter.Shared.csproj index 9ac5160ee..987f14931 100644 --- a/SmartTeslaAmpSetter/Shared/SmartTeslaAmpSetter.Shared.csproj +++ b/SmartTeslaAmpSetter/Shared/SmartTeslaAmpSetter.Shared.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -15,6 +15,9 @@ + + + diff --git a/SmartTeslaAmpSetter/Shared/TimeProviding/DateTimeProvider.cs b/SmartTeslaAmpSetter/Shared/TimeProviding/DateTimeProvider.cs index 18ba5bae1..ff7b82f1e 100644 --- a/SmartTeslaAmpSetter/Shared/TimeProviding/DateTimeProvider.cs +++ b/SmartTeslaAmpSetter/Shared/TimeProviding/DateTimeProvider.cs @@ -1,4 +1,6 @@ -namespace SmartTeslaAmpSetter.Shared.TimeProviding; +using SmartTeslaAmpSetter.Shared.Contracts; + +namespace SmartTeslaAmpSetter.Shared.TimeProviding; public class DateTimeProvider : IDateTimeProvider { diff --git a/SmartTeslaAmpSetter/Shared/TimeProviding/FakeDateTimeProvider.cs b/SmartTeslaAmpSetter/Shared/TimeProviding/FakeDateTimeProvider.cs index 4d4c475ea..bc2f0950a 100644 --- a/SmartTeslaAmpSetter/Shared/TimeProviding/FakeDateTimeProvider.cs +++ b/SmartTeslaAmpSetter/Shared/TimeProviding/FakeDateTimeProvider.cs @@ -1,4 +1,6 @@ -namespace SmartTeslaAmpSetter.Shared.TimeProviding; +using SmartTeslaAmpSetter.Shared.Contracts; + +namespace SmartTeslaAmpSetter.Shared.TimeProviding; public class FakeDateTimeProvider : IDateTimeProvider { diff --git a/SmartTeslaAmpSetter/Server/Wrappers/ConfigurationWrapper.cs b/SmartTeslaAmpSetter/Shared/Wrappers/ConfigurationWrapper.cs similarity index 79% rename from SmartTeslaAmpSetter/Server/Wrappers/ConfigurationWrapper.cs rename to SmartTeslaAmpSetter/Shared/Wrappers/ConfigurationWrapper.cs index 542f8f3ed..2756cd09e 100644 --- a/SmartTeslaAmpSetter/Server/Wrappers/ConfigurationWrapper.cs +++ b/SmartTeslaAmpSetter/Shared/Wrappers/ConfigurationWrapper.cs @@ -1,8 +1,10 @@ using System.Runtime.CompilerServices; -using SmartTeslaAmpSetter.Server.Contracts; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using SmartTeslaAmpSetter.Shared.Contracts; [assembly: InternalsVisibleTo("SmartTeslaAmpSetter.Tests")] -namespace SmartTeslaAmpSetter.Server.Wrappers; +namespace SmartTeslaAmpSetter.Shared.Wrappers; public class ConfigurationWrapper : IConfigurationWrapper { @@ -18,7 +20,7 @@ public ConfigurationWrapper(ILogger logger, IConfiguration public string ConfigFileLocation() { var environmentVariableName = "ConfigFileLocation"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -54,7 +56,7 @@ public TimeSpan PvValueJobUpdateIntervall() public string MqqtClientId() { var environmentVariableName = "MqqtClientId"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -62,7 +64,47 @@ public string MqqtClientId() public string MosquitoServer() { var environmentVariableName = "MosquitoServer"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); + _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); + return value; + } + + public string TeslaMateDbServer() + { + var environmentVariableName = "TeslaMateDbServer"; + var value = _configuration.GetValue(environmentVariableName); + _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); + return value; + } + + public int TeslaMateDbPort() + { + var environmentVariableName = "TeslaMateDbPort"; + var value = _configuration.GetValue(environmentVariableName); + _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); + return value; + } + + public string TeslaMateDbDatabaseName() + { + var environmentVariableName = "TeslaMateDbDatabaseName"; + var value = _configuration.GetValue(environmentVariableName); + _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); + return value; + } + + public string TeslaMateDbUser() + { + var environmentVariableName = "TeslaMateDbUser"; + var value = _configuration.GetValue(environmentVariableName); + _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); + return value; + } + + public string TeslaMateDbPassword() + { + var environmentVariableName = "TeslaMateDbPassword"; + var value = _configuration.GetValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -70,7 +112,7 @@ public string MosquitoServer() public string CurrentPowerToGridUrl() { var environmentVariableName = "CurrentPowerToGridUrl"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -78,7 +120,7 @@ public string CurrentPowerToGridUrl() public string? CurrentInverterPowerUrl() { var environmentVariableName = "CurrentInverterPowerUrl"; - var value = GetNullableConfigurationValue(environmentVariableName); + var value = GetNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -174,7 +216,7 @@ public bool CurrentPowerToGridInvertValue() public string TeslaMateApiBaseUrl() { var environmentVariableName = "TeslaMateApiBaseUrl"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -182,7 +224,7 @@ public string TeslaMateApiBaseUrl() public List CarPriorities() { var environmentVariableName = "CarPriorities"; - var rawValue = GetNotNullableConfigurationValue(environmentVariableName); + var rawValue = GetNotNullableConfigurationValue(environmentVariableName); var value = rawValue.Split("|").Select(id => Convert.ToInt32(id)).ToList(); _logger.LogDebug("Config value extracted: [{key}]: {@value}", environmentVariableName, value); return value; @@ -191,7 +233,7 @@ public List CarPriorities() public string GeoFence() { var environmentVariableName = "GeoFence"; - var value = GetNotNullableConfigurationValue(environmentVariableName); + var value = GetNotNullableConfigurationValue(environmentVariableName); _logger.LogDebug("Config value extracted: [{key}]: {value}", environmentVariableName, value); return value; } @@ -238,10 +280,10 @@ public int PowerBuffer() return value; } - internal string GetNotNullableConfigurationValue(string environmentVariableName) + internal T GetNotNullableConfigurationValue(string environmentVariableName) { - var value = GetNullableConfigurationValue(environmentVariableName); - if (string.IsNullOrEmpty(value)) + var value = GetNullableConfigurationValue(environmentVariableName); + if (value == null) { var exception = new NullReferenceException($"Configuration value {environmentVariableName} is null or empty"); @@ -252,9 +294,9 @@ internal string GetNotNullableConfigurationValue(string environmentVariableName) return value; } - internal string? GetNullableConfigurationValue(string environmentVariableName) + internal T? GetNullableConfigurationValue(string environmentVariableName) { - return _configuration.GetValue(environmentVariableName); + return _configuration.GetValue(environmentVariableName); } internal TimeSpan GetSecondsConfigurationValueIfGreaterThanMinumum(string environmentVariableName, TimeSpan minimum) From 185d056307894aeffb1eccd17e72350e7a9efe5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sat, 2 Jul 2022 20:50:04 +0200 Subject: [PATCH 3/7] feat(ChargingService): Reduce charging speed based on pilot amp --- SmartTeslaAmpSetter/Client/Pages/Index.razor | 8 ++++++++ .../Server/Services/CarDbUpdateService.cs | 6 +----- .../Server/Services/ChargingService.cs | 15 +++++++++++++++ .../Shared/Dtos/Settings/CarState.cs | 2 ++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/SmartTeslaAmpSetter/Client/Pages/Index.razor b/SmartTeslaAmpSetter/Client/Pages/Index.razor index c68810ff3..e12fbbf00 100644 --- a/SmartTeslaAmpSetter/Client/Pages/Index.razor +++ b/SmartTeslaAmpSetter/Client/Pages/Index.razor @@ -96,6 +96,14 @@ else @car.CarState.Name + + + Pilot Current + + + @car.CarState.ChargerPilotCurrent + + StateString diff --git a/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs index ca9364b17..2518b13ac 100644 --- a/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs +++ b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs @@ -32,11 +32,7 @@ public async Task UpdateCarsFromDatabase() .FirstOrDefaultAsync(); _logger.LogTrace("Pilot Current for var {car} is {pilotCurrent}", car.Id, pilotCurrent); - //ToDo: Remove telegram notification - if (pilotCurrent < 16 && car.CarState.ChargerActualCurrent > 0) - { - await _telegramService.SendMessage($"Pilot Current for var {car.Id} is {pilotCurrent}"); - } + car.CarState.ChargerPilotCurrent = pilotCurrent; } } } \ No newline at end of file diff --git a/SmartTeslaAmpSetter/Server/Services/ChargingService.cs b/SmartTeslaAmpSetter/Server/Services/ChargingService.cs index 60b29623d..9d4d9af00 100644 --- a/SmartTeslaAmpSetter/Server/Services/ChargingService.cs +++ b/SmartTeslaAmpSetter/Server/Services/ChargingService.cs @@ -180,6 +180,21 @@ private async Task ChangeCarAmp(Car car, int ampToChange) var maxAmpPerCar = car.CarConfiguration.MaximumAmpere; _logger.LogDebug("Min amp for car: {amp}", minAmpPerCar); _logger.LogDebug("Max amp for car: {amp}", maxAmpPerCar); + if (car.CarState.ChargerPilotCurrent != null && maxAmpPerCar > car.CarState.ChargerPilotCurrent) + { + _logger.LogWarning("Charging speed of {carID} id reduced to {amp}", car.Id, car.CarState.ChargerPilotCurrent); + maxAmpPerCar = (int)car.CarState.ChargerPilotCurrent; + if (!car.CarState.ReducedChargeSpeedWarning) + { + car.CarState.ReducedChargeSpeedWarning = true; + await _telegramService.SendMessage($"Charging of {car.CarState.Name} is reduced to {car.CarState.ChargerPilotCurrent} due to chargelimit of wallbox.").ConfigureAwait(false); + } + } + else if(car.CarState.ReducedChargeSpeedWarning) + { + car.CarState.ReducedChargeSpeedWarning = false; + await _telegramService.SendMessage($"Charging speed of {car.CarState.Name} is regained.").ConfigureAwait(false); + } EnableFullSpeedChargeIfMinimumSocNotReachable(car); DisableFullSpeedChargeIfMinimumSocReachedOrMinimumSocReachable(car); diff --git a/SmartTeslaAmpSetter/Shared/Dtos/Settings/CarState.cs b/SmartTeslaAmpSetter/Shared/Dtos/Settings/CarState.cs index cd7c51a53..7d8917688 100644 --- a/SmartTeslaAmpSetter/Shared/Dtos/Settings/CarState.cs +++ b/SmartTeslaAmpSetter/Shared/Dtos/Settings/CarState.cs @@ -18,6 +18,7 @@ public class CarState public int? ChargerVoltage { get; set; } public int? ChargerActualCurrent { get; set; } + public int? ChargerPilotCurrent { get; set; } public bool? PluggedIn { get; set; } public bool? ClimateOn { get; set; } public int? ChargingPowerAtHome { get; set; } @@ -33,4 +34,5 @@ public int? ChargingPower public string? StateString { get; set; } public Enums.CarState? State { get; set; } public bool? Healthy { get; set; } + public bool ReducedChargeSpeedWarning { get; set; } } \ No newline at end of file From b07f503196a91bf5ff1d828f6d49e5a507fd103b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sun, 3 Jul 2022 02:59:29 +0200 Subject: [PATCH 4/7] fix(solution): remove unnecessary code --- SmartTeslaAmpSetter.sln | 6 ------ 1 file changed, 6 deletions(-) diff --git a/SmartTeslaAmpSetter.sln b/SmartTeslaAmpSetter.sln index 3ca90167f..38a40e8aa 100644 --- a/SmartTeslaAmpSetter.sln +++ b/SmartTeslaAmpSetter.sln @@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmartTeslaAmpSetter.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.SolarEdge", "Plugins.SolarEdge\Plugins.SolarEdge.csproj", "{9F3C7BDB-B856-4C09-BD17-784312A9B095}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartTeslaAmpSetter.Model", "SmartTeslaAmpSetter.Model\SmartTeslaAmpSetter.Model.csproj", "{8247068B-4A75-40FB-B5BE-1C557CE20AC9}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,10 +45,6 @@ Global {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.Build.0 = Release|Any CPU - {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 7957dbaa3019a995237a1c4ab730c8b5de121cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sun, 3 Jul 2022 03:05:39 +0200 Subject: [PATCH 5/7] feat(README): Add additional environment variables --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 8f21325c4..af8381c7a 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,11 @@ Note: TeslaMateApi has to be configured to allow any command without authenticat | **CurrentInverterPowerJsonPattern** | string | If Power from inverter is json formated use this to extract the correct value | $.data.overage | | **TelegramBotKey** | string | Telegram Bot API key | 1234567890:ASDFuiauhwerlfvasedr | | **TelegramChannelId** | string | ChannelId Telegram bot should send messages to | -156480125 | +| **TeslaMateDbServer** | string | Name or IP Address of the TeslaMate database service | database | +| **TeslaMateDbPort** | int | Port of the TeslaMate database service | 5432 | +| **TeslaMateDbDatabaseName** | string | Database Name of the TeslaMate database service | teslamate | +| **TeslaMateDbUser** | string | Database user name of the TeslaMate database service | teslamate | +| **TeslaMateDbPassword** | string | Database user's password of the TeslaMate database service | secret | ### Car Priorities If you set `CarPriorities` environment variable like the example above, the car with ID 2 will only start charing, if car 1 is charging at full speed and there is still power left, or if car 1 is not charging due to reached battery limit or not within specified geofence. Note: You always have to add the car Ids to this list separated by `|`. Even if you only have one car you need to ad the car's Id but then without `|`. From 1bd26badcdea5068a58acd9924fa37b6166d5d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sun, 3 Jul 2022 02:59:29 +0200 Subject: [PATCH 6/7] Revert "fix(solution): remove unnecessary code" This reverts commit b07f503196a91bf5ff1d828f6d49e5a507fd103b. --- SmartTeslaAmpSetter.sln | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SmartTeslaAmpSetter.sln b/SmartTeslaAmpSetter.sln index 38a40e8aa..3ca90167f 100644 --- a/SmartTeslaAmpSetter.sln +++ b/SmartTeslaAmpSetter.sln @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmartTeslaAmpSetter.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugins.SolarEdge", "Plugins.SolarEdge\Plugins.SolarEdge.csproj", "{9F3C7BDB-B856-4C09-BD17-784312A9B095}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartTeslaAmpSetter.Model", "SmartTeslaAmpSetter.Model\SmartTeslaAmpSetter.Model.csproj", "{8247068B-4A75-40FB-B5BE-1C557CE20AC9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,6 +47,10 @@ Global {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F3C7BDB-B856-4C09-BD17-784312A9B095}.Release|Any CPU.Build.0 = Release|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8247068B-4A75-40FB-B5BE-1C557CE20AC9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From fd9abefebd1143c9e0c9c23b7408570579ada7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20K=C3=BChnel?= Date: Sun, 3 Jul 2022 03:13:59 +0200 Subject: [PATCH 7/7] feat(CarDbUpdateService): Log db connection error and wait one minute for retry --- .../Server/Services/CarDbUpdateService.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs index 2518b13ac..f2383884f 100644 --- a/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs +++ b/SmartTeslaAmpSetter/Server/Services/CarDbUpdateService.cs @@ -25,14 +25,23 @@ public async Task UpdateCarsFromDatabase() _logger.LogTrace("{method}()", nameof(UpdateCarsFromDatabase)); foreach (var car in _settings.Cars) { - var pilotCurrent = await _teslamateContext.Charges - .Where(c => c.ChargingProcess.CarId == car.Id) - .OrderByDescending(c => c.Date) - .Select(c => c.ChargerPilotCurrent) - .FirstOrDefaultAsync(); - _logger.LogTrace("Pilot Current for var {car} is {pilotCurrent}", car.Id, pilotCurrent); - - car.CarState.ChargerPilotCurrent = pilotCurrent; + try + { + var pilotCurrent = await _teslamateContext.Charges + .Where(c => c.ChargingProcess.CarId == car.Id) + .OrderByDescending(c => c.Date) + .Select(c => c.ChargerPilotCurrent) + .FirstOrDefaultAsync(); + _logger.LogTrace("Pilot Current for var {car} is {pilotCurrent}", car.Id, pilotCurrent); + car.CarState.ChargerPilotCurrent = pilotCurrent; + } + catch (Exception exception) + { + _logger.LogError(exception, "Error while trying to get pilot current from database. Retrying in one minute."); + await Task.Delay(TimeSpan.FromMinutes(1)); + } + + } } } \ No newline at end of file