Skip to content
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

🔌 🕐 Experiment with an end to end demo of departure time #64

Closed
shankari opened this issue Jul 15, 2024 · 104 comments
Closed

🔌 🕐 Experiment with an end to end demo of departure time #64

shankari opened this issue Jul 15, 2024 · 104 comments

Comments

@shankari
Copy link
Collaborator

shankari commented Jul 15, 2024

Let's try to build on #44 to include departure time.

EDIT: Simplified scenarios with a single SASchedule. More complex schedules are tracked in #68

High level scenario using AC L2:

  • ISO 15118-2 with EIM
    • plug in the car with no departure time, eamount = 60,000 Wh
    • receive SASchedule with pmax = 22,080W, max current = 32A, duration = 1 day
  • ISO 15118-2 with PnC
    • plug in the car with no departure time, eamount = 60,000 Wh
    • receive SASchedule with pmax = 22,080W, max current = 32A, duration = 1 day
  • Grid control only: grid -> CSMS sends a charging profile to the station with:
    • 10A or 6900W starting an hour before the start of the demo and running for 4 hours
    • plug in the car with no departure time, eamount = 60,000 Wh
    • receive SASchedule with pmax = 6900W, max current = 10A, duration = 1 day
  • Car control only: restart EVSE so that prior charge schedule is deleted
    • plug in the car with departure time of 6 hours (21600 secs), eamount = 60,000 Wh
    • receive SASchedule with pmax = 10,000W, max current = 15A, duration = 6 hours
  • Car + grid control: grid -> CSMS sends a charging profile to the station with:
    • 10A or 6900 W starting an hour before the start of the demo and running for 4 hours
    • plug in the car with departure time of 3 hours (10800 secs), eamount = 60,000 Wh
    • receive SASchedule with pmax = 6900W, max current = 10A, duration = 3 hours
    • note that the car does not recieve its requested energy because of the grid control. It only receives 20,700
  • Real world example: grid -> CSMS sends a charging profile to the station with:
    • 20A or 13,800 W for the next 12 hours (43200 secs, overnight, no sun is shining)
    • EV plugs in with a requested departure time of 16 hours (57600 secs) and requested energy of 85kWh [1]
    • receive SASchedule with pmax = 5312, max current = 7A, duration = 16 hours pmax (float) = 5312.5 (ceil: 5313), max_current = 7.7 (ceil 8), 15.998 hours (ceil 16).

[1] This is a real-life example from our recent trip to Arcata. We got to the hotel at around 8pm with a Tesla that was almost empty. We wanted to walk to a concert the next morning (9am - 11am) and then leave at noon rather than deal with parking at the concert venue. The hotel had validated parking in the public lot, but the charger was not smart, and there was no communication between the network and the hotel - the validated permit was a piece of paper to put on the windshield. So we got a notification at around 6am indicating that we would start getting charged for parking since the charging was complete. In this case, the fast charging was actually bad - my husband had to run down to the lot and move the car right after he woke up.

@shankari
Copy link
Collaborator Author

shankari commented Jul 15, 2024

Note that these are still very simple scenarios that are primarily focused on the communication between the station and the car. Concretely, the following scenarios are out of scope:

  • EVSE sending NotifyEVChargingNeedsRequest to the CSMS; from our previous investigation, neither MaEVe or Citrine support this properly (❇️ Smart charging demo at CharIN #44 (comment)). And Citrine doesn't work with PnC right now anyway.
  • EV sending charging profiles as part of PowerDeliveryReq or ChargingStatusReq
  • Renegotiation of any kind, either between EVSE and EV or fully end to end

There are lots of cool things we can do in terms of renegotiation and I fully agree that is where the power in smart charging is. But we are going to take one step at a time and bring in more and more complex functionality into the demo over time, involving the community, and making sure that it is consistent with what stakeholders expect. Note the final scenario here, where the EVSE is not able to meet the requested schedule - is that what we want the EVSE to return?

The goal of these initial demos is to build interest and engagement and help spearhead those conversations.

@shankari
Copy link
Collaborator Author

From a technical perspective, this demo boils down to the following technical tasks:

  • plumb through the new options that we need (departure time and requested energy) from the node-red UI through the car simulator to pyjosev to the JSEVManager module so that the correct messages are sent to the EV (@the-bay-kay, similar to Patch Cleanup After CharIN Demos #61 (comment))
  • plumb through the charge profiles from OCPP 2.0.1 to the EVSE manager module so that they can be read correctly by the EVSE ISO 15118-2 code (some combination of @shankari @louisg1337 and @drmrd)
  • update the docker image for the demo (@shankari)

We will update this issue with progress as we work on these tasks

@shankari
Copy link
Collaborator Author

shankari commented Jul 15, 2024

Looking through the patches that I slapped together quickly, the callback in the core module that handles the set limits or charge profile calls from the CSMS is in modules/OCPP201/OCPP201.cpp
which essentially calls

        this->set_external_limits(charging_schedules);                                                       
        this->publish_charging_schedules(charging_schedules);                                                
  • set_external_limits calls this->r_evse_manager.at(evse_id - 1)->call_set_external_limits(limits);
  • publish_charging_schedules calls publish_charging_schedules on the ocppImplBase base implementation. However, I don't know where that implementation actually is. I do find a default base implementation in modules/OCPP201/ocpp_generic/ocppImpl.hpp/cpp, but there is no implementation of publish_charging_schedules in it

Couple of other notes:

  • The implementation in modules/OCPP201/OCPP201.cpp seems to be a direct copy of modules/OCPP/OCPP.cpp!!
  • I don't see any declaration or definition of ocppImplBase. Searching for it gives the pointers and the subclasses, but not the original class. Given the name, I guess that it is the hookup between the module and the library.

Going to focus on the EVSE manager's call_set_external_limits for now since:

  1. That seems most promising
  2. At least I can find it!

@shankari
Copy link
Collaborator Author

That looks like it calls through to the local_energy_limitsvariable in the EvseManager - e.g.
https://github.com/EVerest/everest-core/blob/4b13b10c4b6ba7ae3edf0a9f7ddfdce274a9332a/modules/EvseManager/EvseManager.cpp#L1084

so here's where the ISO messages are sent out
https://github.com/EVerest/everest-core/blob/4b13b10c4b6ba7ae3edf0a9f7ddfdce274a9332a/modules/EvseV2G/iso_server.cpp#L1105

it's a little bit complex, and it looks like we only populate one PMaxSchedule!!

            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]
                .PMaxSchedule.PMaxScheduleEntry.array[0]
                .RelativeTimeInterval.start = 0;
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]
                .PMaxSchedule.PMaxScheduleEntry.array[0]
                .RelativeTimeInterval.duration_isUsed = 1;
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]
                .PMaxSchedule.PMaxScheduleEntry.array[0]
                .RelativeTimeInterval.duration = SA_SCHEDULE_DURATION;
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]
                .PMaxSchedule.PMaxScheduleEntry.arrayLen = 1;
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.arrayLen = 1;

Need to add more logs to figure out what is going in here for our current working scenario, and then how we can extend it going forward....

@the-bay-kay
Copy link

the-bay-kay commented Jul 15, 2024

Tracing through the repos to see where we'll need to add DepartureTime. It helps to know that this is of the type "EVChargeParameterType", and is an optional field of of the AC_EVChargeParameterType. Knowing this, we can go through the repos to figure out what needs changed.

It seems there are three variations of the AC_EVChargeParameterType that are defined:

  • First, the struct in (ext-openv2g), which appears to be a version of the din message struct defined below. Because this repository is kept for archival purposes (link), we can ignore this repo for now.
  • Second, we have iso2_AC_EVChargeParameterType, and its corresponding initialization function here
    • Interestingly, this initialization zero's out the DepartureTime, and does not set any of the other variables
  • Third, din_AC_EVChargeParameterType/ and its corresponding initialization function here
    • This init zero's out all of the values of the struct except Departure Time. Whoops, accidentally read the DC init. This init (as I understand it) sets the pointer passed as a parameter to a generic pointer for the type.

Tracing through now to see exactly when these EVChargeParameterTypes are used, should shed some light on exactly where changes are needed

@the-bay-kay
Copy link

the-bay-kay commented Jul 15, 2024

Drawing out a call graph, mostly to make sure I'm not missing anything when tracing through the code. I'll keep the diagrams updated below a fold, if folks are curious about my process.
EDIT: Since we can ignore ext-openv2g, I've updated the graph accordingly. See edits below the cut.

Call Graph

image

@shankari
Copy link
Collaborator Author

ok so the evse_sa_schedule_list is set in modules/EvseV2G/v2g_ctx.cpp, but I only see one entry being set, and I don't see how it is hooked up to the local_energy_limits.

What I see is that there is a MQTT message to set the limits.

  • API's set_limit_amps callback calls evse->call_set_external_limits
  • which seems to have the following callbacks
# grep -rl set_external_limits modules | grep -v OCPP
modules/API/API.cpp
modules/EvseManager/tests/EvseManagerStub.hpp
modules/EvseManager/evse/evse_managerImpl.cpp
modules/EvseManager/evse/evse_managerImpl.hpp
modules/EnergyNode/energy_grid/energyImpl.hpp
modules/EnergyNode/energy_grid/energyImpl.cpp
modules/EnergyNode/external_limits/external_energy_limitsImpl.cpp
modules/EnergyNode/external_limits/external_energy_limitsImpl.hpp

modules/EnergyNode/external_limits/external_energy_limitsImpl.cpp calls mod->signalExternalLimit(value); in modules/EnergyNode/energy_grid/energyImpl.cpp which calls void energyImpl::set_external_limits

In the EVSE manager, I see

void evse_managerImpl::handle_set_external_limits(types::energy::ExternalLimits& value) {
    mod->updateLocalEnergyLimit(value);
}                 

I do note

    // wait for EnergyManager to assign optimized current on next opimizer run                             

commented in some logs from the energy manager, let's see how the clamping actually gets passed through...

@shankari
Copy link
Collaborator Author

shankari commented Jul 16, 2024

Tracethrough for a single schedule
024-07-16 14:36:13.203502 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 14:36:14.297764 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 14:36:15.392452 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 14:36:16.565686 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 14:36:17.659685 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 

...

2024-07-16 14:37:52.310423 [INFO] ocpp:OCPP201     :: Received SetChargingProfile: {
    "chargingProfile": {
        "chargingProfileKind": "Absolute",
        "chargingProfilePurpose": "TxDefaultProfile",
        "chargingSchedule": [
            {
                "chargingRateUnit": "A",
                "chargingSchedulePeriod": [
                    {
                        "limit": 20.0,
                        "numberPhases": 3,
                        "startPeriod": 0
                    }
                ],
                "duration": 172800,
                "id": 0,
                "minChargingRate": 0.0,
                "startSchedule": "2024-07-16T00:00:00.000Z"
            }
        ],
        "id": 1,
        "recurrencyKind": "Daily",
        "stackLevel": 1
    },
    "evseId": 0
}
with messageId: 5659bddd-959d-4c5c-9772-e86dae7e742b
2024-07-16 14:37:52.318355 [WARN] ocpp:OCPP201    module::OCPP201::ready()::<lambda()> :: Received a new Charging Schedules from the CSMS or another actor.
2024-07-16 14:37:52.318528 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 14:37:52.319332 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T00:00:00.000Z
2024-07-16 14:37:52.319439 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T14:37:52.318Z
2024-07-16 14:37:52.319580 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T00:00:00.000Z
2024-07-16 14:37:52.319777 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-18T00:00:00.000Z
2024-07-16 14:37:52.319970 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 20.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-18T00:00:00.000Z
2024-07-16 14:37:52.320061 [INFO] ocpp:OCPP201     :: period.has_value() limit = 13800
2024-07-16 14:37:52.320193 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 13800
2024-07-16 14:37:52.320363 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 14:37:52.320489 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T00:00:00.000Z
2024-07-16 14:37:52.320624 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T14:37:52.320Z
2024-07-16 14:37:52.320751 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T00:00:00.000Z
2024-07-16 14:37:52.320814 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-18T00:00:00.000Z
2024-07-16 14:37:52.320938 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 20.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-18T00:00:00.000Z
2024-07-16 14:37:52.321113 [INFO] ocpp:OCPP201     :: period.has_value() limit = 13800
2024-07-16 14:37:52.321212 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 13800
2024-07-16 14:37:52.333571 [WARN] evse_manager_1: virtual void module::evse::evse_managerImpl::handle_set_external_limits(types::energy::ExternalLimits&) :: In the EVSE manager, received external energy limit {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 13800.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T14:37:52.321Z"
        }
    ]
}
2024-07-16 14:37:52.334509 [WARN] evse_manager_1: bool module::EvseManager::updateLocalEnergyLimit(types::energy::ExternalLimits) :: External limits are lower, applying them {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 13800.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T14:37:52.321Z"
        }
    ]
}
2024-07-16 14:37:52.368285 [INFO] ocpp:OCPP201     :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-16 14:37:53.115735 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:37:54.252971 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:39:16.416786 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:39:17.550394 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:39:18.684171 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:39:19.853086 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 


2024-07-16 14:40:00.381452 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "2B978B6FEFEFE5B7"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 0, "EAmount": {"Value": 60, "Multiplier": 0, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}

2024-07-16 14:40:01.073155 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent ChargeParameterDiscoveryReq2024-07-16 14:40:01.073178 [INFO] iso15118_charge  :: Parameter-phase started

2024-07-16 14:40:01.073333 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state ChargeParameterDiscovery

2024-07-16 14:40:01.075056 [INFO] iso15118_charge  :: Selected energy transfer mode: AC_three_phase_core
2024-07-16 14:40:01.157703 [INFO] evse_manager_1:  ::                                     CAR ISO V2G ChargeParameterDiscoveryReq
2024-07-16 14:40:01.230939 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargeParameterDiscoveryRes
2024-07-16 14:40:01.248810 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 14:40:01.293935 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"2B978B6FEFEFE5B7"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":86400},"PMax":{"Multiplier":0,"Unit":"W","Value":13800}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":200}}}}}}
Multi schedule
{
    "id": 1,
    "chargingProfileKind": "Absolute",
    "chargingProfilePurpose": "TxDefaultProfile",
    "chargingSchedule": [
        {
            "id": 0,
            "chargingRateUnit": "A",
            "chargingSchedulePeriod": [
                {
                    "limit": 3.0,
                    "numberPhases": 3,
                    "startPeriod": 0
                }
            ],
            "duration": 3600,
            "minChargingRate": 0.0,
            "startSchedule": "2024-07-16T00:00:00.000Z"
        },
        {
            "id": 1,
            "chargingRateUnit": "A",
            "chargingSchedulePeriod": [
                {
                    "limit": 5.0,
                    "numberPhases": 3,
                    "startPeriod": 0
                }
            ],
            "duration": 3600,
            "minChargingRate": 0.0,
            "startSchedule": "2024-07-16T01:00:00.000Z"
        },
        {
            "id": 3,
            "chargingRateUnit": "A",
            "chargingSchedulePeriod": [
                {
                    "limit": 2.0,
                    "numberPhases": 3,
                    "startPeriod": 0
                }
            ],
            "duration": 3600,
            "minChargingRate": 0.0,
            "startSchedule": "2024-07-16T00:02:00.000Z"
        }
    ],
    "recurrencyKind": "Daily",
    "stackLevel": 1
}

Fails with

2024-07-16 15:11:25.227606 [WARN] ocpp:OCPP201    ocpp::DateTime ocpp::v201::SmartChargingHandler::get_next_temp_time(ocpp::DateTime, const std::vector<ocpp::v201::ChargingProfile>&, int32_t) :: Charging Profiles with more than one ChargingSchedule are not currently supported.

@shankari
Copy link
Collaborator Author

New multi-schedule with multiple periods in the day
2024-07-16 15:15:28.531018 [INFO] ocpp:OCPP201     :: Received SetChargingProfile: {
    "chargingProfile": {
        "chargingProfileKind": "Absolute",
        "chargingProfilePurpose": "TxDefaultProfile",
        "chargingSchedule": [
            {
                "chargingRateUnit": "A",
                "chargingSchedulePeriod": [
                    {
                        "limit": 3.0,
                        "numberPhases": 3,
                        "startPeriod": 0
                    },
                    {
                        "limit": 5.0,
                        "numberPhases": 3,
                        "startPeriod": 3600
                    },
                    {
                        "limit": 2.0,
                        "numberPhases": 3,
                        "startPeriod": 7200
                    }
                ],
                "duration": 86400,
                "id": 0,
                "minChargingRate": 0.0,
                "startSchedule": "2024-07-16T00:00:00.000Z"
            }
        ],
        "id": 1,
        "recurrencyKind": "Daily",
        "stackLevel": 1
    },
    "evseId": 0
}
with messageId: 8077d06f-1e92-4efd-870b-f218202f027e
2024-07-16 15:15:28.532022 [WARN] ocpp:OCPP201    module::OCPP201::ready()::<lambda()> :: Received a new Charging Schedules from the CSMS or another actor.
2024-07-16 15:15:28.532131 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 15:15:28.532215 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T00:00:00.000Z
2024-07-16 15:15:28.532313 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.532Z
2024-07-16 15:15:28.532505 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T00:00:00.000Z
2024-07-16 15:15:28.532597 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:15:28.532651 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.532Z
2024-07-16 15:15:28.532685 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:15:28.532717 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:15:28.532749 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.532Z
2024-07-16 15:15:28.532779 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:15:28.532809 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T00:00:00.000Z
2024-07-16 15:15:28.533136 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 2.0,
    "numberPhases": 3,
    "startPeriod": 7200
} end_time: 2024-07-17T00:00:00.000Z
2024-07-16 15:15:28.533251 [INFO] ocpp:OCPP201     :: period.has_value() limit = 1380
2024-07-16 15:15:28.533369 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 1380
2024-07-16 15:15:28.533584 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 15:15:28.533635 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T00:00:00.000Z
2024-07-16 15:15:28.533741 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.533Z
2024-07-16 15:15:28.533792 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T00:00:00.000Z
2024-07-16 15:15:28.533867 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:15:28.533945 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.533Z
2024-07-16 15:15:28.534005 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:15:28.534089 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:15:28.534194 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:15:28.533Z
2024-07-16 15:15:28.534295 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:15:28.534608 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T00:00:00.000Z
2024-07-16 15:15:28.534848 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 2.0,
    "numberPhases": 3,
    "startPeriod": 7200
} end_time: 2024-07-17T00:00:00.000Z
2024-07-16 15:15:28.534933 [INFO] ocpp:OCPP201     :: period.has_value() limit = 1380
2024-07-16 15:15:28.534985 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 1380
2024-07-16 15:15:28.538997 [WARN] evse_manager_1: virtual void module::evse::evse_managerImpl::handle_set_external_limits(types::energy::ExternalLimits&) :: In the EVSE manager, received external energy limit {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 1380.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:15:28.535Z"
        }
    ]
}
2024-07-16 15:15:28.539186 [WARN] evse_manager_1: bool module::EvseManager::updateLocalEnergyLimit(types::energy::ExternalLimits) :: External limits are lower, applying them {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 1380.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:15:28.535Z"
        }
    ]
}
2024-07-16 15:15:28.578860 [INFO] ocpp:OCPP201     :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-16 15:15:28.597725 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 15:15:29.649187 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 0A 0W 
2024-07-16 15:15:30.746741 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 0A 0W 
2024-07-16 15:15:31.866096 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 0A 0W 

But now the limits are set to 0A. Why? It looks like it finds the correct period. I bet it is because the current is below the min (should add logs to verify). But for now, we can just bump up the amps....

@shankari
Copy link
Collaborator Author

shankari commented Jul 16, 2024

Bumping up the amps by x 10, we get the correct limits, but the last period is the one that is valid.
2024-07-16 15:21:51.526192 [INFO] ocpp:OCPP201     :: period.has_value() limit = 13800
2024-07-16 15:21:51.526250 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 13800
2024-07-16 15:21:51.526477 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 15:21:51.526591 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T00:00:00.000Z
2024-07-16 15:21:51.527036 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:21:51.526Z
2024-07-16 15:21:51.527216 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T00:00:00.000Z
2024-07-16 15:21:51.527319 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:21:51.527469 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:21:51.526Z
2024-07-16 15:21:51.527539 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T01:00:00.000Z
2024-07-16 15:21:51.527598 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:21:51.527666 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:21:51.526Z
2024-07-16 15:21:51.527724 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T02:00:00.000Z
2024-07-16 15:21:51.527968 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T00:00:00.000Z
2024-07-16 15:21:51.528132 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 20.0,
    "numberPhases": 3,
    "startPeriod": 7200
} end_time: 2024-07-17T00:00:00.000Z
2024-07-16 15:21:51.528224 [INFO] ocpp:OCPP201     :: period.has_value() limit = 13800
2024-07-16 15:21:51.528338 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 13800
2024-07-16 15:21:51.571891 [WARN] evse_manager_1: virtual void module::evse::evse_managerImpl::handle_set_external_limits(types::energy::ExternalLimits&) :: In the EVSE manager, received external energy limit {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 13800.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:21:51.528Z"
        }
    ]
}
2024-07-16 15:21:51.572105 [WARN] evse_manager_1: bool module::EvseManager::updateLocalEnergyLimit(types::energy::ExternalLimits) :: External limits are lower, applying them {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 13800.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:21:51.528Z"
        }
    ]
}
2024-07-16 15:21:51.575528 [INFO] ocpp:OCPP201     :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-16 15:21:51.702667 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 0A 0W 
2024-07-16 15:21:52.798328 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:53.895156 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:54.989252 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:56.125233 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:57.224404 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:58.360300 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:21:59.418406 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:00.591170 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:01.687073 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:02.780232 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:03.833069 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:04.968330 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:06.106089 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:07.162219 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:08.219222 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:09.352950 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:10.446061 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:11.608998 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:12.702205 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:13.757494 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:14.811088 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:15.905048 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:16.999038 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:18.093100 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:19.188310 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:20.282066 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:21.376391 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:22.470083 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:23.566002 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:24.675210 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:25.730184 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:26.828686 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
2024-07-16 15:22:27.967246 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 20A 13800W 
Let's adjust the start time so that we can have multiple future schedules
2024-07-16 15:25:43.591721 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 15:25:43.591783 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T15:00:00.000Z
2024-07-16 15:25:43.592335 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:25:43.591Z
2024-07-16 15:25:43.592509 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T15:00:00.000Z
2024-07-16 15:25:43.592693 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T16:00:00.000Z
2024-07-16 15:25:43.592939 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 10.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-16T16:00:00.000Z
2024-07-16 15:25:43.593056 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-16 15:25:43.593236 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900
2024-07-16 15:25:43.593441 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 15:25:43.593561 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T15:00:00.000Z
2024-07-16 15:25:43.593712 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T15:25:43.593Z
2024-07-16 15:25:43.593909 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T15:00:00.000Z
2024-07-16 15:25:43.594291 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T16:00:00.000Z
2024-07-16 15:25:43.594567 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 10.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-16T16:00:00.000Z
2024-07-16 15:25:43.594667 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-16 15:25:43.594751 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900
2024-07-16 15:25:43.597813 [WARN] evse_manager_1: virtual void module::evse::evse_managerImpl::handle_set_external_limits(types::energy::ExternalLimits&) :: In the EVSE manager, received external energy limit {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 6900.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:25:43.594Z"
        }
    ]
}
2024-07-16 15:25:43.598107 [WARN] evse_manager_1: bool module::EvseManager::updateLocalEnergyLimit(types::energy::ExternalLimits) :: External limits are lower, applying them {
    "schedule_import": [
        {
            "limits_to_leaves": {
                "total_power_W": 6900.0
            },
            "limits_to_root": {},
            "timestamp": "2024-07-16T15:25:43.594Z"
        }
    ]
}
2024-07-16 15:25:43.638801 [INFO] ocpp:OCPP201     :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-16 15:25:43.696389 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 15:25:44.802562 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 10A 6900W 
2024-07-16 15:25:45.948495 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 10A 6900W 
2024-07-16 15:25:47.085433 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 10A 6900W 
2024-07-16 15:25:48.223086 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 10A 6900W 
Now to plug in the car again
2024-07-16 15:27:06.990023 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "42A1CFBD7F36EF7D"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 0, "EAmount": {"Value": 60, "Multiplier": 0, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}

2024-07-16 15:27:07.580390 [INFO] iso15118_charge  :: Parameter-phase started2024-07-16 15:27:07.580374 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent ChargeParameterDiscoveryReq

2024-07-16 15:27:07.580664 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state ChargeParameterDiscovery

2024-07-16 15:27:07.582664 [INFO] iso15118_charge  :: Selected energy transfer mode: AC_three_phase_core
2024-07-16 15:27:07.624863 [INFO] evse_manager_1:  ::                                     CAR ISO V2G ChargeParameterDiscoveryReq
2024-07-16 15:27:07.626222 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 10A 6900W 
2024-07-16 15:27:07.717601 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargeParameterDiscoveryRes
2024-07-16 15:27:08.142249 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"42A1CFBD7F36EF7D"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":86400},"PMax":{"Multiplier":0,"Unit":"W","Value":6900}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":100}}}}}}

Again, we get a single SA schedule with 6900W for one day (86400 duration).
But we are only requesting 60 Wh. Let's bump that up to 60 kWh and see what happens.

@the-bay-kay
Copy link

Keeping a tally of the locations I'll need to add DepartureTime. First, just consolidating the iso requirements for my ease of reading...

15118-2 `DepartureTime` requirements

Figure 5 on page 15 gives a helpful seq. diagram for the ChargeParameterDiscoveryReq(), the message carrying the ChargeParameterType (DepartureTime) payload.

Where implementation is needed:

  • EVCC Resumes previous paused V2G Communication [V2G2-742]

Constraints:

  • If no DepartureTime, the extension should not be included [V2G2-215] (Presumably, this is what we're already doing)
  • Sum of individual intervals in PMaxSchedule & SalesTariff in ChargeParamDiscoveryRes shall match the period indicated in DepartureTime ChargeParameterDisoveryReq [V2G2-303]
  • If no DepartureTime, sum of PMaxSchedule intervals & SalesTariff shall be >= 24 hours [V2G-304] (Likewise, assuming this is the current behavior. Will check later.)
  • If the number of SalesTariffEntry elements or PMaxSchedule elements does not cover the entire period of time until Departuretime, the Target Setting EAmmount has not been met and communication has not been finished. It is the responsibility of the EVCC to request a new SAScheduleList via another ChargeParameterDiscoveryReq type as soon as the last SalesTariffEntry / PMaxSchedule entry becomes active[V2G-305]
  • If #(SalesTariffEntry) is not covering until DepartureTime, it is responsibility of EVCC to optimize the schedule

With the info above, it seems we need to send & handle the DepartureTime whenever a ChargeParameterDiscoverReq is being sent. As I understand it, this will occur (i) when a new session has been started, and (ii) when a session has been resumed after a pause.

Now to hunt down these occurrences in PyEVJosev and JsEvManager. At a glance, the JsEvManager changes seem like they will be somewhat straightforward...

@shankari
Copy link
Collaborator Author

shankari commented Jul 16, 2024

Changing the defaults in build/dist/libexec/everest/3rd_party/josev/iso15118/secc/states/iso15118_2_states.py to bump up the power and set the departure time to see if it makes a difference...

            p_e_amount: float = e_amount.value * pow(10, e_amount.multiplier + 3)

        departure_time = (                                    
            ev_data_context.departure_time if ev_data_context.departure_time else 21600
        )                                                  
Pnc is now stuck in Authorization Req/Res
2024-07-16 16:03:05.849775 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=http://www.w3.org/2000/09/xmldsig#): {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "tQU4I0aGz6D6qZtjjNpeLmZV70/6/jWN+Ew7B9cTVq8=", "URI": "#id1"}]}}
2024-07-16 16:03:06.381961 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB", "Signature": {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "tQU4I0aGz6D6qZtjjNpeLmZV70/6/jWN+Ew7B9cTVq8=", "URI": "#id1"}]}, "SignatureValue": {"value": "NmKlHwYsVCQuXgV0tDIzZbNLuDFIMIKMKH1u9Ir3/rR42dqVSB5TXeQHuX97qQOB+MHRPFgTx/bUAPk4Q0xlgw=="}}}, "Body": {"AuthorizationReq": {"Id": "id1", "GenChallenge": "ajHCFwWA+Q8gyoax/ZYwpw=="}}}}
2024-07-16 16:03:06.502111 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:07.678986 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:07.763007 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:07.763968 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization

2024-07-16 16:03:07.864598 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: Response message (type 6) not configured within 98 ms (took 102 ms)
2024-07-16 16:03:07.869701 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:07.873175 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:08.657887 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:08.660089 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:08.665176 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:08.840837 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:09.604521 [WARN] ocpp:OCPP201    void ocpp::MessageQueue<M>::handle_timeout_or_callerror(const std::optional<ocpp::EnhancedMessage<M> >&) [with M = ocpp::v201::MessageType] :: Message timeout for: TransactionEvent (eeee3f10-332c-49f8-ae6d-d3e8fc46fb87)
2024-07-16 16:03:09.604837 [WARN] ocpp:OCPP201    void ocpp::MessageQueue<M>::handle_timeout_or_callerror(const std::optional<ocpp::EnhancedMessage<M> >&) [with M = ocpp::v201::MessageType] :: Message is transaction related and will therefore be sent again
2024-07-16 16:03:09.611485 [WARN] ocpp:OCPP201    void ocpp::MessageQueue<M>::handle_timeout_or_callerror(const std::optional<ocpp::EnhancedMessage<M> >&) [with M = ocpp::v201::MessageType] :: Attempt: 2/5 will be sent at 2024-07-16T15:46:02.225Z
2024-07-16 16:03:09.861305 [INFO] ocpp:OCPP201     :: Unsolicited client close reason: read limited at 32769 bytes close code: 1009
2024-07-16 16:03:09.861784 [ERRO] ocpp:OCPP201    void ocpp::WebsocketTlsTPM::on_conn_fail() :: OCPP client connection to server failed
2024-07-16 16:03:09.862404 [INFO] ocpp:OCPP201     :: Reconnecting in: 3000ms, attempt: 1
2024-07-16 16:03:10.007064 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:10.238957 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:10.242011 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:10.249295 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:10.379931 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:11.139473 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:11.143823 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:11.145803 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:11.205276 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:12.418666 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:12.689119 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:12.690228 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:12.695324 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:12.826622 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:12.863556 [INFO] ocpp:OCPP201     :: Connecting to uri: wss://host.docker.internal/ws/cp001 with security-profile 3
2024-07-16 16:03:12.914853 [INFO] evse_security:E  :: Requesting leaf certificate info: CSMS
2024-07-16 16:03:12.924662 [INFO] evse_security:E  :: Found valid leaf: ["/ext/source/build/dist/etc/everest/certs/client/csms/CSMS_LEAF.pem"]
2024-07-16 16:03:12.932135 [WARN] evse_security:E evse_security::GetCertificateInfoResult evse_security::EvseSecurity::get_leaf_certificate_info_internal(evse_security::LeafCertificateType, evse_security::EncodingFormat, bool) :: CSMS leaf requires full bundle, but full bundle not found at path: "/ext/source/build/dist/etc/everest/certs/client/csms"
2024-07-16 16:03:12.991871 [INFO] evse_security:E  :: Building new certificate hierarchy!
2024-07-16 16:03:13.066321 [INFO] evse_security:E  :: Requesting certificate file: [CSMS] file:"/ext/source/build/dist/etc/everest/certs/ca/v2g/V2G_ROOT_CA.pem"
2024-07-16 16:03:13.103639 [INFO] ocpp:OCPP201     :: Loading CA csms bundle to verify server certificate: /ext/source/build/dist/etc/everest/certs/ca/v2g/V2G_ROOT_CA.pem
2024-07-16 16:03:13.408975 [INFO] ocpp:OCPP201     :: LWS connect with info port: [443] address: [host.docker.internal] path: [/ws/cp001] protocol: [ocpp2.0.1]
2024-07-16 16:03:13.518293 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:13.588124 [INFO] ocpp:OCPP201     :: OCPP client successfully connected to server
2024-07-16 16:03:13.589208 [WARN] ocpp:OCPP201    int ocpp::callback_minimal(lws*, lws_callback_reasons, void*, void*, size_t) :: callback_minimal called, but data->owner is nullptr. Reason: 80
2024-07-16 16:03:13.593802 [WARN] ocpp:OCPP201    int ocpp::callback_minimal(lws*, lws_callback_reasons, void*, void*, size_t) :: callback_minimal called, but data->owner is nullptr. Reason: 75
2024-07-16 16:03:13.595700 [WARN] ocpp:OCPP201    int ocpp::callback_minimal(lws*, lws_callback_reasons, void*, void*, size_t) :: callback_minimal called, but data->owner is nullptr. Reason: 30
2024-07-16 16:03:13.835819 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:13.837436 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:13.839237 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:14.749933 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:15.557712 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:15.558783 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:15.583010 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:15.669615 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:15.873702 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:16.496160 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:16.510183 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:16.514556 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:17.134916 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:17.416761 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:17.419487 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:17.434044 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:17.519517 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:18.054654 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:18.056217 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:18.059287 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:18.233329 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:19.025228 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:19.026175 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:19.032420 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:19.134195 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:19.440722 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:19.447558 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:19.450531 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:19.506529 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:20.446637 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:20.448412 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 16:03:20.454068 [INFO] evse_manager_1:  ::                                     CAR ISO V2G AuthorizationReq
2024-07-16 16:03:20.551506 [INFO] evse_manager_1:  :: EVSE ISO V2G AuthorizationRes
2024-07-16 16:03:20.726106 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:20.858116 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"1BFEFA7BFFFFF7BB"},"Body":{"AuthorizationRes":{"ResponseCode":"OK","EVSEProcessing":"Ongoing"}}}}
2024-07-16 16:03:20.859713 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: AuthorizationRes received
2024-07-16 16:03:20.864215 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "1BFEFA7BFFFFF7BB"}, "Body": {"AuthorizationReq": {}}}}
2024-07-16 16:03:21.820007 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:03:21.839351 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 16:03:21.840325 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
...
2024-07-16 16:08:04.416407 [ERRO] auth:Auth       Everest::json Everest::Everest::call_cmd(const Requirement&, const std::string&, Everest::json) :: Timeout while waiting for result of ocpp:OCPP201->auth_validator:auth_token_validator->validate_token()
terminate called after throwing an instance of 'boost::wrapexcept<Everest::EverestTimeoutError>'
  what():  Timeout while waiting for result of ocpp:OCPP201->auth_validator:auth_token_validator->validate_token()
2024-07-16 16:08:05.366852 [WARN] energy_manager: void module::EnergyManager::enforce_limits(const std::vector<types::energy::EnforcedLimits>&) :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 16:08:05.732677 [CRIT] manager         int boot(const boost::program_options::variables_map&) :: Module auth (pid: 6258) exited with status: 6. Terminating all modules.
2024-07-16 16:08:05.768883 [INFO] manager          :: SIGTERM of child: api (pid: 6257) succeeded.
2024-07-16 16:08:05.774743 [INFO] manager          :: SIGTERM of child: car_simulator_1 (pid: 6259) succeeded.
2024-07-16 16:08:05.784776 [INFO] manager          :: SIGTERM of child: energy_manager (pid: 6260) succeeded.
2024-07-16 16:08:05.840433 [INFO] manager          :: SIGTERM of child: evse_manager_1 (pid: 6261) succeeded.
2024-07-16 16:08:05.840984 [INFO] manager          :: SIGTERM of child: evse_security (pid: 6267) succeeded.
2024-07-16 16:08:05.841217 [INFO] manager          :: SIGTERM of child: grid_connection_point (pid: 6269) succeeded.
2024-07-16 16:08:05.841350 [INFO] manager          :: SIGTERM of child: iso15118_car (pid: 6270) succeeded.
2024-07-16 16:08:05.860398 [INFO] manager          :: SIGTERM of child: iso15118_charger (pid: 6271) succeeded.
2024-07-16 16:08:05.886850 [INFO] manager          :: SIGTERM of child: ocpp (pid: 6272) succeeded.
2024-07-16 16:08:05.899151 [INFO] manager          :: SIGTERM of child: slac (pid: 6273) succeeded.
2024-07-16 16:08:05.900147 [INFO] manager          :: SIGTERM of child: system (pid: 6274) succeeded.
2024-07-16 16:08:05.922880 [INFO] manager          :: SIGTERM of child: token_provider_1 (pid: 6280) succeeded.
2024-07-16 16:08:05.923692 [INFO] manager          :: SIGTERM of child: yeti_driver_1 (pid: 6282) succeeded.
2024-07-16 16:08:05.924463 [CRIT] manager         int boot(const boost::program_options::variables_map&) :: Exiting manager.
/ext/source/build # 

Even after reverting changes.

Restarting even further after saving a patch with the logs

@the-bay-kay
Copy link

the-bay-kay commented Jul 16, 2024

Starting with JsEvManager/index.js some observations:

  • When incorporating, it seems that the we can ignore the following states within the car_statemachine:
    • "pluggedin", set by the "pause" command (read: plugged in but not charging)
    • "diode_fail"
    • "error_e"
    • "unplugged"
  • When looking at the remaining states, it seems they call mod.uses.ev_board_support.call.set_cp_state({ cp_state: x}), where x is either CorB`. I'm not sure this is the right lead, but I believe following calls like this may help figure out where we need to incorperate departureTime.

From what I can gather, the mutation of variables like mod.maxCurrent is handled by external packages -- as such, I don't believe we need to make any other changes to this file beyond setting the default of mod.iso_departure_time = null...

@shankari
Copy link
Collaborator Author

Restarted everything. It works again.

For the record, and to help in debugging again, here's what a successful auth *should* look like
2024-07-16 17:12:49.700348 [INFO] evse_security:E  :: Verifying leaf certificate: MO
2024-07-16 17:12:49.700850 [INFO] evse_security:E  :: Building new certificate hierarchy!
2024-07-16 17:12:49.702983 [INFO] evse_security:E  :: Building new certificate hierarchy!
2024-07-16 17:12:49.708433 [INFO] ocpp:OCPP201     :: Local contract validation result: Valid
2024-07-16 17:12:49.719646 [INFO] ocpp:OCPP201     :: Online: Pass generated OCSP data to CSMS

2024-07-16 17:12:49.839650 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"AuthorizationReq": {"Id": "id1", "GenChallenge": "AW5ao2VeCrL6l0hePq/8Zg=="}}
2024-07-16 17:12:49.899228 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=http://www.w3.org/2000/09/xmldsig#): {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "9yFpODfSMBDrbQA2T6oQsKv5JFBYvI6b4QbwozA27rw=", "URI": "#id1"}]}}
2024-07-16 17:12:49.951302 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "77EA5F7FD63DFEEF", "Signature": {"SignedInfo": {"CanonicalizationMethod": {"Algorithm": "http://www.w3.org/TR/canonical-exi/"}, "SignatureMethod": {"Algorithm": "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}, "Reference": [{"Transforms": {"Transform": [{"Algorithm": "http://www.w3.org/TR/canonical-exi/"}]}, "DigestMethod": {"Algorithm": "http://www.w3.org/2001/04/xmlenc#sha256"}, "DigestValue": "9yFpODfSMBDrbQA2T6oQsKv5JFBYvI6b4QbwozA27rw=", "URI": "#id1"}]}, "SignatureValue": {"value": "zrDorSH8GT7q2GQjmvXMzrbu29oYeWB8RzLaDkCRYhfFHD+72BCl/COw3O8Gq4VkIgLK7oCJyFKPVCG2VZjGLA=="}}}, "Body": {"AuthorizationReq": {"Id": "id1", "GenChallenge": "AW5ao2VeCrL6l0hePq/8Zg=="}}}}

2024-07-16 17:12:50.527150 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent AuthorizationReq
2024-07-16 17:12:50.527474 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Entered state Authorization
2024-07-16 17:12:50.534481 [INFO] ocpp:OCPP201     :: CSMS idToken status: Accepted
2024-07-16 17:12:50.534584 [INFO] ocpp:OCPP201     :: CSMS certificate status: Accepted
2024-07-16 17:12:50.534605 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_message(const ocpp::EnhancedMessage<ocpp::v201::MessageType>&) :: Handle_message called: [3,"daafe391-ffef-4980-ad32-84e73d097da3",{"certificateStatus":"Accepted","idTokenInfo":{"status":"Accepted"}}]
2024-07-16 17:12:50.534751 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_message(const ocpp::EnhancedMessage<ocpp::v201::MessageType>&) :: json_message called: [3,"daafe391-ffef-4980-ad32-84e73d097da3",{"certificateStatus":"Accepted","idTokenInfo":{"status":"Accepted"}}]
2024-07-16 17:12:50.536751 [INFO] auth:Auth        :: Providing authorization to connector#1
2024-07-16 10:12:00 time=2024-07-16T17:12:00.548Z level=INFO msg="POST /api/v0/cs/cp001/setchargingprofile" remote_addr=192.168.65.1:48446 status=201 bytes=0 duration=2.257924ms
2024-07-16 10:12:00 time=2024-07-16T17:12:00.598Z level=ERROR msg="unable to route message" chargeStationId=cp001 action=SetChargingProfile err="routing request: NotImplemented: SetChargingProfile result not implemented"
2024-07-16 10:12:00 time=2024-07-16T17:12:00.598Z level=ERROR msg="cs/in/ocpp2.0.1/# receive" duration=103.775µs messaging.system=mqtt messaging.consumer.id=manager-GFDaQ messaging.message.payload_size_bytes=588 messaging.operation=receive csId=cp001 ocpp.version=2.0.1 call_result.action=SetChargingProfile messaging.message.conversation_id=edf9ca5f-5875-4bb4-aab7-a556f28f1e60
2024-07-16 10:12:00 time=2024-07-16T17:12:00.598Z level=ERROR msg=exception exception.type=*fmt.wrapError exception.message="routing request: NotImplemented: SetChargingProfile result not implemented"
2024-07-16 10:12:05 time=2024-07-16T17:12:00.547Z level=INFO msg="cs/out/ocpp2.0.1/# publish" duration=1.475038ms messaging.system=mqtt messaging.message.payload_size_bytes=555 messaging.operation=publish messaging.message.conversation_id=edf9ca5f-5875-4bb4-aab7-a556f28f1e60 csId=cp001 call.action=SetChargingProfile
2024-07-16 10:12:25 time=2024-07-16T17:12:25.782Z level=INFO msg="checking for pending charge station certificates changes"
2024-07-16 10:12:25 time=2024-07-16T17:12:25.784Z level=INFO msg="checking for pending charge station settings changes"
2024-07-16 10:12:25 time=2024-07-16T17:12:25.780Z level=INFO msg="sync triggers" duration=4.453844ms sync.trigger.previous="" sync.trigger.count=0
2024-07-16 10:12:45 time=2024-07-16T17:12:42.785Z level=INFO msg="cs/in/ocpp2.0.1/# receive" duration=349.616µs messaging.system=mqtt messaging.consumer.id=manager-GFDaQ messaging.message.payload_size_bytes=191 messaging.operation=receive csId=cp001 ocpp.version=2.0.1 call.action=StatusNotification messaging.message.conversation_id=03fb6a01-6ad1-4677-9c32-c25853c0c574 status.evse_id=1 status.connector_id=1 status.connector_status=Occupied
2024-07-16 10:12:45 time=2024-07-16T17:12:42.785Z level=INFO msg="cs/out/ocpp2.0.1/# publish" duration=72.589µs messaging.system=mqtt messaging.message.payload_size_bytes=98 messaging.operation=publish messaging.message.conversation_id=03fb6a01-6ad1-4677-9c32-c25853c0c574 csId=cp001 call_result.action=StatusNotification
2024-07-16 10:12:50 time=2024-07-16T17:12:50.532Z level=WARN msg="ocsp check" attempt=1 maxAttempts=1 error="parsing ocsp response: asn1: structure error: tags don't match (16 vs {class:0 tag:28 length:33 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} responseASN1 @2"
2024-07-16 10:12:50 time=2024-07-16T17:12:50.611Z level=INFO msg="transaction event" chargeStationId=cp001 transactionId=12ab48fc-820a-4243-8332-e34f2cd52cbe eventType=Started triggerReason=Authorized seqNo=0
2024-07-16 10:12:50 time=2024-07-16T17:12:49.721Z level=INFO msg="cs/in/ocpp2.0.1/# receive" duration=811.00724ms messaging.system=mqtt messaging.consumer.id=manager-GFDaQ messaging.message.payload_size_bytes=948 messaging.operation=receive csId=cp001 ocpp.version=2.0.1 call.action=Authorize messaging.message.conversation_id=daafe391-ffef-4980-ad32-84e73d097da3 authorize.certificate=hash token_auth.id=UKSWI123456789G token_auth.type=eMAID token_auth.status=Accepted authorize.cert_warn="No OCSP, but ignoring for testing purpose." request.status=Accepted
2024-07-16 10:12:50 time=2024-07-16T17:12:49.725Z level=INFO msg="HTTP POST" duration=807.121357ms http.method=POST http.url=https://www.example.com/ net.peer.name=www.example.com http.request_content_length=97 http.status_code=200 http.response_content_length=1256
2024-07-16 10:12:50 time=2024-07-16T17:12:50.532Z level=INFO msg="cs/out/ocpp2.0.1/# publish" duration=88.681µs messaging.system=mqtt messaging.message.payload_size_bytes=155 messaging.operation=publish messaging.message.conversation_id=daafe391-ffef-4980-ad32-84e73d097da3 csId=cp001 call_result.action=Authorize
2024-07-16 10:12:50 time=2024-07-16T17:12:50.610Z level=INFO msg="cs/in/ocpp2.0.1/# receive" duration=11.894652ms messaging.system=mqtt messaging.consumer.id=manager-GFDaQ messaging.message.payload_size_bytes=1605 messaging.operation=receive csId=cp001 ocpp.version=2.0.1 call.action=TransactionEvent messaging.message.conversation_id=193336cd-a66f-437d-92d6-0062a8734ada token_auth.id=UKSWI123456789G token_auth.type=eMAID token_auth.status=Accepted
2024-07-16 10:12:50 time=2024-07-16T17:12:50.622Z level=INFO msg="cs/out/ocpp2.0.1/# publish" duration=73.971µs messaging.system=mqtt messaging.message.payload_size_bytes=131 messaging.operation=publish messaging.message.conversation_id=193336cd-a66f-437d-92d6-0062a8734ada csId=cp001 call_result.action=TransactionEvent
2024-07-16 10:12:52 time=2024-07-16T17:12:52.744Z level=INFO msg="transaction event" chargeStationId=cp001 transactionId=12ab48fc-820a-4243-8332-e34f2cd52cbe eventType=Updated triggerReason=ChargingStateChanged seqNo=1
2024-07-16 10:12:55 time=2024-07-16T17:12:52.743Z level=INFO msg="cs/in/ocpp2.0.1/# receive" duration=9.621107ms messaging.system=mqtt messaging.consumer.id=manager-GFDaQ messaging.message.payload_size_bytes=322 messaging.operation=receive csId=cp001 ocpp.version=2.0.1 call.action=TransactionEvent messaging.message.conversation_id=615822f6-7887-4301-a381-a289e102517a
2024-07-16 10:12:55 time=2024-07-16T17:12:52.752Z level=INFO msg="cs/out/ocpp2.0.1/# publish" duration=122.01µs messaging.system=mqtt messaging.message.payload_size_bytes=96 messaging.operation=publish messaging.message.conversation_id=615822f6-7887-4301-a381-a289e102517a csId=cp001 call_result.action=TransactionEvent
Making the pyjosev changes without adding any other logs
2024-07-16 17:48:36.189938 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "DE20EB55FEFCBC67"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 0, "EAmount": {"Value": 60, "Multiplier": 0, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}

@shankari
Copy link
Collaborator Author

I note that the construction of the charge parameter discovery request/response also has some SA schedule creation

        sa_schedule_list = await self.comm_session.evse_controller.get_sa_schedule_list(                
            ev_data_context,                                                                            
            self.comm_session.config.free_charging_service,                                             
            max_schedule_entries,                                                                       
            departure_time,                                                                             
        )                                                                                       

But the current message doesn't seem to use that so we will ignore for simplicity

@the-bay-kay
Copy link

the-bay-kay commented Jul 16, 2024

Taking some time to set up the Node-RED UI, I think that's the best place to start (knowing what signals we can / will send will help define the message behavior, and so on as the call graph grows). Some initial notes on the UI nodes available:

UI Node Choices
  • We can't use the date node, as it only gives us per-day granularity
  • departureTime is defined as a 32-bit unsigned integer, that represents an offset in seconds from the point of time the message is sent. As much as I'd like to have a fancy UI (pick the time, and it handles it for you), let's hack together a solution that uses that input.
    • The text node does have a time picker option. In the interest of time, I won't be using this: just wanted to note that this is an avenue for improvement!
  • The integer node is not a viable option, for two reasons:
    • We cannot set the max of 32u
    • Even if we could, it would be so slow to use the click widget to implement charging 1 second at a time.
  • For these reasons, I think the best course of action is to add a text node, and then interpret the text into an integer.
Here is where we run into our first design quirk. Per [V2H2-215]... > If there is no DepartureTime information available, the EVCC shall not include this message in the ChargeParameterDiscoveryReq message

This means we cannot simply have 0 be our base case for the input component (or use some value like -1 as the "null" - this value must be unsigned).

  • My first thought was to add a toggle node: something like "enable DepartureTime". Stepping back, I think this is needlessly complicated, and shouldn't be necessary for the reason below.
  • When initialized, the text node does not contain any text. As such, I think we can pass this null value along, and that absence can be used later when we form the ChargeParameterDiscoveryReq.

Without piping through any of the messages, below is a mock up of the module

UI Screenshots

image
image
(I believe we won't need a default injection, we actually want the value to be null)
EDIT: I think we actually need to hook up the departure time to the BufferSimCommands...

When sketching up these values, I'm left one concern. As sketched up, the proposed "setDepartureTime" command will send every time the number is set. How can we make sure that we only change the DepartureTime value when starting or resuming a charging session? Will have to spend more time with JsEVManager to figure out how this will look in practice.

@the-bay-kay
Copy link

Still getting used to the Node-RED workflow, setting up the message flow -- writing these notes down mostly for my own understanding...


As I understand it, the Buffer sim commands function node takes the inputs from each of the input nodes, and adjusts the payload according to the topic.

Screenshot of nodes, example code

image

if (msg.topic.indexOf('sim_commands') > -1) {
    const s = msg.payload.split('#');
    flow.set('sim_commands_start', s[0]);
// the code continues...

After some searching, it seems the sim_commands topic is defined within the injection of the CarSimulation node, but I cannot find the flows for sim_commands_pause, etc... Am I misunderstanding how the flow get command works? Where are these being defined?

This leads me to the question: do I even need to filter through the buffer?? For example, the values set by the MaxCurrentSlider aren't being filtered. I'm going to just assume we don't have to filter it for now, I think that should be OK...

@shankari
Copy link
Collaborator Author

Aha! It looks like the pyjosev library is in two locations

# find / -name states.py
/ext/cache/cpm/josev/dd7dc8e95662d54aca01374e5283ead8d4793261/Josev/iso15118/shared/states.py
/ext/source/build/dist/libexec/everest/3rd_party/josev/iso15118/shared/states.py

I have been editing the one in build/dist, but it may be that the code is getting pulled from the cache. Not sure how the original patch ever worked; maybe some parts are pulled from each location?!

Trying to modify an existing log to see which one is loaded (modifying the one in states.py)

2024-07-16 19:24:00.442684 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state ServiceDiscovery
2024-07-16 19:24:01.223707 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state PaymentServiceSelection
2024-07-16 19:24:01.952899 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state PaymentDetails
2024-07-16 19:24:02.769054 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state Authorization
2024-07-16 19:24:03.475439 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state ChargeParameterDiscovery

Let's make sure that the loggers are set up in the same way...

@shankari
Copy link
Collaborator Author

shankari commented Jul 16, 2024

I might have made changes in the SECC implementation of pyjosev, which is unused in EVerest.
The actual values are here:
https://github.com/EVerest/ext-switchev-iso15118/blob/7f16c4b2c1307ce73798215f34b8fe06862bbae1/iso15118/evcc/controller/simulator.py#L276C15-L276C35

            e_amount = PVEAmount(multiplier=3, value=60,        
                                 unit=UnitSymbol.WATT_HOURS)    

            ac_charge_params = ACEVChargeParameter(
                departure_time=21600,         
                e_amount=e_amount,            
                ev_max_voltage=ev_max_voltage,
                ev_max_current=ev_max_current,    
                ev_min_current=ev_min_current,                      
            )                                                                       

Bingo!

2024-07-16 19:33:51.232377 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "BDF67F7EFD4FCEDD"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 21600, "EAmount": {"Value": 60, "Multiplier": 3, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}

2024-07-16 19:33:51.944143 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"BDF67F7EFD4FCEDD"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":86400},"PMax":{"Multiplier":0,"Unit":"W","Value":22080}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":320}}}}}}

Now, we set our charging profile

2024-07-16 19:37:02.768247 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-16 19:37:02.768315 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900
2024-07-16 19:37:02.768429 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 19:37:02.768507 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-16T19:00:00.000Z
2024-07-16 19:37:02.768611 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T19:37:02.768Z
2024-07-16 19:37:02.768690 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-16T19:00:00.000Z
2024-07-16 19:37:02.768808 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-16T20:00:00.000Z
2024-07-16 19:37:02.769048 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 10.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-16T20:00:00.000Z
2024-07-16 19:37:02.769080 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-16 19:37:02.769131 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900

And now we plug in the car, and we send the correct request, but the response still has only one SASchedule, which is 6900W for the entire day ("duration":86400).

2024-07-16 19:38:02.521698 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Message to encode (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message": {"Header": {"SessionID": "BFF27B0FED3BDBFE"}, "Body": {"ChargeParameterDiscoveryReq": {"RequestedEnergyTransferMode": "AC_three_phase_core", "AC_EVChargeParameter": {"DepartureTime": 21600, "EAmount": {"Value": 60, "Multiplier": 3, "Unit": "Wh"}, "EVMaxVoltage": {"Value": 400, "Multiplier": 0, "Unit": "V"}, "EVMaxCurrent": {"Value": 32000, "Multiplier": -3, "Unit": "A"}, "EVMinCurrent": {"Value": 10, "Multiplier": 0, "Unit": "A"}}}}}}

2024-07-16 19:38:03.085580 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Sent ChargeParameterDiscoveryReq
2024-07-16 19:38:03.085726 [INFO] iso15118_charge  :: Parameter-phase started
2024-07-16 19:38:03.086015 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: IN BUILD_DIST: Entered state ChargeParameterDiscovery

2024-07-16 19:38:03.088033 [INFO] iso15118_charge  :: Selected energy transfer mode: AC_three_phase_core
2024-07-16 19:38:03.129469 [INFO] evse_manager_1:  ::                                     CAR ISO V2G ChargeParameterDiscoveryReq
2024-07-16 19:38:03.185479 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargeParameterDiscoveryRes
2024-07-16 19:38:03.240756 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"BFF27B0FED3BDBFE"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":86400},"PMax":{"Multiplier":0,"Unit":"W","Value":6900}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":100}}}}}}

@shankari
Copy link
Collaborator Author

So it is fairly clear that the current ISO 15118-2 implementation does not work the way we had hoped in
#64 (comment)

Concretely, the EVSE does not send a list of SASchedules; it only sends a single SASchedule that corresponds to the current limits. When the EVSE sent the ChargeParameterDiscoveryRes, it basically said that you can get 6900 W for the rest of the day. This is technically correct because we started with the lowest current, but I don't think it will give us the energy we requested.

To run some numbers:

  • we requested 60x10^3 Wh = 60,000 Wh with a departure time of 21600 (6 hours)
  • the max current was limited to 10A, 3 phase. So the max power is 240 * 10 = 2400 W. For some reason, the max power is actually set to 6900W (not sure why, need to investigate)
  • and then the SASchedule is returned in watts 6,900W for the entire day.
    • That gives us 165,600 Wh, but doesn't let us leave after 6 hours
    • if we do try to leave after 6 hours, we will end up with only 41,400 Wh which is less than what we requested

So basically, departure time does not work, and we only send a single SA Schedule as I had speculated from the code earlier. Not sure if it is super easy to fix this, but I have the afternoon to try!

@the-bay-kay
Copy link

Parsing the syntax & design behind the MQTT routes... My current understanding is that the DepartureTime should be send via the /carsim/cmd/{} route, as the DepartureTime is set by the EVCC (read: vehicle).
When looking at the docs for these routes (The (EVManager), we can see that there are several commands that are sent within a execute_charging_session or modify_charging_session message. As such, it doesn't seem appropriate to create an entirely new route; rather, I think the goal is to add a separate command within the execute_charging_session packet. This goes back to my explorations earlier -- turns out I should be adding to the sim commands. I'm still a bit confused as to this process, but will do some digging into JsEvManager and EvManager's car_simulatorImpl.cpp. Should also probably take some time to investigate the testing code that covers these functions...

@shankari
Copy link
Collaborator Author

First, where is the limit computation coming from?

It is

int SmartChargingHandler::get_power_limit(const int limit, const int nr_phases,                                        
                                          const ChargingRateUnitEnum& unit_of_limit) {                                 
    if (unit_of_limit == ChargingRateUnitEnum::W) {                                                                    
        return limit;                                                                                                  
    } else {                                                                                                           
        return limit * LOW_VOLTAGE * nr_phases;                                                                        
    }                                                                                                                  
}                                                                                                                      

ah

const int LOW_VOLTAGE = 230;

updating the power limits in #64 (comment)

  • we requested 60x10^3 Wh = 60,000 Wh with a departure time of 21600 (6 hours)
    • the max current was limited to 10A, 3 phase. So the max power is 230 (LOW_VOLTAGE) * 10 * 3 = 6900 W.
    • Then the SASchedule is returned in watts @ 6,900W for the entire day.
      • That gives us 165,600 Wh (6900 * 24) which is more than the energy we want , but doesn't let us leave after 6 hours
      • if we do try to leave after 6 hours, we will end up with only 41,400 Wh (6900 * 6) which is less than what we requested

Next question: why are we not handling the departure time correctly, and why are we returning exactly one SASchedule?

@shankari
Copy link
Collaborator Author

Confirmed that the return SASchedules (EVSE -> car) are created in the modules/EvseV2G/iso_server.cpp, in handle_iso_charge_parameter_discovery. We create one SASchedule with one PMax entry, and we set it to the entire day.

            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]                          
                .PMaxSchedule.PMaxScheduleEntry.array[0]                                                     
                .RelativeTimeInterval.start = 0;                                                             
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]                          
                .PMaxSchedule.PMaxScheduleEntry.array[0]                                                 
                .RelativeTimeInterval.duration_isUsed = 1;                                                   
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]                          
                .PMaxSchedule.PMaxScheduleEntry.array[0]                                                     
                .RelativeTimeInterval.duration = SA_SCHEDULE_DURATION;                                       
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.array[0]                          
                .PMaxSchedule.PMaxScheduleEntry.arrayLen = 1;                                                
            conn->ctx->evse_v2g_data.evse_sa_schedule_list.SAScheduleTuple.arrayLen = 1;                     

@shankari
Copy link
Collaborator Author

So achieving our original goals, with multiple SASchedules is going to be fairly complex. Given the short timeframe, let us at least try for a much simpler option in with there is a single charging profile set, but the user specifies a departure time and energy need, and we spread the energy out over the entire charging period.

@the-bay-kay
Copy link

the-bay-kay commented Jul 16, 2024

It seems that once you add a command to /carsim/cmd/{}, it needs to be registered in both JsEvManager and EVManager's car_simulatorImpl.cpp.

So, we need to finally answer the question: How do we add commands to the message?

Looking at the Buffer sim commands function node's code:

if (msg.topic.indexOf('sim_commands') > -1) {
    const s = msg.payload.split('#');
    flow.set('sim_commands_start', s[0]);
    flow.set('sim_commands_stop', s[1]);
    flow.set('sim_commands_pause', s[2]);
    flow.set('sim_commands_resume', s[3]);
} 
// Code continues...

We can use the default injection to understand exactly how the payload is generated. The following string...

sleep 1;iec_wait_pwr_ready;sleep 1;draw_power_regulated 16,3;sleep 36000#unplug#pause;sleep 3600#draw_power_regulated 16,3;sleep 36000

Assigns itself to each of the sim commands, as follows...

Flow Variable (Command) Flow Value (Commands)
Start sleep 1;iec_wait_pwr_ready;sleep 1;draw_power_regulated 16,3;sleep 36000
Stop unplug
Pause pause;sleep 3600
Resume draw_power_regulated 16,3;sleep 36000

Ah, that makes more sense -- we set a series of commands for each possible method of interacting with the simulation loop! Cool. Know this, we finally have some steps to move forward:
EDIT: Updating checklist.

  • The Set DepartureTime node should add a new command set_departure_time to the Start and Resume phases of the simulation.
    • I believe this can be done within the Buffer sim commands function, though we may want to separate out the functionality to a second function node. TBD.
    • Aside: I think we don't have to worry about the type of the input for this command on the Node-RED side of things. Everything is already being input as a string, so we can parse / throw errors after the package has been received.
  • The command must be registered with both of the managers described above (JsEvManager, EVManager).
  • Once registered, we can define and detail the implementation!

@shankari
Copy link
Collaborator Author

Ok, so I can confirm that I can read the values correctly in the ISO server code,

2024-07-16 23:30:07.580610 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: max_current 32.000000, nom_voltage 230, pmax 22080
2024-07-16 23:30:07.580705 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: Requested departure time 0, requested energy 60.000000

now to actually use the departure time and requested energy...

@the-bay-kay
Copy link

the-bay-kay commented Jul 16, 2024

First design hiccup: We cannot simply pipe the set_departure_time command into the buffer like the other commands. Consider the following scenario:

  • User selects CarSimulation AC ISO 15118-2
    • Result: All 4 commands are set from this "default sim profile"
  • User then inputs a departure time
    • Result: command is propagated to the commands
  • User then changes their mind, and selects AC ISO 15118-2: Plug & Charge
    • Result: All 4 commands are set, overwriting the departure time insertion. The DepartureTime will not be propagated again until it is mutated

Solution: We still need have the set_departure_time send its message through the buffer*, but we should also set a flag somewhere that the other that the car simulation node can check. I think this will be done via a "Flow Variable", as we have done is done with the sim_commands. Once I figure out how to set one of these scoped variables, this should be a relatively fix

*Caveat: I think this part of the function will behave quite similar to the simulation selection. That is, the change will be fed into the buffer, but the message will not propagate through to the mqtt server (This is because should only send departure time during a Start or Resume vent)

@shankari
Copy link
Collaborator Author

shankari commented Jul 17, 2024

So I am not quite sure how we go from a complex set of schedule periods to a single limit.
OCPP calls OCPP201::set_external_limits which passes in a composite schedule.
But when we get to the energy manager, we only return one optimized schedule

2024-07-16 23:59:55.150578 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-16 23:59:55.150671 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-16 23:59:55.150816 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 
2024-07-16 23:59:55.277531 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000

If I can figure out how to pass this through, we might be able to do a better demo.
Also checking to see whether the schedules are automatically recalculated (there is a timer that sets the limits)

None of them are valid
2024-07-16 23:56:11.012269 [WARN] ocpp:OCPP201    module::OCPP201::ready()::<lambda()> :: Received a new Charging Schedules from the CSMS or another actor.
2024-07-16 23:56:11.012377 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 23:56:11.012454 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-17T00:00:00.000Z
2024-07-16 23:56:11.012531 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.012Z
2024-07-16 23:56:11.012617 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T00:00:00.000Z
2024-07-16 23:56:11.012693 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T01:00:00.000Z
2024-07-16 23:56:11.012797 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.012Z
2024-07-16 23:56:11.012897 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T01:00:00.000Z
2024-07-16 23:56:11.012973 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T02:00:00.000Z
2024-07-16 23:56:11.013047 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.012Z
2024-07-16 23:56:11.013118 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T02:00:00.000Z
2024-07-16 23:56:11.013267 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-18T00:00:00.000Z
2024-07-16 23:56:11.013349 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  end_time: 2080-03-01T16:33:27.779Z
2024-07-16 23:56:11.013443 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-16 23:56:11.013473 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-17T00:00:00.000Z
2024-07-16 23:56:11.013502 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.013Z
2024-07-16 23:56:11.013529 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T00:00:00.000Z
2024-07-16 23:56:11.013612 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T01:00:00.000Z
2024-07-16 23:56:11.013721 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.013Z
2024-07-16 23:56:11.013799 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T01:00:00.000Z
2024-07-16 23:56:11.013839 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T02:00:00.000Z
2024-07-16 23:56:11.013986 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-16T23:56:11.013Z
2024-07-16 23:56:11.014055 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T02:00:00.000Z
2024-07-16 23:56:11.014151 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-18T00:00:00.000Z
2024-07-16 23:56:11.014379 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  end_time: 2080-03-01T16:33:27.779Z
2024-07-16 23:56:11.098733 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_set_charging_profile_req(ocpp::Call<ocpp::v201::SetChargingProfileRequest>) :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-16 23:56:11.329473 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-16 23:56:11.329732 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}

Day switched over (in UTC), but the timer doesn't seem to be recalculating
2024-07-16 23:59:59.613293 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-16 23:59:59.613351 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-16 23:59:59.701427 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:00.012011 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_message(const ocpp::EnhancedMessage<ocpp::v201::MessageType>&) :: Handle_message called: [3,"6459f8b8-bc74-4cf0-a946-20f0007d2338",{}]
2024-07-17 00:00:00.012105 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_message(const ocpp::EnhancedMessage<ocpp::v201::MessageType>&) :: json_message called: [3,"6459f8b8-bc74-4cf0-a946-20f0007d2338",{}]
2024-07-17 00:00:00.792140 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:00.792267 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:00.792492 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:00.792576 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:00.881991 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:01.929852 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:01.930111 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:01.930357 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:01.930521 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:01.977783 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:03.024977 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:03.025242 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:03.025353 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:03.025468 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:03.073103 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:04.119963 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:04.120263 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:04.120372 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:04.120509 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:04.208647 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:05.297367 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:05.297640 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:05.297807 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:05.297898 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:05.386170 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:06.434387 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:06.434612 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:06.434808 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:06.434921 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:06.523742 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:07.570195 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:07.570478 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:07.570590 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:07.570651 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:07.618045 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:08.663480 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:08.663657 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:08.663806 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:08.663845 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:08.752327 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:09.839791 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:09.840045 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:09.840189 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:09.840265 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:09.888312 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:10.975204 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:10.975472 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:10.975792 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:10.975854 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:10.982449 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:12.028872 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:12.029073 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:12.029182 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:12.029243 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:12.075557 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:13.162296 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:13.162551 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:13.162727 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:13.162803 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:13.210296 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:14.259348 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:14.259736 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:14.259860 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:14.259930 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:14.307981 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:15.316521 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:15.316672 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:15.316752 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:15.316797 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:15.429489 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:16.476905 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:16.477109 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:16.477219 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:16.477280 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:16.564772 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:17.611086 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:17.611292 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:17.611411 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:17.611671 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:17.659640 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:18.708795 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:18.708973 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:18.709107 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:18.709204 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:18.755105 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:19.803908 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:19.804180 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:19.804335 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:19.804417 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:19.852383 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:20.901811 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:20.902077 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:20.902219 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:20.902298 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:20.950124 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:21.998977 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:21.999181 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:21.999287 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:21.999345 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:22.005213 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:23.053485 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:23.053674 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:23.053760 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:23.053805 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:23.140427 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:24.189693 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:24.189949 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:24.190099 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:24.190178 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:24.197073 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:25.285275 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:25.285501 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:25.285684 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:25.285745 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:25.333425 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:26.421466 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:26.421780 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:26.421897 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:26.421958 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:26.459672 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:27.508468 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:27.508760 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:27.508947 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:27.509105 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:27.557371 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:28.604746 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:28.604951 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:28.605049 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:28.605155 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:28.652187 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:29.741137 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:29.741400 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:29.741673 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:29.741871 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:29.830648 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:30.876287 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:30.876542 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:30.876706 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:30.876767 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:30.882841 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:31.928334 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:31.928511 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:31.928593 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:31.928635 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:32.014657 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:33.061162 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:33.061422 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:33.061626 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:33.061730 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:33.109183 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:34.200705 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:34.200998 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:34.201159 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:34.201341 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:34.208331 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:35.254159 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:35.254723 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:35.254863 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:35.255011 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:35.311777 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:36.336359 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:36.336616 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:36.336756 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:36.336835 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:36.343761 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:37.391450 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:37.391636 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:37.391733 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:37.391787 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:37.397841 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:38.485356 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:38.485579 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:38.485676 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:38.485839 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:38.532511 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:39.620220 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:39.620662 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:39.620795 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:39.620870 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:39.626831 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:40.673955 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:40.674196 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:40.674377 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:40.674611 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:40.721364 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:41.811856 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:41.812144 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:41.812277 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:41.812338 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:41.901316 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:42.989366 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:42.989549 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:42.989683 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:42.989739 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:43.037266 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:44.125913 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:44.126223 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:44.126531 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:44.126617 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:44.173596 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:45.219017 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:45.219339 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:45.219520 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:45.219652 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:45.306465 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:46.355596 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:46.355803 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:46.355912 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:46.355973 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:46.403151 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:47.449671 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:47.449877 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:47.449985 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:47.450046 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:47.456590 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:48.548042 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:48.548305 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:48.548422 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:48.548484 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:48.596305 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:49.642440 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:49.642696 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:49.642835 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:49.642914 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:49.690390 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:50.737078 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:50.737253 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:50.737339 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:50.737409 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:50.782754 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:51.829982 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:51.830249 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:51.830452 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:51.830515 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:51.877462 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:52.924249 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:52.924422 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:52.924520 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:52.924571 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:52.970958 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:54.019200 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:54.019504 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:54.019645 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:54.019723 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:54.068059 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:55.117471 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:55.117729 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:55.117869 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:55.117946 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:55.166134 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:56.253945 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:56.254246 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:56.254446 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:56.254576 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:56.344033 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:57.433494 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:57.433754 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:57.433894 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:57.434032 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:57.482176 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:58.530312 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:58.530578 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:58.530750 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:58.530829 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:58.562756 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:00:59.611335 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:00:59.611658 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:00:59.611842 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:00:59.611931 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:00:59.660272 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:01:00.707389 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:01:00.707572 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:01:00.707675 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:01:00.707727 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:01:00.796434 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:01:01.842880 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:01:01.843087 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}

Resending the setChargingProfile, the limits are now clamped, but there is still only one limit from the energy manager
2024-07-17 00:06:22.566084 [WARN] ocpp:OCPP201    module::OCPP201::ready()::<lambda()> :: Received a new Charging Schedules from the CSMS or another actor.
2024-07-17 00:06:22.566365 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-17 00:06:22.566447 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-17T00:00:00.000Z
2024-07-17 00:06:22.566551 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-17T00:06:22.566Z
2024-07-17 00:06:22.566625 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T00:00:00.000Z
2024-07-17 00:06:22.566717 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T01:00:00.000Z
2024-07-17 00:06:22.566881 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 10.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-17T01:00:00.000Z
2024-07-17 00:06:22.566953 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-17 00:06:22.567066 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900
2024-07-17 00:06:22.567298 [INFO] ocpp:OCPP201     :: ProfileId #1 Kind: Absolute
2024-07-17 00:06:22.567369 [INFO] ocpp:OCPP201     :: #1 find_period_at> 2024-07-17T00:00:00.000Z
2024-07-17 00:06:22.567425 [INFO] ocpp:OCPP201     ::    find_period_at>        start_time> 2024-07-17T00:06:22.567Z
2024-07-17 00:06:22.567493 [INFO] ocpp:OCPP201     ::    find_period_at> period_start_time> 2024-07-17T00:00:00.000Z
2024-07-17 00:06:22.567536 [INFO] ocpp:OCPP201     ::    find_period_at>   period_end_time> 2024-07-17T01:00:00.000Z
2024-07-17 00:06:22.567692 [INFO] ocpp:OCPP201     :: PeriodDateTimePair>  period: {
    "limit": 10.0,
    "numberPhases": 3,
    "startPeriod": 0
} end_time: 2024-07-17T01:00:00.000Z
2024-07-17 00:06:22.567758 [INFO] ocpp:OCPP201     :: period.has_value() limit = 6900
2024-07-17 00:06:22.567819 [INFO] ocpp:OCPP201     :: period.has_value() stackLevel = 6900
2024-07-17 00:06:22.611970 [ERRO] ocpp:OCPP201    void ocpp::v201::ChargePoint::handle_set_charging_profile_req(ocpp::Call<ocpp::v201::SetChargingProfileRequest>) :: Received profile validity: Validsetting response to {
    "status": "Accepted"
}
2024-07-17 00:06:22.670534 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:06:22.670733 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 32.0
}
2024-07-17 00:06:22.670840 [INFO] energy_manager:  :: returning optimized values vector of length 1
2024-07-17 00:06:22.670897 [INFO] energy_manager:  :: evse_manager_1 Enforce limits 32A -9999W 

2024-07-17 00:06:22.718080 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: In ISO15118 charger impl, after updating AC max current to 32.000000, we get 32.000000
2024-07-17 00:06:23.765308 [INFO] energy_manager:  ::                                NO TRADE 
2024-07-17 00:06:23.765548 [INFO] energy_manager:  :: Sending enfored limits (import) to :evse_manager_1 {
    "ac_max_current_A": 10.0,
    "total_power_W": 6900.0
}
2024-07-17 00:06:23.765665 [INFO] energy_manager:  :: returning optimized values vector of length 1

@the-bay-kay
Copy link

the-bay-kay commented Jul 17, 2024

Will we need a separate command to clear the departureTime once it's sent? Or will re-starting (resuming) without the command sufficient?

For now, let's assume we have to delete the command. With some initial futzing, this has proven to be somewhat non trivial. Below is my exploration of this first approach.

Method: Command Insertion / Deletion

First, we define a command insertion as changing a string as follows:

// Old Command List: sleep 1;iso_wait_slac_matched;iso_start_v2g_session externalpayment,ac;iso_wait_pwr_ready;iso_draw_power_regulated 16,3;sleep 36000
flow.set('sim_commands_start', flow.get('sim_commands_start').splice(2, 0, 'iso_set_departure_time'));
// New Command List: sleep 1;iso_wait_slac_matched; iso_set_departure_time; iso_start_v2g_session externalpayment,ac;iso_wait_pwr_ready;iso_draw_power_regulated 16,3;sleep 36000

To pick apart my thought process, let's draw up a truth table:

departure_time_msg has value departure_time_msg empty
departure_time_cmd in start/resume Update current commands to new command Remove Existing command
departure_time_cmd not in start/resume Insert new cmd NOOP

Likewise, as defined above, we need to account for the profile reset. Let's assume we've re-set the profile, and are now checking whether or not the user has defined a departureTime. Drawing up another table...

Update Simulation Profile
departure_time_cmd defined Insert cmd
departure_time_cmd undefined NOOP

Well, after drafting that up, I think it's time to take a step back: we can do better. Instead of removing or adding the commands (which starts to add complications), what happens if we simply mutate the value within the command? Let's re-do the truth tables from my first attempt

User Inputs new Departure Time

departure_time_msg has value departure_time_msg empty
departure_time_cmd in start/resume Update current commands to new value Update current commands to new value
departure_time_cmd not in start/resume Command will always be present N/A N/A
Update Simulation Profile
departure_time_cmd defined Update Command
departure_time_cmd undefined Update Command

Phew!! I was really gilding the lily with the first approach -- this is way simpler.


To summarize: Going forward, each "simulation profile" will have a iso_set_departure_time command. This command will be one of two values: null, or a 32u value. This means that the signal being sent here is not in absolute parity with the spec, but this approach (i) allows us to include / exclude the extension on the EVManager, and (ii) greatly simplifies the UI code.

@shankari
Copy link
Collaborator Author

Yay! with some fairly obvious changes, this now works!

2024-07-17 00:41:59.842439 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: before adjusting for departure time, max_current 32.000000, nom_voltage 230, pmax 22080

2024-07-17 00:41:59.842500 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: Requested departure time 21600, requested energy 60000.000000

2024-07-17 00:41:59.842541 [WARN] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: Min hours to charge 2.717391, requested departure time in hours 6.000000, plenty of time to charge, lowering pmax = 1.000000

2024-07-17 00:41:59.843014 [ERRO] iso15118_charge void dlog_func(dloglevel_t, const char*, int, const char*, const char*, ...) :: CHECKME: when is this called and do we need to modify it as well
2024-07-17 00:41:59.925920 [INFO] evse_manager_1:  ::                                     CAR ISO V2G ChargeParameterDiscoveryReq
2024-07-17 00:41:59.981000 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargeParameterDiscoveryRes
2024-07-17 00:41:59.990256 [DEBG] iso15118_car    pybind11_init_everestpy(pybind11::module_&)::<lambda(const std::string&)> :: Decoded message (ns=urn:iso:15118:2:2013:MsgDef): {"V2G_Message":{"Header":{"SessionID":"3968BF77DD9EBDB9"},"Body":{"ChargeParameterDiscoveryRes":{"ResponseCode":"OK","EVSEProcessing":"Finished","SAScheduleList":{"SAScheduleTuple":[{"SAScheduleTupleID":1,"PMaxSchedule":{"PMaxScheduleEntry":[{"RelativeTimeInterval":{"start":0,"duration":21600},"PMax":{"Multiplier":0,"Unit":"W","Value":10000}}]}}]},"AC_EVSEChargeParameter":{"AC_EVSEStatus":{"NotificationMaxDelay":0,"EVSENotification":"None","RCD":false},"EVSENominalVoltage":{"Multiplier":-1,"Unit":"V","Value":2300},"EVSEMaxCurrent":{"Multiplier":-1,"Unit":"A","Value":320}}}}}}

However, the EVSEMaxCurrent needs to be fixed, in the second part of the handler. Not quite sure why we are handling it twice, but whatever...

@the-bay-kay
Copy link

the-bay-kay commented Jul 29, 2024

Progress! Modifying charger_state.py to add DepartureTime: 86400 seems to have worked! Now, we can run the plug & Charge without issue.

To recap the status of the integration:

  • JsEvManager/index/js
  • PyEvJosev/module.py
  • .../secc/everest/charger_state/py
  • .../secc/controller/simulator.
  • .../secc/controller/simulator.py

Fingers crossed these last two will be it!

@shankari
Copy link
Collaborator Author

I would not expect that you need to change any of the SECC code. I didn't have to change any of it when I set the departure time by editing files.

@the-bay-kay
Copy link

I would not expect that you need to change any of the SECC code. I didn't have to change any of it when I set the departure time by editing files.

That was my assumption as well -- I'm somewhat unsure as to why this issue was happening, but I think I've solved it.

Changing onlymodule.py, evcc/ev_state.py and evcc.simulator.py , the simulator is running, but the departure time change isn't propagating:

Screenshots

image

image

image

@the-bay-kay
Copy link

The good news: Changing the default in ev_state.py does work... why aren't we getting the signal from the UI??

image

@the-bay-kay
Copy link

the-bay-kay commented Jul 29, 2024

Do we need to add something to one of the shared message datatype files?? I can't see a place where the departure time would cleanly fit in, but my assumption is that we're missing some portion of the message I/O...

DepartureTime is already handled in this datatypes file, so I believe we don't need to focus there.

@the-bay-kay
Copy link

the-bay-kay commented Jul 30, 2024

I was so sure I was missing something on the iso15118 side of things, I forgot to really trace through module.py 😅 I'm 95% sure this is my issue.

As currently written, we're trying to gather the departure time as follows:

    def _handler_start_charging(self, args) -> bool:
        log.info(str(args))
        self._es.EnergyTransferMode = args['EnergyTransferMode']
        self._es.DepartureTime = args['DepartureTime']
        self._es.EAmount = args['EAmount'
# ..

Having added this log, we find that the args are:

[{'EnergyTransferMode': 'AC_three_phase_core', 'PaymentOption': 'Contract'}]

Can't exactly fetch what isn't there... Let's see where the args is set

@the-bay-kay
Copy link

Ok, tracing the code:

  • _handler_start_charging is defined in module.py, but not called here. Rather, this is a member function of the PyJosevModule class.
  • We then instantiate an object of this class, call start_evcc_handler(), which in turn calls evcc_handler_main_loop, which instantiates an EVCCHandler(), running its start function. So, let's track that down in the ext-switch-iso15118 repo
  • evcc/__init__.py shows us that EVCCHandler inherits from CommunicationSessionHandler, and calls start_session_handler...

I'll keep going from here, but it feels like I'm starting to lose the forest for the trees. I just can't find where the handler_start_charging is called -- if we can find where those args are passed in, I think I'll better understand why we're not receiving the other data

@the-bay-kay
Copy link

Aha! I had been confused as to the relationship between JsEvManager and PyJosEv until now -- I suppose that is because I didn't read through index.js carefully enough... As we can see on this line, we pass the args in here! That seems to be what I missed, lets go ahead and patch that.

@the-bay-kay
Copy link

the-bay-kay commented Jul 31, 2024

Making the aforementioned changes, we can now the default in index.js and watch it propagate completely! Currently, we have:

  • Node-red sends the UI-set values to the registerCmd(mod, 'iso_set_departure_time')
  • Set departure time is not successfully setting the departure time before
  • The EAMount / DepTime (currenty, default) is passed to module.py, which
  • passes the values to ev_state.py and simulator.py
    So, let's check off that last box

@the-bay-kay
Copy link

the-bay-kay commented Jul 31, 2024

It seems the order of our commands is slightly out-of-wack... Looking at the logs:

image

The values are being sent to module.py before set_departure_time is processed in the simulation loop. Perhaps we need to update the order in our UI command sequence?

EDIT: Yup, that seems to have been the issue. Looking at the order of commands...
...;iso_start_v2g_session contract,ac;iso_set_departure_time null null;...
That's definitely backwards. Here's to hoping this is the final piece!

@the-bay-kay
Copy link

the-bay-kay commented Aug 1, 2024

Success!! Just needed to deploy the flow changes, and that was the final piece. Will edit this comment with videos of the changes in each permutation, and then include the files / how to run after.

Screen Captures Below

Photos of runtime behavior

Fields Empty: Defaults

V1.mp4

Departure Time Only

2.mp4

DepartureTime & EAmount: Low DT

3.mp4

DepartureTime & EAmount: High DT (Adjusts power draw)

4.mp4

@the-bay-kay
Copy link

the-bay-kay commented Aug 1, 2024

Working on reproducibility now -- the above videos show it running, currently attempting to add the files to a fresh install & make the demo run smoothly. Will update with instructions once I have a reproducible demo!

EDIT: The demo is reproducible! Small hitch -- on a fresh reproduction, the empty DT / EAmount result in a failure to get past the "PrepareCharging" phase (This seems to be due to the null values I was using as default, that I forgot to change). Will fix this, then include files + demo instructions,

@shankari
Copy link
Collaborator Author

shankari commented Aug 1, 2024

you should submit a PR to the demo repo with the patches to the files that you changed so we have a working demo again. And then we can submit PRs to the core repos and involve the community in how best to implement this (and similar changes)

But for today afternoon, you can demo from your laptop 😄

@the-bay-kay
Copy link

the-bay-kay commented Aug 2, 2024

Now that we have a working demo, we can pivot to incorporating the SetChargingProfile functionality. Modifying the demo script maeve-set-charging-profile.sh as follows...

# Adding a -v for debugging...
curl -v -X POST \ 
"http://localhost:9410/api/v0/cs/${CS}/setchargingprofile" \
-H "Content-Type: application/json" \
-d "$JSON_DATA"     

Shows us that the issue is indeed with the post. Running the script with one of our Charging Profiles (with a properly adjusted timestamp), we get the following output:

image

I believe our issue is the second half of this... let's investigate further

Re-reading and better understanding the curl output, the POST seems to have successfully created the file.. So, why isn't the profile change not being shown?

@the-bay-kay
Copy link

Yup: Looking at the maeve-csms-manager-1 logs, looks like our POST is happening OK...

Untitled

Let's dig into the files and see why we're not reading this

@shankari
Copy link
Collaborator Author

shankari commented Aug 2, 2024

Wait, this is using 001 instead of cp001?!

@the-bay-kay
Copy link

Wait, this is using 001 instead of cp001?!

OH! Good catch lol -- yup, that was the issue. At least it's an easy fix... 😅

image

@the-bay-kay
Copy link

the-bay-kay commented Aug 6, 2024

Demos are now working with a default values {EA=60, DepartureTime=86400}. Now, the twist is making DepartureTime (DT) optional, as per [V2G2-361]. To do this, we need to:

  • Change the NodeRed to send an empty DT value by default (we use an empty string)
  • In JsEvManager, we now fill in "Null" as the type for DT if no value is given (empty string)
  • iso15118/evcc/ev_state.py now has the DT Default as Optional[int] = None
  • In iso15118/evcc/ev_state.py, only add the DT field to ACChargeParameter if DT has been specified

Once these are (i) implemented and (ii) confirmed to be working, the plan is to:

  • Create an image via docker commit,
  • Take this image, add it to GHCR and tag it
  • Commit the changes to the demo branch
  • Open PRs for the corresponding modules*

After these are done, we can move forward with updating the demo.

*Merging the demo to the main branches may be tricky, because I believe our PaymentMethod strategy in our demo differs from what is currently implemented (link to relevant discussion). Will cross that bridge when we come to it!

@the-bay-kay
Copy link

Taking some time to clean up my code and refactor while making these changes. We have a design decision to make: When should we filter out an empty DepartureTime?

My first though was to do so in the iso15118/evcc/simulator.py call -- I believe this is the most logical answer, as this is the final layer between the Python & C++ code. That being said, we could check for null and not include this value within mod.uses_list.ev[0].call.start_charging(args);, located in JsEvManager/index.html. I don't think this is as valuable (I think we'd still need to update the typing to optional in EvState.py), but I think the thought was worth recording.

@the-bay-kay
Copy link

Ah - it seems that passing in the null value was enough, we don't need to tweak iso15118/evcc/simulator.py:

image

Since this is functionally what we want, and we want a working demo up asap 'll go ahead and commit the image to ghcr.


Aside: I'm not 100% satisfied with our working solution. Per [V2G2-361] of ISO 15118-2, DepartureTime is an optional extension of the AC_EVChargeParameterType. As written, we send an empty DT as DepartureTime: Null. This is then interpreted in as "No DepartureTime was set". While functionally identical, this is not the same as excluding the DepartureTIme field entirely.

Perhaps I'm splitting hairs, but I think our implementation should hug as closely to the spec as possible. This is fine for a hack-y proof of concept, but I think we should re-factor this to better match the spec. I've got some thoughts on how we'd do so, but I can save that for the PR discussion (this issue has gotten quite bulky as is!)

@the-bay-kay
Copy link

I've got an image successfully build, but am running into some hiccups adding it to the demo's us-joet repo. I've successfully pushed a copy to my personal account (link), but I can only link to repos I own (which makes sense). Attempting to push to us-joet/everest-demo/manager results in a "403: Forbidden" error. Perhaps this is an issue with my token authorization? My token doesn't have a "configure SSO" option, I'll dig further

Screenshot of Error

image

@shankari
Copy link
Collaborator Author

shankari commented Aug 8, 2024

@the-bay-kay this is almost certainly a permissions issue. Since this is a temporary stage anyway, you can just make your package be public and point to it. We can then fix the permissions before the final version.

@the-bay-kay
Copy link

The latest image can be found here -- just tested with a completely fresh install, seems to work perfectly! Will push the changes to everest-demo, then we can close this issue and move onto the more complex changes involving the SAScheduleList.

@the-bay-kay
Copy link

@shankari the PR for these changes has been made! Will start moving these changes into individual demo-wrapup PRs, as we did with the initial CharIn changes.

@shankari
Copy link
Collaborator Author

shankari commented Aug 8, 2024

@the-bay-kay we probably want to move on to the full demo before that for two reasons:

  1. we still haven't resolved the previous demo wrap ups
  2. we aim to have the full demo done in a month, which is already a bit tight

@shankari
Copy link
Collaborator Author

We now have a demo of the departure time using the lowest_viable_power algorithm, so closing this issue.
We will track the next stage of this - supporting multiple options that the EV will choose between, in a different issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants