Skip to content

Commit

Permalink
Merge branch 'bassmaster187:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
superfloh247 authored Feb 10, 2025
2 parents 0b4fafb + a60f1e8 commit 1d16eb6
Show file tree
Hide file tree
Showing 39 changed files with 1,588 additions and 48 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ You can import your Teslamate data [here](Teslamate-Import/README.md).

You can setup a link from Teslalogger to Abetterrouteplanner to avoid giving your Tesla credentials to a 3rd Party. Another benefit is to minimize the possibility to prevent the car from going to sleep if more than one service is using your credentials. [YouTube](https://www.youtube.com/watch?v=00s7Y8Iv2iw)

## Tesla Invoices Download

All Supercharger invoices will be downloaded automatically in subfolder "\\raspberry\teslalogger\tesla_invoices" on Raspberries or "\TeslaLogger\bin\tesla_invoices" on Docker

## Translations
You can use our [Weblate page](https://hosted.weblate.org/engage/teslalogger/) to help translate Teslalogger into new languages.

Expand Down
1 change: 1 addition & 0 deletions TeslaLogger/Car.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ public bool Virtual_key
internal string FleetApiAddress = "";
public string _access_type;
public bool _virtual_key;
internal bool vehicle_location = true;

[MethodImpl(MethodImplOptions.Synchronized)]
internal TeslaAPIState GetTeslaAPIState() { return teslaAPIState; }
Expand Down
4 changes: 4 additions & 0 deletions TeslaLogger/ElectricityMeterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public static ElectricityMeterBase Instance(string type, string host, string par
return new ElectricityMeterKeba(host, paramater);
else if (type == "evcc")
return new ElectricityMeterEVCC(host, paramater);
else if (type == "smartevse3")
return new ElectricityMeterSmartEVSE3(host, paramater);
else if (type == "warp")
return new ElectricityMeterWARP(host, paramater);

return null;
}
Expand Down
89 changes: 75 additions & 14 deletions TeslaLogger/ElectricityMeterEVCC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class ElectricityMeterEVCC : ElectricityMeterBase
{
string host;
string parameter;
string loadpointname;
string loadpointcarname;
internal string api_state;

Guid guid; // defaults to new Guid();
static WebClient client;
Expand All @@ -30,14 +31,19 @@ public ElectricityMeterEVCC(string host, string parameter)

if(parameter != null)
{
loadpointname = parameter;
loadpointcarname = parameter;
}
}

string GetCurrentData()
{
try
{
if (api_state != null)
{
return api_state;
}

string cacheKey = "evcc_" + guid.ToString();
object o = MemoryCache.Default.Get(cacheKey);

Expand Down Expand Up @@ -70,6 +76,39 @@ string GetCurrentData()
return "";
}

JToken getLoadPointJson(dynamic json)
{
JToken loadpoint = null;
// loadpointcarname can be vehicle title ("TestCar1", vehicle name ("tsla") or loadpoint name ("Wallbox1")
// Maybe vehicle name?
loadpoint = json.SelectToken($"$.result.loadpoints[?(@.vehicleName == '{loadpointcarname}')]");

if (loadpoint == null)
{
// it's not a vehicle name, maybe vehicle title?
foreach (var vehicle in json.result.vehicles)
{
string vehicleTitle = vehicle.Value.title;
string vehicleName = vehicle.Name;
if (vehicleTitle == loadpointcarname)
{
loadpoint = json.SelectToken($"$.result.loadpoints[?(@.vehicleName == '{vehicleName}')]");
continue;
}
}
// it's also not a vehicle title. Maybe loadpoint title?
if (loadpoint == null)
{

loadpoint = json.SelectToken($"$.result.loadpoints[?(@.title == '{loadpointcarname}')]");
if (loadpoint == null)
{
return null;
}
}
}
return loadpoint;
}

public override double? GetUtilityMeterReading_kWh()
{
Expand All @@ -86,18 +125,31 @@ string GetCurrentData()
if (!Tools.IsPropertyExist(jsonResult, "result"))
return null;

Dictionary<string, object> r1 = jsonResult["result"].ToObject<Dictionary<string, object>>();

if (r1.ContainsKey("gridEnergy"))
JToken grid = jsonResult.SelectToken($"$.result.grid");
if (grid != null)
{
double.TryParse(r1["gridEnergy"].ToString(), out double value);
Dictionary<string, object> r1 = grid.ToObject<Dictionary<string, object>>();

return value;
if (r1.ContainsKey("energy"))
{
double.TryParse(r1["energy"].ToString(), out double value);
return value;
}
}
else
{
return null;
Dictionary<string, object> r1 = jsonResult["result"].ToObject<Dictionary<string, object>>();

if (r1.ContainsKey("gridEnergy"))
{
double.TryParse(r1["gridEnergy"].ToString(), out double value);

return value;
}
}
return null;


}
catch (Exception ex)
{
Expand All @@ -122,9 +174,12 @@ string GetCurrentData()
if (!Tools.IsPropertyExist(jsonResult, "result"))
return null;

JToken acme = jsonResult.SelectToken($"$.result.loadpoints[?(@.title == '{loadpointname}')]");
JToken loadpoint = getLoadPointJson(jsonResult);

if (loadpoint == null)
return null;

Dictionary<string, object> r1 = acme.ToObject<Dictionary<string, object>>();
Dictionary<string, object> r1 = loadpoint.ToObject<Dictionary<string, object>>();

if (r1.ContainsKey("chargeTotalImport"))
{
Expand Down Expand Up @@ -160,9 +215,12 @@ string GetCurrentData()
if (!Tools.IsPropertyExist(jsonResult, "result"))
return null;

JToken acme = jsonResult.SelectToken($"$.result.loadpoints[?(@.title == '{loadpointname}')]");
JToken loadpoint = getLoadPointJson(jsonResult);

Dictionary<string, object> r1 = acme.ToObject<Dictionary<string, object>>();
if (loadpoint == null)
return null;

Dictionary<string, object> r1 = loadpoint.ToObject<Dictionary<string, object>>();

if (r1.ContainsKey("sessionPrice") && r1["sessionPrice"] != null)
{
Expand Down Expand Up @@ -200,9 +258,12 @@ string GetCurrentData()
if (!Tools.IsPropertyExist(jsonResult, "result"))
return null;

JToken acme = jsonResult.SelectToken($"$.result.loadpoints[?(@.title == '{loadpointname}')]");
JToken loadpoint = getLoadPointJson(jsonResult);

if (loadpoint == null)
return null;

Dictionary<string, object> r1 = acme.ToObject<Dictionary<string, object>>();
Dictionary<string, object> r1 = loadpoint.ToObject<Dictionary<string, object>>();

if (r1.ContainsKey("charging"))
{
Expand Down
181 changes: 181 additions & 0 deletions TeslaLogger/ElectricityMeterSmartEVSE3.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

using Exceptionless;
using Newtonsoft.Json;

namespace TeslaLogger
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Keine allgemeinen Ausnahmetypen abfangen", Justification = "<Pending>")]
class ElectricityMeterSmartEVSE3 : ElectricityMeterBase
{
private string host;
private string paramater;

internal string mockup_status, mockup_shelly;

Guid guid; // defaults to new Guid();
static WebClient client;

public ElectricityMeterSmartEVSE3(string host, string paramater)
{
this.host = host;
this.paramater = paramater;

if (client == null)
{
client = new WebClient();
}
}

string GetCurrentData()
{
try
{
if (mockup_status != null)
{
return mockup_status;
}

string cacheKey = "smartevse3_" + guid.ToString();
object o = MemoryCache.Default.Get(cacheKey);

if (o != null)
{
return (string)o;
}

string url = host + "/settings";
string lastJSON = client.DownloadString(url);

MemoryCache.Default.Add(cacheKey, lastJSON, DateTime.Now.AddSeconds(10));
return lastJSON;
}
catch (Exception ex)
{
if (ex is WebException wx)
{
if ((wx.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound)
{
Logfile.Log(wx.Message);
return "";
}

}
if (!WebHelper.FilterNetworkoutage(ex))
ex.ToExceptionless().FirstCarUserID().Submit();

Logfile.Log(ex.ToString());
}

return "";
}


public override double? GetUtilityMeterReading_kWh()
{

string j = null;
try
{
j = GetCurrentData();

if (string.IsNullOrEmpty(j))
return null;

dynamic jsonResult = JsonConvert.DeserializeObject(j);

string value = jsonResult["mains_meter"]["import_active_energy"];

return Double.Parse(value, Tools.ciEnUS);
}
catch (Exception ex)
{
ex.ToExceptionless().FirstCarUserID().Submit();
Logfile.ExceptionWriter(ex, j);
}

return null;
}

public override double? GetVehicleMeterReading_kWh()
{
string j = null;
try
{
j = GetCurrentData();

if (string.IsNullOrEmpty(j))
return null;

dynamic jsonResult = JsonConvert.DeserializeObject(j);

string value = jsonResult["ev_meter"]["import_active_energy"];

return Double.Parse(value, Tools.ciEnUS);
}
catch (Exception ex)
{
ex.ToExceptionless().FirstCarUserID().Submit();
Logfile.ExceptionWriter(ex, j);
}

return null;
}

public override bool? IsCharging()
{
string j = null;
try
{
j = GetCurrentData();

dynamic jsonResult = JsonConvert.DeserializeObject(j);
if (jsonResult == null)
return null;

return jsonResult["evse"]["state_id"] == 2 ? true : false;


}
catch (Exception ex)
{
ex.ToExceptionless().FirstCarUserID().Submit();
Logfile.ExceptionWriter(ex, j);
}

return null;
}

public override string GetVersion()
{
string j = null;
try
{
j = GetCurrentData();

dynamic jsonResult = JsonConvert.DeserializeObject(j);
if (jsonResult == null)
return null;

string fwversion = jsonResult["version"];

return fwversion;
}
catch (Exception ex)
{
if (!WebHelper.FilterNetworkoutage(ex))
ex.ToExceptionless().FirstCarUserID().Submit();

Logfile.ExceptionWriter(ex, j);
}

return "";
}
}
}
Loading

0 comments on commit 1d16eb6

Please sign in to comment.