matth-x / MicroOcpp

OCPP 1.6 / 2.0.1 client for microcontrollers
MIT License
344 stars 149 forks source link

Send Metervalues data to OCPP server #128

Closed dipankarkhartad closed 1 year ago

dipankarkhartad commented 1 year ago

Hi Matth,

I am trying to send the meter values like voltage, current, energy, and frequency to the OCPP server. But unable to send MeterValues.req to OCPP.

I added the below functions in the setup function,

Is there anything I need to add in a void loop or any library files?

` addMeterValueInput([] { return readVoltage(); }, "Voltage", "V", nullptr, "L1");

addMeterValueInput([]() { return readCurrent(); }, "Current.import", "A");

addMeterValueInput([] { return readEnergy(); }, "Energy.Active.Import.Register", "Wh");

addMeterValueInput([] { return readFreaquency(); }, "Frequency", "Hz");`

pedro-fuoco commented 1 year ago

Not even the Energy.Active.Import.Register is sent? That's weird. Does the code even run the MeterValues::createReq() function? You can check that by adding a print on ArduinoOcpp/MessagesV16/MeterValues.cpp

If it's running try adding the following code to the end of the createReq() function:

String reqSent;

serializeJson(*doc, reqSent);

Serial.println(reqSent);
return doc;

This will print on the serial monitor the message that's being sent to the Central System, you can post it here if you want further help.

Also, check #110

pedro-fuoco commented 1 year ago

Also, did you successfully connect to the Ocpp server through OCPP_initialize() ?

dipankarkhartad commented 1 year ago

@pedro-fuoco

Thank you very much for your response.

I added "Energy.Active.Import.Register" in setup function.

`void setup() {

Serial.begin(115200); Serial.print(F("[main] Wait for WiFi: "));

if defined(ESP8266)

WiFiMulti.addAP(STASSID, STAPSK); while (WiFiMulti.run() != WL_CONNECTED) { Serial.print('.'); delay(1000); }

elif defined(ESP32)

WiFi.begin(STASSID, STAPSK); while (!WiFi.isConnected()) { Serial.print('.'); delay(1000); }

else

error only ESP32 or ESP8266 supported at the moment

endif

Serial.println(F(" connected!"));

std::shared_ptr<ArduinoOcpp::Configuration<const char >> mvSampledData = ArduinoOcpp::declareConfiguration<const char >("MeterValuesSampledData", "", CONFIGURATION_FN); const char example = mvSampledData; // example: read value of configuration mvSampledData = "Voltage,Current.import,Energy.Active.Import.Register,Frequency, Power.Active.Import, Temperature"; // example: update configuration value ArduinoOcpp::configuration_save(); // write configs file back to flash immediately (not really necessary though) /

Also successfully connected to the OCPP server charger available, preparing, charging and finishing states are working properly in my code.

***** Logs above mentioned states**** Charger Condition:ev_connect [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp.cpp:308): Added ConnectorPluggedSampler. Transaction-management is in auto mode now 0 [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StatusNotification.cpp:50): New status: Preparing (connectorId 1) Charger Condition:start_charging [main] Transaction initiated. StartTransaction will be sent when ConnectorPlugged Input becomes true [main] Authorizing user with idTag NO.000000192468 0 [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/Tasks/ChargePointStatus/ConnectorStatus.cpp:237): Session mngt: trigger StartTransaction Allowed to charge isTransactionRunning 1 [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StatusNotification.cpp:50): New status: Charging (connectorId 1) Allowed to charge isTransactionRunning 1 Charger Condition:stop_charging [main] End transaction by RFID card 1 [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/Tasks/ChargePointStatus/ConnectorStatus.cpp:280): Session mngt: trigger StopTransaction [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StartTransaction.cpp:145): Request has been accepted [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StatusNotification.cpp:50): New status: Finishing (connectorId 1)
[AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StopTransaction.cpp:187): Request has been accepted! Charger Condition:ev_disconnect [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp.cpp:308): Added ConnectorPluggedSampler. Transaction-management is in auto mode now 0 [AO] info (.pio/libdeps/esp32dev/ArduinoOcpp/src/ArduinoOcpp/MessagesV16/StatusNotification.cpp:50): New status: Available (connectorId 1)

Do i need to call MeterValues::createReq() in setup as well as in loop?

pedro-fuoco commented 1 year ago

The code and the logs look good

Do i need to call MeterValues::createReq() in setup as well as in loop?

No, MeterValues::createReq() is called by the library during the OCPP_loop. In fact it is called every minute after the charger starts a transaction. Did you wait more than a minute in the Charging state to see if the values were sent?

dipankarkhartad commented 1 year ago

Thank you very much @pedro-fuoco

Now I am able to send metervalues to OCPP server.

Allowed to charge isTransactionRunning 1 Allowed to charge isTransactionRunning 1 Allowed to charge isTransactionRunning 1 {"connectorId":1,"transactionId":671421,"meterValue":[{"timestamp":"2023-03-17T04:55:19.000Z","sampledValue":[{"value":"0","context":"Sample.Periodic","measurand":"Energy.Active.Import.Register","unit":"Wh"},{"value":"230","context":"Sample.Periodic","measurand":"Voltage","phase":"L1","unit":"V"},{"value":"124","context":"Sample.Periodic","measurand":"Current.import","unit":"A"},{"value":"1244","context":"Sample.Periodic","measurand":"Energy.Active.Import.Register","unit":"Wh"},{"value":"50","context":"Sample.Periodic","measurand":"Frequency","unit":"Hz"}]}]} Allowed to charge isTransactionRunning 1

Can i change the period of meter values?

Also the reading context is Sample.Periodic, but could not found Transaction.Begin and Transaction.End.

matth-x commented 1 year ago

Hi,

You can change the period with MeterValueSampleInterval.

By default, Transaction.Begin and Transaction.End is turned off. You can set the desired parameters in the Configuration Key StopTxnSampledData just like MeterValuesSampledData for normal Meter Values. These values will appear in the StopTransaction message then.

jpily commented 1 year ago

Could you please share the full code?

Even if you analyze arduinoOCPP.cpp, there is difficulty in implementing meter sending. Any help would be appreciated.

dipankarkhartad commented 1 year ago

@matth-x

Hi,

I am facing issues while sending the meter values for the "context=Transaction.Begin", as for start transaction we need to send context as Transaction.Begin, but in the OCPP server logs I am able to see only context=Sample.Periodic.

Following snippet from server logs.

I have also attached the snippet of void setup of my code.

****ERROR FROM OCPP SERVER*****

023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:179 - *****Meter Values information** 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:180 - Meter Value Request :: MeterValuesRequest{connectorId=1, transactionId=597335, meterValue.length=1, isValid=true} 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:219 - Charger :: /AC_CHARGER1 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:220 - User :: NO.000000192468 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:221 - Time Elapsed :: 00:01:03 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:222 - Rate :: 10.0 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:235 - Meter Sample Value :: SampledValue{value=230, context=Sample.Periodic, format=null, measurand=Voltage, phase=L1, location=null, unit=V, isValid=true} 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:235 - Meter Sample Value :: SampledValue{value=124, context=Sample.Periodic, format=null, measurand=Current.import, phase=null, location=null, unit=A, isValid=true} 2023-03-23 11:22:08 DEBUG [Thread-351] ServerCoreResponseEvent:235 - Meter Sample Value :: SampledValue{value=1941, context=Sample.Periodic, format=null, measurand=Energy.Active.Import.Register, phase=null, location=null, unit=Wh, isValid=true} 2023-03-23 11:22:08 ERROR [Thread-351] ServerCoreResponseEvent:414 - Error in MeterValue request :: java.lang.NullPointerException: null at ocpp1_6.events.ServerCoreResponseEvent.handleMeterValuesRequest(ServerCoreResponseEvent.java:354) [classes!/:1.0.0] at eu.chargetime.ocpp.feature.profile.ServerCoreProfile.handleRequest(ServerCoreProfile.java:82) [v1_6-1.0.1.jar!/:?] at eu.chargetime.ocpp.feature.ProfileFeature.handleRequest(ProfileFeature.java:54) [common-1.0.jar!/:?] at eu.chargetime.ocpp.Server$1.handleRequest(Server.java:104) [common-1.0.jar!/:?] at eu.chargetime.ocpp.SimplePromiseFulfiller.fulfill(SimplePromiseFulfiller.java:41) [common-1.0.jar!/:?] at eu.chargetime.ocpp.AsyncPromiseFulfillerDecorator$1.run(AsyncPromiseFulfillerDecorator.java:43) [common-1.0.jar!/:?] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]

****END ERROR FROM OCPP SERVER*****

*void setup function***** void setup() {

/*

*void setup function end***** Is there any configuration which will send the the metervalue for the

  1. context=Transaction.Begin
  2. context=Sample.Periodic //Its working fine

Please have a look and help me to solve this issue.

dipankarkhartad commented 1 year ago

Hi @matth-x and @jpily,

I am little bit confused regarding when to send meter values.

Please correct my understanding if it is wrong. The flow is mentioned below as per my understanding.

  1. StartTransaction.req with the meterStart value
  2. MeterValues.req with the context as Transaction.Begin (Send meterValues to represent data related to beginning of transaction)
  3. MeterValues.req with the context as Sample.Periodic (Send meterValues periodically)
  4. StopTranscation.req with the meterStop value

//////////OR/////////////

  1. StartTransaction.req with the meterStart value
  2. MeterValues.req with the context as Sample.Periodic (Send meterValues periodically)
  3. StopTranscation.req with the meterStop and transactionData containing Transaction.Begin & Transaction.End

My Questions:

  1. The power consumption will be based on meterStart & meterStop OR
  2. The power consumption will be based on Transaction.Begin & meterStop
jpily commented 1 year ago

It is difficult to answer with simple information. Please post the complete code used by the arduino IDE. The basic test for the code I am developing has been completed. RFID (Authentication) -> Start of charging -> Charging -> RFID (Recognition)-> End of charging

jpily commented 1 year ago

I have summarized the function execution order based on the OCPP 1.6 charging scenario as follows:

1.OCPP_initialize(): Initializes the OCPP library. 2.bootNotification(): Sends a signal to the charging station that the charging station has completed booting. 3.authorize(): Performs user authentication. 4.beginTransaction(): Notifies the charging station that the charging has started. 5.setConnectorPluggedInput(): Detects that the vehicle is connected to the charger. 6.setEvReadyInput(): Detects that the vehicle is ready for charging. 7.setEvseReadyInput(): Detects that the charging station is ready for charging. 8.addMeterValueInput(): Adds energy meter values. 9.setOnResetNotify(): Registers a callback function to receive notifications when the charger is reset. 10.setOnResetExecute(): Registers a callback function to execute when the charger is reset. 11.setOnUnlockConnectorInOut(): Registers a callback function to execute when the vehicle completes charging and the connection is released. 12.setConnectorLockInOut(): Locks the charger so that the connection cannot be released while the vehicle is charging. 13.setTxBasedMeterInOut(): Registers the meter value to measure the energy usage of the charging vehicle. 14.stopTransaction(): Notifies the charging station that the charging has completed. 15.OCPP_deinitialize(): Deinitializes the OCPP library. 16.Of these functions, OCPP_initialize(), OCPP_loop(), and OCPP_deinitialize() functions must be called. The remaining functions are called as needed according to the scenario.

dipankarkhartad commented 1 year ago

@matth-x @pedro-fuoco @jpily

Thank you very much for your support. This library really helping us.

dipankarkhartad commented 1 year ago

Thank you very much @pedro-fuoco

Now I am able to send metervalues to OCPP server.

Allowed to charge isTransactionRunning 1 Allowed to charge isTransactionRunning 1 Allowed to charge isTransactionRunning 1 {"connectorId":1,"transactionId":671421,"meterValue":[{"timestamp":"2023-03-17T04:55:19.000Z","sampledValue":[{"value":"0","context":"Sample.Periodic","measurand":"Energy.Active.Import.Register","unit":"Wh"},{"value":"230","context":"Sample.Periodic","measurand":"Voltage","phase":"L1","unit":"V"},{"value":"124","context":"Sample.Periodic","measurand":"Current.import","unit":"A"},{"value":"1244","context":"Sample.Periodic","measurand":"Energy.Active.Import.Register","unit":"Wh"},{"value":"50","context":"Sample.Periodic","measurand":"Frequency","unit":"Hz"}]}]} Allowed to charge isTransactionRunning 1

@matth-x @jpily

One quick question on value field of the each meterValue.

Why the value are not showing "230.14" instead of "230"?

My declaration in the setup function is mentioned below


void setup(){ OCPP_initialize(OCPP_HOST, OCPP_PORT, OCPP_URL);

addMeterValueInput([] { return (int32_t) readVoltage(1); }, "Voltage", "V", nullptr, "L1", 1);

addMeterValueInput([]() { return (int32_t) readCurrent(1); }, "Current.Import", "A", nullptr, "L1", 1);

addMeterValueInput([] { return (int32_t) readEnergy(1); }, "Energy.Active.Import.Register", "Wh", nullptr, "L1", 1);

std::shared_ptr<ArduinoOcpp::Configuration<const char >> mvSampledData = ArduinoOcpp::declareConfiguration<const char >("MeterValuesSampledData", "DEFAULT VALUE", CONFIGURATION_FN); *mvSampledData = "Voltage,Current.Import,Energy.Active.Import.Register"; // example: update configuration value ArduinoOcpp::configuration_save(); }


All the parameter read function are returning double.

Is there any configuration setting I need to do to get "230.90" instead of "230"?

pedro-fuoco commented 1 year ago

@dipankarkhartad you are casting the return of your functions as (int32_t) before returning to addMeterValueInput. Try removing that cast.

The library should accept floats since #125 merged.

If you'd like more information, take a look at #112.

dipankarkhartad commented 1 year ago

@pedro-fuoco Thank you, I got it.