-
Notifications
You must be signed in to change notification settings - Fork 316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dataclasses for ChargingProfile and its constituents #172
base: master
Are you sure you want to change the base?
Add dataclasses for ChargingProfile and its constituents #172
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your PR!
I'm unsure what to do this PR. I think your code is an improvement and should be included at some point.. However, the changes are backwards incompatible with the current code.
There are more backwards incompatible changes that we want to integrate on our way to a v1.0.0 release. I'll discuss with others how and what to do.
In the mean time there are some things that you can improve to your code.
Nested dataclasses can't be deserialized. Consider the following example:
from dataclasses import asdict
from ocpp.v16.call import ChargingSchedule, ChargingProfile, ChargingSchedulePeriod
from ocpp.v16.enums import ChargingProfilePurposeType, ChargingProfileKindType, ChargingRateUnitType
charging_schedule_period = { 'start_period': 0, 'limit': 10 }
charging_schedule = {
'charging_rate_unit': ChargingRateUnitType.amps,
'charging_schedule_period': [charging_schedule_period],
}
charging_profile = {
'charging_profile_id': 1,
'stack_level': 0,
'charging_profile_purpose': ChargingProfilePurposeType.tx_profile,
'charging_profile_kind': ChargingProfileKindType.absolute,
'charging_schedule': charging_schedule,
}
profile = ChargingProfile(**charging_profile)
# This fails as `profile.charging_schedule` is of type `dict`.
assert type(profile.charging_schedule) == ChargingSchedule
Can you you modify the code and make sure that nested dataclasses are deserialized correctly? I think you can use __post_init__()
for that.
Regarding the location, I suggest to put the code in it's own module ocpp.v16.charging_profile
. It doesn't really fit in ocpp.v16.call
as that module contains only payloads to construct OCPP Calls. It also doesn't fit in ocpp.v16.enums
because it isn't an enum.
No problem! Good point regarding the de-serialisation, I had missed that. I'll look to make changes to support this. Apologies, I don't quite understand the backwards incompatibility. My understanding when the payload is passed to |
Changing type of However, you're right when you write "my understanding is we don't de-serialise back to the payload class automatically anywhere ". In practice it means users implementing a Changing the type hints, as you suggested, is required to express that I think for v1.0.0 we should drop |
Ok, I follow you now. I'll go with Union for now then to avoid making a backwards incompatible change. I agree with the changes on (de)serialisation for v1.0.0 - we're doing this internally on top of the library at the minute at it would be handy to have it upstream! |
In order for remove_nones to work with the charging profile data structures it needs to be able to remove nones of nested dictionaries, as well as dictionaries made of lists of dictionaries (for example, a list of charging schedules represented as dicts). This commit modifies the logic, and adds tests
For now, dicts are acceptable to maintain backwards compatibility. Perhaps in v1.0 only the dataclass will be accepted.
remove_nones needed to change to remove keys where the value is None for nested dicts, and dicts which contains lists of dicts. These structures appear in the charging profile code. I've added that in this commit 19bfe11 If we agree that deserialisation of dicts to dataclasses is out of scope and something for v1.0 then I think this PR is ready to go. |
There is a PR I'd like to submit and was working on a variation of your change to remove_nones. +1 on that change from me. |
* Change Decimal to float * Move dataclasses to separate charging_profile module * Add ChargingProfile type to RemoteStartTransaction payload
@OrangeTux @tropxy I think this is ready to go. Are there any other changes you need? |
The PR is quite interesting in the context of smart charging algos conception and validation, which has become a requirement for charging infrastructure. What is the rationale for not next merging it since 3 years? |
Some questions:
These objects don't quite fit into calls.py, because they're not call payloads. On the other hand, they don't really fit in enums.py either. I considered adding a new file like
types.py
, but figured it best to see what your preference is?I also wanted to add a test to ensure a SetChargingProfilePayload is serialised to the correct representation when using these objects. I noticed the codebase doesn't have such tests for other payloads, so I left it. Would you like to keep it this way?
Thanks!