matth-x / MicroOcpp

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

Need Help for How to Add the new parameters in the Meter values like SOC, Voltage, Current and Temeprature #114

Closed mukeshtalks closed 1 year ago

mukeshtalks commented 1 year ago

Hello All, I am able to work with my CMS and geting the Energy (Wh) and the Power while charging. I need to Add More parameters in the meter reading like SOC, Voltage, Current and temperature, etc. Need the know how I can add these to the code. If any document or example is available or any guidance on how I can add that will be great.

piyush9999 commented 1 year ago

Hello @mukeshtalks are you able to add multiconnector functionality to the code. Could you please help me in getting the connector 1 and connector 2

mukeshtalks commented 1 year ago

@piyush9999 I have not tried yet. I was working with one connector only. Can you help me if you are able to add the parameters I am looking for.

matth-x commented 1 year ago

Hi, you can use the more generic function addMeterValueInput. It works similar to the EneryInput and PowerInput, but you can define more details. See the example here:

https://github.com/OpenEVSE/ESP32_WiFi_V4.x/blob/751d8374ab072df83a920295b6723dc8e904d21e/src/ocpp.cpp#L165-L169

matth-x commented 1 year ago

@piyush9999 Sorry, I forgot to mention multiple connectors here. See the following code snippet:

int connectorId = 1; //select connectorId 0, 1 or 2

addMeterValueInput([this] () {
    return (int32_t) evse->getAmps();
}, 
"Current.Import",
"A",
nullptr, //location (optional)
nullptr, //phase (optional)
connectorId);
piyush9999 commented 1 year ago

Hey, @matth-x if I want to use Two connectors, then the statusNotification should send connector id 1 and 2 but in current condition, it is sending 0 and 1. Is there anything in the main source code that I have to add to get multiple connectors functionality. So I can start and stop transaction and meter them separately

matth-x commented 1 year ago

Hi @piyush9999, in platformio.ini, add -D AO_NUMCONNECTORS=3 to the build_flags section.

The first connector has connectorId 1, the second has Id 2. You can ignore Id 0 for the moment.

Most of the functions in ArduinoOcpp.h have an optional parameter connectorId. It allows to select the connector.

mukeshtalks commented 1 year ago

@matth-x thank you for your reply. I will try the solution you suggest and get back to you if any issues I will face.

piyush9999 commented 1 year ago

hey @matth-x I have successfully added two connectors 1 and 2 as you told.

So when I'm starting transaction for Connector ID 2 I'm getting an error from the library as MeterStart Undefined

Log: [AO] Recv: [2,"a992d12c-cfbd-429d-94df-25382d5a52ff","RemoteStartTransaction",{"connectorId":2,"idTag":"Abcd12345"}] 17:34:56.138 -> [AO] Send: [3,"a992d12c-cfbd-429d-94df-25382d5a52ff",{"status":"Accepted"}] 17:34:56.138 -> [AO] info (lib_extras/ArduinoOcpp-master/src/ArduinoOcpp/Tasks/ChargePointStatus/ConnectorStatus.cpp:237): Session mngt: trigger StartTransaction 17:34:56.138 -> [AO] ERROR (lib_extras/ArduinoOcpp-master/src/ArduinoOcpp/Tasks/ChargePointStatus/ConnectorStatus.cpp:245): MeterStart undefined

And same error when I'm stopping the transaction Log: [AO] ERROR (lib_extras/ArduinoOcpp-master/src/ArduinoOcpp/Tasks/ChargePointStatus/ConnectorStatus.cpp:301): MeterStop undefined

matth-x commented 1 year ago

@piyush9999 When adding more connectors, it is necessary to add the setup functions for each connector again. For example, when setting the energy meter:

https://github.com/matth-x/ArduinoOcpp/blob/27ce8b15cd5158e1b8d637b67fe55416093bfe57/src/ArduinoOcpp.h#L191

you need to execute that function once for connectorId = 1 and for connectorId = 2. The same is required for each function which has the parameter unsigned int connectorId.

mukeshtalks commented 1 year ago

@matth-x I have added the meter values as suggested by you but these values are not getting added to the meter values while charging. Can you please suggest what could be wrong? I have added the meter values in main.cpp file in Setup function in SECC example in the library.

mukeshtalks commented 1 year ago

@matth-x I could able to send the meter values to my CMS with new inputs. I missed adding these new inputs to default configurations. After adding these this is working. Thank you for your Support.

piyush9999 commented 1 year ago

@matth-x Thanks brother added☺

mukeshtalks commented 1 year ago

@matth-x I have added the code as given below in the setup to add the new measurement values. But after adding this code I started facing an issue. At every power up I need to configure the WebSocket again. Please suggest where could be the issue, or I am missing something.

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 = "Power.Active.Import,Energy.Active.Import.Register,Voltage,Current.Import,SoC,Temperature"; //example: update configuration value //ArduinoOcpp::configuration_save(); //write configs file back to flash immediately (not really necessary though)

std::shared_ptr filesystem = ArduinoOcpp::makeDefaultFilesystemAdapter(ArduinoOcpp::FilesystemOpt::Use_Mount_FormatOnFail); ArduinoOcpp::configuration_init(filesystem);

if 1

ArduinoOcpp::declareConfiguration<const char *>(
    "MeterValuesSampledData", "DEFAULT VALUE", CONFIGURATION_FN); //declare configuration and use the default value parameter (replace with required value)
//ArduinoOcpp::configuration_save(); //again, not really necessary

endif

mukeshtalks commented 1 year ago

@matth-x below is the code in main.cpp for your reference.

`// matth-x/ArduinoOcpp // Copyright Matthias Akstaller 2019 - 2022 // MIT License // // // IMPORTANT: Please add https://github.com/tzapu/WiFiManager.git to the lib_deps of your project! // // This sketch demonstrates a complete OCPP Wi-Fi module of an EVSE. You can flash // an ESP8266/ESP32 with this program, build it into your EVSE and start charging with // OCPP-connectivity. // // The pin mapping and additional comments can be found in this file. You probably need // to adapt a few things before deployment. //

include

include //please add to lib_deps: https://github.com/tzapu/WiFiManager.git

include

include <ArduinoOcpp/Core/Configuration.h> //load and save settings of WiFi captive portal

/*

define EV_PLUG_PIN 14 // Input pin | Read if an EV is connected to the EVSE

if defined(ESP32)

define EV_PLUGGED HIGH

define EV_UNPLUGGED LOW

elif defined(ESP8266)

define EV_PLUGGED LOW

define EV_UNPLUGGED HIGH

endif

define OCPP_CHARGE_PERMISSION_PIN 5 // Output pin | Signal if OCPP allows / forbids energy flow

define OCPP_CHARGE_PERMITTED HIGH

define OCPP_CHARGE_FORBIDDEN LOW

define EV_CHARGE_PIN 12 // Input pin | Read if EV requests energy (corresponds to SAE J1772 State C)

if defined(ESP32)

define EV_CHARGING LOW

define EV_SUSPENDED HIGH

elif defined(ESP8266)

define EV_CHARGING HIGH

define EV_SUSPENDED LOW

endif

define OCPP_AVAILABILITY_PIN 0 // Output pin | Signal if this EVSE is out of order (set by Central System)

define OCPP_AVAILABLE HIGH

define OCPP_UNAVAILABLE LOW

define EVSE_GROUND_FAULT_PIN 13 // Input pin | Read ground fault detector

define EVSE_GROUND_FAULTED HIGH

define EVSE_GROUND_CLEAR LOW

/*

define SERVER_CONNECT_LED 16 // Output pin | Signal if connection to OCPP server has succeeded

define SERVER_CONNECT_ON LOW

define SERVER_CONNECT_OFF HIGH

define CHARGE_PERMISSION_LED 2 // Output pin | Signal if OCPP allows / forbids energy flow

if defined(ESP32)

define CHARGE_PERMISSION_ON HIGH

define CHARGE_PERMISSION_OFF LOW

elif defined(ESP8266)

define CHARGE_PERMISSION_ON LOW

define CHARGE_PERMISSION_OFF HIGH

endif

if !defined(SECC_NO_DEBUG)

define PRINT(...) Serial.print(__VA_ARGS__)

define PRINTF(...) Serial.printf(__VA_ARGS__)

define PRINTLN(...) Serial.println(__VA_ARGS__)

else

define PRINT(...)

define PRINTF(...)

define PRINTLN(...)

endif

WebSocketsClient wSock; ArduinoOcpp::EspWiFi::OcppClientSocket oSock{&wSock};

int evPlugged = EV_UNPLUGGED;

bool booted = false; ulong scheduleReboot = 0; //0 = no reboot scheduled; otherwise reboot scheduled in X ms ulong reboot_timestamp = 0; //timestamp of the triggering event; if scheduleReboot=0, the timestamp has no meaning

// ============ CAPTIVE PORTAL

define CAPTIVE_PORTAL_TIMEOUT 60 //in seconds

define WIFI_CONNECTION_TIMEOUT 30 //in seconds

struct Ocpp_URL { bool isTLS = true; String host = String('\0'); uint16_t port = 443; String url = String('\0'); bool parse(String& url); };

Ocpp_URL ocppUrlParsed = Ocpp_URL();

bool runWiFiManager(); // ============ END CAPTIVE PORTAL

//============= Kill Transaction ===================== //Added By Mukesh

define KILL_TRANSACTION_PIN 33 // Output pin | Signal if connection to OCPP server has succeeded

define KILL_TRANSACTION_ON LOW

define KILL_TRANSACTION_OFF HIGH

//====================================================

void setup() {

/*
 * Initialize peripherals
 */
Serial.begin(115200);

if !defined(SECC_NO_DEBUG)

Serial.setDebugOutput(true);

endif

pinMode(EV_PLUG_PIN, INPUT);
//pinMode(EV_PLUG_PIN, INPUT_PULLUP);
pinMode(EV_CHARGE_PIN, INPUT);
pinMode(EVSE_GROUND_FAULT_PIN, INPUT);
pinMode(OCPP_CHARGE_PERMISSION_PIN, OUTPUT);
digitalWrite(OCPP_CHARGE_PERMISSION_PIN, OCPP_CHARGE_FORBIDDEN);
pinMode(OCPP_AVAILABILITY_PIN, OUTPUT);
digitalWrite(OCPP_AVAILABILITY_PIN, OCPP_UNAVAILABLE);
pinMode(CHARGE_PERMISSION_LED, OUTPUT);
digitalWrite(CHARGE_PERMISSION_LED, CHARGE_PERMISSION_OFF);

pinMode(AMPERAGE_PIN, OUTPUT);

if defined(ESP32)

pinMode(AMPERAGE_PIN, OUTPUT);
ledcSetup(0, 1000, 8); //channel=0, freq=1000Hz, range=(2^8)-1
ledcAttachPin(AMPERAGE_PIN, 0);
ledcWrite(AMPERAGE_PIN, 256); //256 is constant +3.3V DC

elif defined(ESP8266)

analogWriteRange(255); //range=(2^8)-1
analogWriteFreq(1000); //freq=1000Hz
analogWrite(AMPERAGE_PIN, 256); //256 is constant +3.3V DC

else

error Can only run on ESP8266 and ESP32 on the Arduino platform!

endif

//==========Kill Transaction====================================== pinMode(KILL_TRANSACTION_PIN, INPUT_PULLUP); //================================================================

pinMode(SERVER_CONNECT_LED, OUTPUT);
digitalWrite(SERVER_CONNECT_LED, SERVER_CONNECT_ON); //signal device reboot
delay(100);
digitalWrite(SERVER_CONNECT_LED, SERVER_CONNECT_OFF);

if 1

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 = "Power.Active.Import,Energy.Active.Import.Register,Voltage,Current.Import,SoC,Temperature"; //example: update configuration value
ArduinoOcpp::configuration_save(); //write configs file back to flash immediately (not really necessary though)

endif

/*
 * You can use ArduinoOcpp's internal configurations store for credentials other than those which are
 * specified by OCPP. To use it before ArduinoOcpp is initialized, you need to call configuration_init()
 * 
 * This snippet also shows how to integrate a custom filesystem. Just subclass FilesystemAdapter and pass
 * it to the library
 */
    std::shared_ptr<ArduinoOcpp::FilesystemAdapter> filesystem = ArduinoOcpp::makeDefaultFilesystemAdapter(ArduinoOcpp::FilesystemOpt::Use_Mount_FormatOnFail);
    ArduinoOcpp::configuration_init(filesystem);
#if 1
    ArduinoOcpp::declareConfiguration<const char *>(
        "MeterValuesSampledData", "DEFAULT VALUE", CONFIGURATION_FN); //declare configuration and use the default value parameter (replace with required value)
    //ArduinoOcpp::configuration_save(); //again, not really necessary
#endif
/*
 * WiFiManager opens a captive portal, lets the user enter the WiFi credentials and provides a settings
 * page for the OCPP connection
 */
if (!runWiFiManager()) {
    //couldn't connect
    PRINTLN(F("[main] Couldn't connect to WiFi after multiple attempts"));
    delay(30000);
    ESP.restart();
}

std::shared_ptr<ArduinoOcpp::Configuration<const char *>> ocppUrl = ArduinoOcpp::declareConfiguration<const char *>(
    "ocppUrl", "", CONFIGURATION_FN, false, false, true, true);
std::shared_ptr<ArduinoOcpp::Configuration<const char *>> CA_cert = ArduinoOcpp::declareConfiguration<const char *>(
    "CA_cert", "", CONFIGURATION_FN, false, false, true, true);
std::shared_ptr<ArduinoOcpp::Configuration<const char *>> httpAuthentication = ArduinoOcpp::declareConfiguration<const char *>(
    "httpAuthentication", "", CONFIGURATION_FN, false, false, true, true);

String ocppUrlString = String(*ocppUrl);
if (!ocppUrlParsed.parse(ocppUrlString)) {
    PRINTLN(F("[main] Invalid OCPP URL. Restart."));
    delay(10000);
    ESP.restart();
}

PRINTF("[main] host, port, URL: %s, %hu, %s\n",
            ocppUrlParsed.host.isEmpty() ? "undefined" : ocppUrlParsed.host.c_str(),
            ocppUrlParsed.port,
            ocppUrlParsed.url.isEmpty()  ? "undefined" : ocppUrlParsed.url.c_str());

/*
 * Initialize ArduinoOcpp framework.
 */
wSock.setReconnectInterval(5000);
wSock.enableHeartbeat(15000, 3000, 2);

if (httpAuthentication->getBuffsize() > 1) {
    wSock.setAuthorization(*httpAuthentication);
}

if (ocppUrlParsed.isTLS) {
    if (CA_cert->getBuffsize() > 0) {
        //TODOS: ESP8266: limit BearSSL buffsize
        configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); //alternatively: settimeofday(&de, &tz);
        PRINT(F("[main] Wait for NTP time (used for certificate validation) "));
        time_t now = time(nullptr);
        while (now < 8 * 3600 * 2) {
            delay(500);
            PRINT('.');
            now = time(nullptr);
        }
        PRINTF(" finished. Unix timestamp is %lu\n", now);

        wSock.beginSslWithCA(ocppUrlParsed.host.c_str(), ocppUrlParsed.port, ocppUrlParsed.url.c_str(), *CA_cert, "ocpp1.6");
    } else {
        wSock.beginSSL(ocppUrlParsed.host.c_str(), ocppUrlParsed.port, ocppUrlParsed.url.c_str(), nullptr, "ocpp1.6");
    }
} else {
    wSock.begin(ocppUrlParsed.host, ocppUrlParsed.port, ocppUrlParsed.url, "ocpp1.6");
}

OCPP_initialize(oSock,
        230.f, //European grid voltage
        ArduinoOcpp::FilesystemOpt::Use_Mount_FormatOnFail);

/*
 * Integrate OCPP functionality. You can leave out the following part if your EVSE doesn't need it.
 */
setEnergyMeterInput([]() {
    //read the energy input register of the EVSE here and return the value in Wh
    /*
     * Approximated value. Replace with real reading
     */
    static ulong lastSampled = millis();
    static float energyMeter = 0.f;
    if (getTransactionId() > 0)
        energyMeter += ((float) (millis() - lastSampled)) * 0.003f; //increase by 0.003Wh per ms (~ 10.8kWh per h)
    lastSampled = millis();
    return energyMeter;
});

//!!!!!!!!!!!!!!!!!!!!!! Added new Energy Meter inputs By Mukesh !!!!!!!!!!!!!!!!!!!!!!!!!!! addMeterValueInput([](){ return 230; }, "Voltage", "V", nullptr, "L1", 1);

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

addMeterValueInput([] () {
        return (int32_t) 25;
    }, 
    "Temperature",
    "Celsius");

addMeterValueInput([] () {
        return (int32_t) 25;
    }, 
    "SoC",
    "Percent");

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /*

if defined(ESP32)

    ledcWrite(AMPERAGE_PIN, pwmVal);

elif defined(ESP8266)

    analogWrite(AMPERAGE_PIN, pwmVal);

endif

});

setEvReadyInput([]() {
    //return true if the EV is in state "Ready for charging" (see https://en.wikipedia.org/wiki/SAE_J1772#Control_Pilot)
    return digitalRead(EV_CHARGE_PIN) == EV_CHARGING;
});

addErrorCodeInput([] () {
    //Uncomment if Ground fault pin is used
    //if (digitalRead(EVSE_GROUND_FAULT_PIN) != EVSE_GROUND_CLEAR) {
    //    return "GroundFault";
    //}
    return (const char *) nullptr;
});

setOnResetSendConf([] (JsonObject confirmation) {
    if (getTransactionId() >= 0)
        stopTransaction();

    PRINTLN(F("[main] Execute reset command"));
    reboot_timestamp = millis();
    scheduleReboot = 5000; //reboot will be executed in loop()
    booted = false;
});

//... see ArduinoOcpp.h for more settings

/*
 * Notify the Central System that this station is ready
 */
auto evseDetailsDoc = std::unique_ptr<DynamicJsonDocument>(new DynamicJsonDocument(
    JSON_OBJECT_SIZE(5)
    + 5
    + 5
    + 5));
JsonObject evseDetails = evseDetailsDoc->to<JsonObject>();
evseDetails["chargePointModel"] = "MKB-AC001";
evseDetails["chargePointSerialNumber"] = "12345"; //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/218
evseDetails["chargePointVendor"] = "TestEV";
evseDetails["firmwareVersion"] = "0.0.1";
evseDetails["meterSerialNumber"] = "0.0.1";

//bootNotification("MKB-AC001", "TestEV Private Limited", [] (JsonObject response) {
bootNotification(std::move(evseDetailsDoc), [](JsonObject response) { //ArduinoOcpp will delete evseDetailsDoc
    if (response["status"].as<String>().equals("Accepted")) {
        booted = true;
        digitalWrite(SERVER_CONNECT_LED, SERVER_CONNECT_ON);
    } else {
        //Wait for the connection retry
        reboot_timestamp = millis();
        scheduleReboot = 60000; //wait for 60s until reboot; reboot will be executed in loop()
    }
});

}

void loop() {

/*
 * Do all OCPP stuff (process WebSocket input, send recorded meter values to Central System, etc.)
 */
OCPP_loop();

//NFC reader integration example
if (/* RFID chip detected? */ false) {
    const char *idTag = "0123456789A";//"my-id-tag"; //e.g. idTag = RFID.readIdTag(); //Mukesh
    authorize(idTag);
}

if (ocppPermitsCharge()) {
    //EVSE is in a charging session and charging is permitted by the OCPP server
    digitalWrite(OCPP_CHARGE_PERMISSION_PIN, OCPP_CHARGE_PERMITTED);
    digitalWrite(CHARGE_PERMISSION_LED, CHARGE_PERMISSION_ON);
} else {
    //Charging is not allowed due to OCPP rules
    digitalWrite(OCPP_CHARGE_PERMISSION_PIN, OCPP_CHARGE_FORBIDDEN);
    digitalWrite(CHARGE_PERMISSION_LED, CHARGE_PERMISSION_OFF);
}

if (scheduleReboot > 0 && millis() - reboot_timestamp >= scheduleReboot) {
    ESP.restart();
}

if (!booted) {
    return;
}

auto readEvPlugged = digitalRead(EV_PLUG_PIN);
if (evPlugged == EV_UNPLUGGED && readEvPlugged == EV_PLUGGED //transition from unplugged to plugged
            && getTransactionId() < 0  //no transaction yet
            && isOperative()) {        //EVSE is in operative mode
            PRINTF("In Start Transaction\n\r");
    startTransaction("0123456789A");//("my-id-tag");    //Mukesh
} else if (evPlugged == EV_PLUGGED && readEvPlugged == EV_UNPLUGGED //transition from plugged to unplugged
            && getTransactionId() >= 0) { //need to stop transaction
            PRINTF("In Stop Transaction\n\r");
    stopTransaction();
}
else if( digitalRead(KILL_TRANSACTION_PIN) == KILL_TRANSACTION_ON)
{
    PRINTF("In Kill Transaction\n\r");
    stopTransaction();  
}
evPlugged = readEvPlugged;

//... see ArduinoOcpp.h for more possibilities

}

// ### End of the OCPP integration. The following code integrates the // ### WiFi-Manager into this example sketch.

bool runWiFiManager() {

/*
 * Initialize WiFi and start captive portal to set connection credentials
 */ 
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP

std::shared_ptr<ArduinoOcpp::Configuration<const char *>> ocppUrl = ArduinoOcpp::declareConfiguration<const char *>(
    "ocppUrl", "", CONFIGURATION_FN, false, false, true, true);
std::shared_ptr<ArduinoOcpp::Configuration<const char *>> CA_cert = ArduinoOcpp::declareConfiguration<const char *>(
    "CA_cert", "", CONFIGURATION_FN, false, false, true, true);
std::shared_ptr<ArduinoOcpp::Configuration<const char *>> httpAuthentication = ArduinoOcpp::declareConfiguration<const char *>(
    "httpAuthentication", "", CONFIGURATION_FN, false, false, true, true);

WiFiManager wifiManager;
wifiManager.setTitle("EVSE configuration portal");
wifiManager.setParamsPage(true);
WiFiManagerParameter ocppUrlParam ("ocppUrl", "OCPP 1.6 Server URL + Charge Box ID", *ocppUrl, 150,"placeholder=\"wss://&lt;domain&gt;:&lt;port&gt;/&lt;path&gt;/&lt;chargeBoxId&gt;\"");
wifiManager.addParameter(&ocppUrlParam);

WiFiManagerParameter divider("<div><br/></div>");
wifiManager.addParameter(&divider);

WiFiManagerParameter caCertParam ("caCert", "CA Certificate", "", 1500,"placeholder=\"Paste here or leave blank\"");
wifiManager.addParameter(&caCertParam);
WiFiManagerParameter caCertSavePararm ("<div><label for='caCertSave' style='width: auto;'>Save new CA Certificate</label><input type='checkbox' name='caCertSave' value='1'  style='width: auto; margin-left: 10px; vertical-align: middle;'></div>");
wifiManager.addParameter(&caCertSavePararm);

WiFiManagerParameter httpAuthenticationParam ("httpAuthentication", "HTTP-authentication token", "", 150,"placeholder=\"e.g.: aKu0Q4NjMRC9yO3wRo08\"");
wifiManager.addParameter(&httpAuthenticationParam);
WiFiManagerParameter httpAuthenticationSavePararm ("<div><label for='httpAuthenticationSave' style='width: auto;'>Save new HTTP token</label><input type='checkbox' name='httpAuthenticationSave' value='1'  style='width: auto; margin-left: 10px; vertical-align: middle;'></div>");
wifiManager.addParameter(&httpAuthenticationSavePararm);

wifiManager.setSaveParamsCallback([&ocppUrlParam, ocppUrl, &wifiManager, CA_cert, &caCertParam, httpAuthentication, &httpAuthenticationParam] () {
    String newOcppUrl = String(ocppUrlParam.getValue());
    newOcppUrl.trim();
    Ocpp_URL newOcppUrlParsed = Ocpp_URL();
    if (newOcppUrlParsed.parse(newOcppUrl)) {
        //success
        *ocppUrl = newOcppUrl.c_str();
    }

    bool caCertSave = false;
    String caCertChangedParam = String ("caCertSave");
    if(wifiManager.server->hasArg(caCertChangedParam)) {
        String caCertChanged = String(wifiManager.server->arg(caCertChangedParam));
        if (caCertChanged.length() > 0) {
            caCertSave = caCertChanged.charAt(0) == '1' || caCertChanged.charAt(0) == 't' || caCertChanged.charAt(0) == 'o';
        }
    }
    if (caCertSave) {
        *CA_cert = caCertParam.getValue();
    }

    bool httpAuthenticationSave = false;
    String authChangedParam = String ("httpAuthenticationSave");
    if(wifiManager.server->hasArg(authChangedParam)) {
        String authChanged = String(wifiManager.server->arg(authChangedParam));
        if (authChanged.length() > 0) {
            httpAuthenticationSave = authChanged.charAt(0) == '1' || authChanged.charAt(0) == 't' || authChanged.charAt(0) == 'o';
        }
    }
    if (httpAuthenticationSave) {
        *httpAuthentication = httpAuthenticationParam.getValue();
    }
    ArduinoOcpp::configuration_save();
});

wifiManager.setDarkMode(true);

//wifiManager.setConfigPortalTimeout(CAPATITIVE_PORTAL_TIMEOUT / 1000); //if nobody logs in to the portal, continue after timeout 
wifiManager.setTimeout(CAPTIVE_PORTAL_TIMEOUT); //if nobody logs in to the portal, continue after timeout 
wifiManager.setConnectTimeout(WIFI_CONNECTION_TIMEOUT);
//wifiManager.setSaveConnect(true);
wifiManager.setAPClientCheck(true); // avoid timeout if client connected to softap
PRINTLN(F("[main] Start capatitive portal"));

if (wifiManager.startConfigPortal("EVSE-Config", "evse1234")) {
    return true;
} else {
    return wifiManager.autoConnect("EVSE-Config", "evse1234");
}

}

bool Ocpp_URL::parse(String &ocppUrl) { String inputUrl = String(ocppUrl); // wss://host.com:433/path inputUrl.trim();

if (ocppUrl.isEmpty()) {
    return false;
}
url = inputUrl;

inputUrl.toLowerCase();

if (inputUrl.startsWith("wss://")) {
    isTLS = true;
    port = 443;
} else if (inputUrl.startsWith("ws://")) {
    isTLS = false;
    port = 80;
} else {
    return false;
}
inputUrl = inputUrl.substring(inputUrl.indexOf("://") + strlen("://")); // host.com:433/path
if (inputUrl.isEmpty()) {
    return false;
}

host = String('\0');
for (uint i = 0; i < inputUrl.length(); i++) {
    if (inputUrl.charAt(i) == ':') { //case host.com:433/path
        host = inputUrl.substring(0, i);
        uint16_t inputPort = 0;
        for (unsigned int j = i + 1; j < inputUrl.length(); j++) {
            if (isDigit(inputUrl.charAt(j))) {
                inputPort *= (uint16_t) 10;
                inputPort += inputUrl.charAt(j) - '0';
            } else {
                break;
            }
        }
        if (inputPort > 0) {
            port = inputPort;
        }
        break;
    } else if (inputUrl.charAt(i) == '/') { //case host.com/path
        host = inputUrl.substring(0, i);
        break;
    }
}
if (host.isEmpty()) {
    host = inputUrl;
}

return true;

} `

Fareed99 commented 1 year ago

@matth-x @piyush9999 I followed the above discussion to implement multiple connectors. Is there a way to call startTransaction and stopTransaction functions for a specific connector? I'm aware the connectorId can be chosen from RemoteStartTransaction and RemoteStopTransaction but is there a way to do it with startTransaction and stopTransaction?

piyush9999 commented 1 year ago

Hello @Fareed99 you can try by giving a separate IDTAG, this should work

Fareed99 commented 1 year ago

Hey @piyush9999 thanks for your reply. startTransaction and stopTransaction do not have the connectorId paramter. So whenever I call startTransaction, it starts a transaction on connector 1 but I also need to be able to start and stop transactions on connectors 2 and onwards. @piyush9999 @matth-x Please shed some light on this, I would be grateful. Thanks!

Navjot0005 commented 1 year ago

@matth-x Hi hope you are good. I am working on this lib and everything is ok till now. However, I want to send the RFID to Steve pls can you or anyone tell me how can I do this??

piyush9999 commented 1 year ago

`if (/ RFID chip detected? / false) { String idTag = "0123456789ABCD"; //e.g. idTag = RFID.readIdTag();

    if (!getTransaction()) {
        //no transaction running or preparing. Begin a new transaction
        Serial.printf("[main] Begin Transaction with idTag %s\n", idTag.c_str());

        /*
         * Begin Transaction. The OCPP lib will prepare transaction by checking the Authorization
         * and listen to the ConnectorPlugged Input. When the Authorization succeeds and an EV
         * is plugged, the OCPP lib will send the StartTransaction
         */
        auto ret = beginTransaction(idTag.c_str());

        if (ret) {
            Serial.println(F("[main] Transaction initiated. OCPP lib will send a StartTransaction when" \
                             "ConnectorPlugged Input becomes true and if the Authorization succeeds"));
        } else {
            Serial.println(F("[main] No transaction initiated"));
        }

` After reading the tag i.e idTag it will compare the tag you added on the server,

Navjot0005 commented 1 year ago

Thanks for the help @piyush9999 .. Right now I am reading the tag and then copying this to the 32-bit variable. but the thing is I could not send the read id tag to Steve. Will it send the "idTag = "0123456789ABCD"; to the steve server ?? Or how Can I send the RFID tag to steve?? Thanks for reply.

piyush9999 commented 1 year ago

Don't send 0123456789ABCD, add the rfid to the server first, for more comfort make it as parent idtag, make String idtag = RFID.readIdTag();

Navjot0005 commented 1 year ago

Hi @piyush9999. Thanks again for guiding. Actually Can you tell me how I can send the value because in my case it is required to send the read rfid tag to steve. Also one thing more I want to add in this. Like if load not connected then it send reject msg to steve and relays gets off.