matth-x / MicroOcpp

OCPP 1.6 client for microcontrollers
MIT License
330 stars 140 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 11 months 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 11 months 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 11 months 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 11 months 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 11 months 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.