tandemdrive / ocpi-tariffs Goto Github PK
View Code? Open in Web Editor NEWOCPI tariff calculations
License: Apache License 2.0
OCPI tariff calculations
License: Apache License 2.0
When I have a tariff that's supposed to be free for the 30 minutes, it doesn't seem to take into account the restrictions in min_duration and max_duration.
{
"country_code": "NL",
"party_id": "TDR",
"id": "TDR1",
"currency": "EUR",
"elements": [
{
"price_components": [
{
"type": "PARKING_TIME",
"price": 0.0,
"vat": 0.0,
"step_size": 1
}
],
"restrictions": {
"min_duration": 0,
"max_duration": 1800
}
},
{
"price_components": [
{
"type": "PARKING_TIME",
"price": 3.0,
"vat": 0.0,
"step_size": 300
}
],
"restrictions": {
"min_duration": 1800
}
},
{
"price_components": [
{
"type": "FLAT",
"price": 0.50,
"vat": 20.0,
"step_size": 1
},
{
"type": "ENERGY",
"price": 0.25,
"vat": 10.0,
"step_size": 1
}
]
}
],
"end_date_time": "2019-06-30T23:59:59Z",
"last_updated": "2018-12-17T17:15:01Z"
}
Hello
Thanks for openning your tariff calculator to the community !
I was testing it and saw a bug: If you use a time restriction on a energy price component, it doesn't affect the Totals array
For exemple : here is a charge that start at 20h, take until 21h to charge 10kwh, then until 22h to charge an other 10kwh :
"start_date_time": "2015-06-29T20:00:00Z",
"end_date_time": "2015-06-29T22:00:00Z",
"charging_periods": [
{
"start_date_time": "2015-06-29T20:00:00Z",
"dimensions": [
{
"type": "ENERGY",
"volume": 10
}
]
},
{
"start_date_time": "2015-06-29T21:00:00Z",
"dimensions": [
{
"type": "ENERGY",
"volume": 10
}
]
}
],
and here is a tariff that change the kwh's price after 21h :
"elements": [
{
"restriction": {
"end_time": "21:00"
},
"price_components": [{
"type": "ENERGY",
"price": 1,
"step_size": 1
}]
},
{
"price_components": [{
"type": "ENERGY",
"price": 10,
"step_size": 1
}]
}
],
but the output will still be 20 for the kwhs instead of 110 (10 for 10kwh before 21h and 100 for 10kwh after 21h)
Cheers !
I removed the periodic outdated deps action that would fail the build, as this was too strict and got in the way of development sometimes.
I would like to add the same action, but instead of failing the build it notifies the devs that the deps are outdated.
Also the check could happen at most once a day, maybe once a week is more resonable.
Since so many parties are still on v2.1.1 is makes this tool a lot more useful to also support that version.
Clearly state in the README's that OCPI is owned and developed by the EV Roaming Foundation and that this repository has tools which use OCPI. The same should also be mentioned at ocpi-tools.com.
We want to be sure that we can parse a real CDR correctly.
It would be great if the tool could simplify tariffs by removing everything which has no effect.
Example with price components which do nothing:
{
"id": "EXAMPLE",
"currency": "EUR",
"elements": [
{
"price_components": [
{
"type": "FLAT",
"price": 0,
"step_size": 1
},
{
"type": "TIME",
"price": 0,
"step_size": 1
},
{
"type": "ENERGY",
"price": 0.54,
"step_size": 1
}
]
}
],
"last_updated": "2023-10-04T07:15:01.745Z"
}
Is equal to:
{
"id": "EXAMPLE",
"currency": "EUR",
"elements": [
{
"price_components": [
{
"type": "ENERGY",
"price": 0.54,
"step_size": 1
}
]
}
],
"last_updated": "2023-10-04T07:15:01.745Z"
}
Another typical example are restrictions which do not restrict anything. Such as:
"start_time": "00:00", "stop_time": "00:00"
"start_time": "00:00", "stop_time": "23:59"
"day_of_week": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"]
"min_duration": 0
(probably goes for all min_*
restrictions)Also having more generic tariff elements (for a certain dimension) specified before more restricting elements makes the latter one unnecessary.
I expect that tariffs with these no-op components and no-op restrictions exist because the OCPI tariff structure is generated in a way which always specified these things.
If the "last_updated" date time of the tariff is after the start date time of the CDR then show a warning that the tariff maybe a newer version than the version which was applicable at the start of the session.
Currently consumers need to provide the timezone explicitly. We should be able to detect it from the country code.
Hello ๐
We are testing our own implementation against yours, and I noticed that the following text from the spec regarding cdr.charging_periods.tariff_id is ignored:
tariff_id
Unique identifier of the Tariff that is relevant for this Charging Period. If not provided, no Tariff is relevant during this period.
The tool still uses the tariff on each charging period whether this column is set or not, which is confusing.
It would be helpful if the id
of the chosen tariff, and the associated currency
would be provided in the pricer::Report
type, currently the currency
can be deduced using the tariff_index
. The tarrif id
is however not available on the OcpiTariff
type.
I defined the tariff and CDR below. Based on my understanding of OCPI, the min_duration
restriction below should mean I am charged after 3 hours, so for the last hour of my 4 hour session.
However the tool only shows a cost for FLAT
and ENERGY
.
Only if I change min_duration
to 0
do I then receive a charge for TIME
.
{
"country_code": "NL",
"party_id": "TDR",
"id": "TDR1",
"currency": "EUR",
"elements": [
{
"restrictions": {
"min_duration": 10800
},
"price_components": [
{
"type": "TIME",
"price": 2,
"vat": 20.0,
"step_size": 900
}
]
},
{
"price_components": [
{
"type": "FLAT",
"price": 0.50,
"vat": 20.0,
"step_size": 1
},
{
"type": "ENERGY",
"price": 0.25,
"vat": 10.0,
"step_size": 1
}
]
}
],
"end_date_time": "2019-06-30T23:59:59Z",
"last_updated": "2018-12-17T17:15:01Z"
}
And the following CDR:
{
"country_code": "BE",
"party_id": "BEC",
"id": "12345",
"start_date_time": "2015-06-29T13:00:00Z",
"end_date_time": "2015-06-29T17:00:00Z",
"cdr_token": {
"uid": "012345678",
"type": "RFID",
"contract_id": "DE8ACC12E46L89"
},
"auth_method": "WHITELIST",
"cdr_location": {
"id": "LOC1",
"name": "Gent Zuid",
"address": "F.Rooseveltlaan 3A",
"city": "Gent",
"postal_code": "9000",
"country": "BEL",
"coordinates": {
"latitude": "3.729944",
"longitude": "51.047599"
},
"evse_uid": "3256",
"evse_id": "BE*BEC*E041503003",
"connector_id": "1",
"connector_standard": "IEC_62196_T2",
"connector_format": "SOCKET",
"connector_power_type": "AC_1_PHASE"
},
"currency": "EUR",
"tariffs": [],
"charging_periods": [{
"start_date_time": "2015-06-29T13:00:00Z",
"dimensions": [{
"type": "TIME",
"volume": 4
}, {
"type": "ENERGY",
"volume": 15.342
}],
"tariff_id": "12"
}],
"total_cost": {
"excl_vat": 4.00,
"incl_vat": 4.40
},
"total_energy": 15.342,
"total_time": 1.973,
"total_time_cost": {
"excl_vat": 4.00,
"incl_vat": 4.40
},
"last_updated": "2015-06-29T22:01:13Z"
}
Generate human readable text from a JSON Tariff structure. We can try to follow the structure provided by OCPI (a tariff with elements which have dimensions with restrictions) and we can try what would happen if we change the description to: tariff with dimensions and per dimension the elements with their restrictions.
Hello ๐
Comparing our own implementation to yours, I've found what I think is a misinterpretation of the (2.2.1) spec on your end. Consider the following tariff:
{
"country_code": "FI",
"party_id": "FOO",
"id": "TDR1",
"currency": "EUR",
"elements": [{
"price_components": [{
"type": "ENERGY",
"price": 0.25,
"vat": 10.0,
"step_size": 1
}],
"restrictions": {
"day_of_week": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"],
"start_time": "20:00",
"end_time": "15:00"
}
}],
"last_updated": "2018-12-17T17:15:01Z"
}
And these definitions regarding restrictions (11.4.6. TariffRestrictions class):
start_time: Start time of day in local time, the time zone is defined in the time_zone field of the Location, for example 13:30, valid from this time of the day.
end_time: End time of day in local time, the time zone is defined in the time_zone field of the Location, for example 19:45, valid until this time of the day. Same syntax as start_time. If end_time < start_time then the period wraps around to the next day. To stop at end of the day use: 00:00.
day_of_week: Which day(s) of the week this TariffElement is active.
Is it not an error that the tool considers Monday 08:01 to be covered by the tariff?
It seems like the "logical and" instruction is ignored, as the start_time on Monday is clearly 20:00 (ending at Tuesday 15:00.)
When more than one restriction is set, they are to be threaded as a logical AND. So all need to be valid before this tariff is active.
The "is it on a matching weekday"-check is indeed true, but the "is it within the start/end times" ought to to be false given the definitions of start_time and end_time above. What do you think?
Here is the CDR I used as input (which is confusing, since CDRs are the results of applying a tariff to some input ๐ฌ) for good measure:
{
"country_code": "FI",
"party_id": "FOO",
"id": "12345",
"cdr_token": {
"uid": "012345678",
"type": "RFID",
"contract_id": "DE8ACC12E46L89"
},
"auth_method": "WHITELIST",
"currency": "EUR",
"start_date_time": "2023-12-04T07:00:00Z",
"end_date_time": "2023-12-04T08:50:00Z",
"charging_periods": [{
"start_date_time": "2023-12-04T07:01:00Z",
"dimensions": [{
"type": "ENERGY",
"volume": 10
}]
}],
"total_cost": {
"incl_vat": 0,
"excl_vat": 0
},
"total_energy_cost": {
"incl_vat": 1337,
"excl_vat": 1337
},
"total_energy": 10,
"total_time": 1,
"last_updated": "2023-12-04T07:50:00Z"
}
A tariff could contain restrictions based on reservations, these are currently not handled.
Additionally a cdr could contain reservation time as a dimension and volume. It's not fully clear how this should be priced and handled.
OCPI specifies that all numbers otherwise mentioned should be rounded to 4 decimals.
When serializing tariffs, cdr's or reports we should follow this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.