Sponsored

Calculating Mi/Kwh from App API Data

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
I've been tinkering on some code that I eventually want to track driving efficiency and cost data for my R1T. I'm currently polling the API for current mileage and battery charge percentage data along with other data that I'm interested in.

Initially I thought that the Mi/Kwh calculation should be (CurrentMiles - StartingMiles) / ((StartingCharge - CurrentCharge) / 100) * 135kwh. Unfortunately, this results in numbers in the 3 mi / kwh range, which doesn't match whats displayed by the in car efficiency data.

I found another post that talked about needing to double the reported used kwh per hrip to get the numbers to work out. (https://www.rivianforums.com/forum/threads/what-is-the-math-behind-efficiency-calculation.11262/)

I haven't compared any numbers against the reported charge data either, so maybe these numbers will make more sense if I normalize them with charging data. Off the top of my head, I'm thinking kwhPerBatteryPercent = kwhAdded / (chargeEnd - chargeStart).

Thoughts?
Sponsored

 
OP
OP

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
Currently my data is looking like this (using 270kwh for 100% battery capacity):

Code:
{
  "startingMilage": 616.0435052827844,
  "startingBattery": 53.5,
  "efficiencyData": [
    {
      "datetime": "20231014 15:58:1697313506",
      "milesDriven": 0.372902423865753,
      "kwhConsumed": 0.2699945999999983,
      "efficiency": 1.3811477113459134
    },
    
    ...
    
    {
      "datetime": "20231014 16:27:1697315261",
      "milesDriven": 0.5854568054692209,
      "kwhConsumed": 0.5400027000000008,
      "efficiency": 1.0841738485182018
    }
  ],
  "endingMilage": 636.9807333747669,
  "endingCharge": 48.200001,
  "avgEfficiency": 1.4646952787350098
}
 

MrMusAddict

Well-Known Member
Joined
Oct 29, 2022
Threads
42
Messages
323
Reaction score
890
Location
Oregon
Vehicles
2023 Rivian R1T
Occupation
Data Analyst
Hmm, I haven't specifically tinkered with the API directly. But I can say that when I plug in mileage and % consumed that I see in my ElectraFi dashboard, into your equation, I get numbers that appear normal.


(Going Uphill)
(1011.89 - 985.92) / ((77.2 - 66.09)/100) * 135 = 1.73150648398173

(Going Downhill)
(1044.16 - 1016.35) / ((62.9 - 54.29)/100) * 135 = 2.39256678281069

That is to say, the formula seems to be correct. I'm not sure ElectraFi would be manipulating the mileage or start/end percent, and those efficiency results came from your formula not ElectraFi.

Two questions:

  1. Based on doubling the result in your code, 2.9 mi / kWh seems on the high side of normal. What was your speed and elevation change during your test?
  2. What was the efficiency reported by your vehicle?
 

sub

Well-Known Member
Joined
Jul 23, 2021
Threads
34
Messages
1,873
Reaction score
3,306
Location
USA
Vehicles
Rivian R1S, Tesla Model 3
This is also a topic that I have spent quite a bit of time trying to figure out.


Assuming 135 kwh for the 100% battery is definitely not right. There isn't 135 kwh of usable capacity.

The vehicle reports 127 via the API.

Code:
"batteryCapacity": {
"__typename": "TimeStampedFloat",
"timeStamp": "2023-08-03T14:58:50.761Z",
"value": 127
},
But even that doesn't really help, because it is a fixed number (all large packs report exactly 127) so it doesn't account for degradation. The battery is going to degrade over time, if you don't account for this, the values are not useful for long term comparisons.

distanceToEmpty seems like it should account for any battery degradation that has happened, but rivian claims that the displayed range is adaptive based on driving history. I haven't found evidence proving that they actually do this. My 70% range has never changed (when looking at the same drive mode). But still I don't like applying a static conversion constant to that when Rivian claims they are using a dynamic conversion.

Thus far the most promising idea I have is to watch the charge cycle to figure out how many kwH are in each %, and then watch the % dropping when driving to calculate the efficiency. But I haven't had to to verify that this actually works.
 

sub

Well-Known Member
Joined
Jul 23, 2021
Threads
34
Messages
1,873
Reaction score
3,306
Location
USA
Vehicles
Rivian R1S, Tesla Model 3
Also, the API is capable of providing more information that what you will find in electrify's logs or in the commonly found documentation (which came from someone decompiling the rivian app).

For example, you probably didn't see the batteryCapacity field in the documentation you were looking at. I found that and quite a few other fields by guessing new field names seeing which if any Rivian will respond to.

My real hope is that eventually I or someone else will find a field reports the battery state in kwh or can be converted to that via a static conversion constant.
 

Sponsored

MrMusAddict

Well-Known Member
Joined
Oct 29, 2022
Threads
42
Messages
323
Reaction score
890
Location
Oregon
Vehicles
2023 Rivian R1T
Occupation
Data Analyst
This is also a topic that I have spent quite a bit of time trying to figure out.


Assuming 135 kwh for the 100% battery is definitely not right. There isn't 135 kwh of usable capacity.

The vehicle reports 127 via the API.

Code:
"batteryCapacity": {
"__typename": "TimeStampedFloat",
"timeStamp": "2023-08-03T14:58:50.761Z",
"value": 127
},
But even that doesn't really help, because it is a fixed number (all large packs report exactly 127) so it doesn't account for degradation. The battery is going to degrade over time, if you don't account for this, the values are not useful for long term comparisons.

distanceToEmpty seems like it should account for any battery degradation that has happened, but rivian claims that the displayed range is adaptive based on driving history. I haven't found evidence proving that they actually do this. My 70% range has never changed (when looking at the same drive mode). But still I don't like applying a static conversion constant to that when Rivian claims they are using a dynamic conversion.

Thus far the most promising idea I have is to watch the charge cycle to figure out how many kwH are in each %, and then watch the % dropping when driving to calculate the efficiency. But I haven't had to to verify that this actually works.

Yeah, true. To clarify, I was just pointing out that their first formula is nearly perfect, it's just that the variables are not.

There's definitely room for improvement for calculating the battery's capacity/start SOC/end SOC. But the problem OP seems to be having is that the battery capacity needs to increase for their high efficiency numbers to make sense, whereas 127 + degradation would be decreasing the capacity and make the high efficiency numbers even higher.

So, that implies that either OP had a truly efficient drive (which seems unlikely since they say their vehicle reports a different efficiency for the drive), or they might be pulling the API data incorrectly?
 
OP
OP

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
Also, the API is capable of providing more information that what you will find in electrify's logs or in the commonly found documentation (which came from someone decompiling the rivian app).

For example, you probably didn't see the batteryCapacity field in the documentation you were looking at. I found that and quite a few other fields by guessing new field names seeing which if any Rivian will respond to.

My real hope is that eventually I or someone else will find a field reports the battery state in kwh or can be converted to that via a static conversion constant.
Yeah, I suspected there was more data behind the API, I'm weary of probing the API too much. How did you find the BatteryCapacity field?

I'm about to take a 50mi round trip and plan to use the in vehicle trip meter, I'll report back on the data when I get back.
 

sub

Well-Known Member
Joined
Jul 23, 2021
Threads
34
Messages
1,873
Reaction score
3,306
Location
USA
Vehicles
Rivian R1S, Tesla Model 3
Yeah, true. To clarify, I was just pointing out that their first formula is nearly perfect, it's just that the variables are not.

There's definitely room for improvement for calculating the battery's capacity/start SOC/end SOC. But the problem OP seems to be having is that the battery capacity needs to increase for their high efficiency numbers to make sense, whereas 127 + degradation would be decreasing the capacity and make the high efficiency numbers even higher.

So, that implies that either OP had a truly efficient drive (which seems unlikely since they say their vehicle reports a different efficiency for the drive), or they might be pulling the API data incorrectly?
Unreasonably good efficiency calculation could come from forgetting to convert units. Or doing the conversion wrong.

The API reports data in inconsistent and counterintuitive units. I'm pretty sure I remember one of the fields even had miles in the name yet was actually kilometers or some other distance unit.

Make sure you didn't calculate km / kwh thinking it was mi/kwh.

Also if you change driving modes mid drive to a mode that is more efficient it will screw up any calculation based on range remaining making it look like you got unreasonably good efficiency. Even if you don't change modes, at least in theory the vehicle could update range remaining calculation mid drive and mess up your calculation if you are using range remaining to calculate energy use.
 

sub

Well-Known Member
Joined
Jul 23, 2021
Threads
34
Messages
1,873
Reaction score
3,306
Location
USA
Vehicles
Rivian R1S, Tesla Model 3
Yeah, I suspected there was more data behind the API, I'm weary of probing the API too much. How did you find the BatteryCapacity field?

I'm about to take a 50mi round trip and plan to use the in vehicle trip meter, I'll report back on the data when I get back.
I just spent a few days guessing field names and seeing what happens when I ask for them.

The vehicle status API just gives you a generic, completely unhelpful error message if you ask for a field that doesn't exist. But the charging API is configured differently and provides helpful tips when you ask for a non-existent field. If the field doesn't exist but there's something close it will say maybe you meant one of these other things, a, b, or c.
 

MrMusAddict

Well-Known Member
Joined
Oct 29, 2022
Threads
42
Messages
323
Reaction score
890
Location
Oregon
Vehicles
2023 Rivian R1T
Occupation
Data Analyst
Make sure you didn't calculate km / kwh thinking it was mi/kwh.
@jime_r1t could that be it? Changing the "mileage" from "616 - 637 km" to "383 - 396 mi" would change your efficiency from 2.9mi/kWh to 1.8mi/kWh, which seems more in line with reality.
 

Sponsored

Forager

Well-Known Member
Joined
Jul 21, 2021
Threads
13
Messages
734
Reaction score
1,086
Location
PNW
Vehicles
R1T
Occupation
Structural Engineer
Clubs
 
From what I can tell just monitoring the UI trip odometers, the reported efficiency is based only on drivetrain energy use —it ignores energy consumed on cabin HVAC and stereo. What I’m less sure about it energy loss due to battery heating, but I think it excludes that as well because I see my SoC dropping precipitously on cold mornings but my odometer efficiency barely moves (I’ve been resetting the trip B odometer every 200-300 miles while I make various changes to my truck).
 
OP
OP

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
ok.. So the numbers actually came out about right compared to the onboard trip meter. As you suggested, I put the total battery capacity to 127Kwh instead of 135Kwh.

I also added some more calculations at the end of drive calulations to show me what my code thinks total milesDriven and kwhUsed.

Code:
  "endingMilage": 697.4481044126787,
  "endingCharge": 46.0,
  "milesDriven": 59.93971410814174,
  "kwhUsed": 26.669999999999998,
  "avgEfficiency": 2.24745834676197
The Trip Computer Claimed:
60.4 mi driven
28 kwh Used
Efficiency: 2.17 mi/kwh

I think part of what confused me is that I was looking at the live-ish data, which range from 1 mi/kwh up to 4+ mi/kwh. I'm polling every minute when the code sees the power state is 'go'.

I still need to tweak the very fuzzy logic that tries to grab the starting milage and charge state. This issue being the vehicle reports data to the cloud at different times for the various fields.

I'm also going to implement a more dynamic kwh / battery percentage based on the charge data, but I need to write the charge data code first :)
 
OP
OP

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
From what I can tell just monitoring the UI trip odometers, the reported efficiency is based only on drivetrain energy use —it ignores energy consumed on cabin HVAC and stereo. What I’m less sure about it energy loss due to battery heating, but I think it excludes that as well because I see my SoC dropping precipitously on cold mornings but my odometer efficiency barely moves (I’ve been resetting the trip B odometer every 200-300 miles while I make various changes to my truck).
That's a good point, I'm more interested in total cost, so I'd be good including other power draw sources in my calculations
 
OP
OP

jime_r1t

Well-Known Member
First Name
Jim
Joined
Mar 16, 2023
Threads
5
Messages
49
Reaction score
15
Location
Mid-Atlantic
Vehicles
R1T
@jime_r1t could that be it? Changing the "mileage" from "616 - 637 km" to "383 - 396 mi" would change your efficiency from 2.9mi/kWh to 1.8mi/kWh, which seems more in line with reality.
I take care of the Meters to Miles and Celsius to Fahrenheit conversions right in the polling code.

Code:
def getVehicleState(self) -> dict:
        reqBody = {
            "operationName": "GetVehicleState",
            "variables": {
                "vehicleID": self.getVehicleID()
            },
            "query": "query GetVehicleState($vehicleID: String!) { vehicleState(id: $vehicleID) { __typename gnssLocation { __typename latitude longitude timeStamp } timeToEndOfCharge { __typename timeStamp value } gearGuardLocked { __typename timeStamp value } powerState { __typename timeStamp value } batteryHvThermalEventPropagation { __typename timeStamp value } vehicleMileage { __typename timeStamp value } gearStatus { __typename timeStamp value } batteryLevel { __typename timeStamp value } chargerState { __typename timeStamp value } batteryLimit { __typename timeStamp value } remoteChargingAvailable { __typename timeStamp value } batteryHvThermalEvent { __typename timeStamp value } rangeThreshold { __typename timeStamp value } distanceToEmpty { __typename timeStamp value } cabinClimateInteriorTemperature { __typename timeStamp value } chargerStatus { __typename timeStamp value } chargerDerateStatus { __typename timeStamp value } driveMode { __typename timeStamp value } } }"
        }

        self.login()

        resp = requests.post(self.GATEWAY_URL, headers=self.getReqHeader(), json=reqBody)

        resp_data = resp.json()["data"]["vehicleState"]

        for key in resp_data.keys():
            if (key == "__typename"):
                continue
            elif ("value" in resp_data[key]):
                if (key == "vehicleMileage"):
                    self.vehicleState[key] = resp_data[key]["value"] / M2MI
                elif (key == "cabinClimateInteriorTemperature"):
                    self.vehicleState[key] = (resp_data[key]["value"] * (9/5)) + 32
                else:
                    self.vehicleState[key] = resp_data[key]["value"]
            else:
                self.vehicleState[key] = resp_data[key]
        return self.vehicleState
Sponsored

 
 








Top