ChargeTimeEU / Java-OCA-OCPP

Open source client and server library of Open Charge-Point Protocol (OCPP) defined by openchargealliance.org (OCA)
MIT License
272 stars 174 forks source link

Testing with Steve #37

Closed victormunoz closed 6 years ago

victormunoz commented 6 years ago

I am trying to use this project as a chargepoint simulator to make tests with a central system that is running with Steve, now that it supports OCPP 1.6 (https://github.com/RWTH-i5-IDSG/steve). But I haven't succeded on receiving any message in the Steve central system, neither using SOAP nor JSON types.

I have created a very basic main app that simply starts a chargepoint:

FakeChargePoint chargePoint = new FakeChargePoint();
chargePoint.connect();
chargePoint.sendBootNotification("A", "B");
chargePoint.sendHeartbeatRequest();

And in the constructor of the FakeChargePoint class I have changed the url to the ones that are provided by steve once it is started:

switch (type) {
            case JSON:
                client = new JSONClient(core, "testdummy");
                url = "ws://192.168.1.7:9220/steve/websocket/CentralSystemService/testdummy";
                break;
            case SOAP:
                client = new SOAPClient("me", new URL("http://127.0.0.1:8889"), core);
                url = "http://192.168.1.7:9220/steve/services/CentralSystemService";
                break;
        }

This code compiles and executes without problems or error messages. However, the Steve central system does not seem to be receiving anything at all from the chargepoint.

What is missing?

TVolden commented 6 years ago

Hi Victormunoz,

Now that sounds like an interesting project.

It may have no effect, but I can see you assign a client name to the json client, but also have it included in the url. Have you tried to debug it step by step to see if it connects? Maybe add some useful output in the event methods?

goekay commented 6 years ago

related issue in our project: https://github.com/RWTH-i5-IDSG/steve/issues/53

i also looked at this issue. there are two problems:

edit: per spec, "The exact OCPP version MUST be specified in the Sec-Websocket-Protocol field."

edit2: you should have seen the exception in the logs of steve: "org.springframework.web.socket.server.HandshakeFailureException: No protocol (OCPP version) is specified."

TVolden commented 6 years ago

Now that's a bug. Let me check.

goekay commented 6 years ago

i think, the problem lies in the OcppDraft.

first of all, the methods postProcessHandshakeRequestAsClient and postProcessHandshakeResponseAsServer call themselves and create an infinite recursion. i guess, you want to call the super method, but the super. prefix is missing.

on the other hand, you shouldn't set the Sec-WebSocket-Protocol this way anyways. if you look at the Draft_6455, the impl is actually complete enough to set protocols and deal with them etc.

you should only call its constructor by setting the wanted protocol, like:

public OcppDraft() {
    super(Collections.emptyList(), Collections.singletonList(new Protocol("ocpp1.6")));
}

but, i am not familiar with the code base and this is my observation after looking at the code for a few minutes. i hope it helps.

edit: when you call the super constructor like that, you do not need to override these two methods anymore.

TVolden commented 6 years ago

Thanks for your input, and you're absolutely right. Luckily a debug showed that they don't get called.

I reverted some PR some time ago that aimed to fix this, I'll reintroduce some of it when I have time. https://github.com/ChargeTimeEU/Java-OCA-OCPP/pull/33

Thanks for your help, I really appreciate it.

V2G-UK commented 6 years ago

Not that I have anything to add re the "bug" at the moment, but SteVe does indeed look like an interesting project since apparently it supports OCPP 1.6J.

It was searching for an open source 1.6J "server" that led me here in the first place.

TVolden commented 6 years ago

@V2G-UK you're not the only one.

TVolden commented 6 years ago

I have reintroduced the Sec-Websocket-Protocol part. Please check if it works.

V2G-UK commented 6 years ago

After some more Eclipse fun & games I have managed to achieve the following, which I guess counts as "it works"? selection_999 435

goekay commented 6 years ago

yes, the received heartbeat and the fact that there is one ocpp 1.6j charging station that is connected to steve are indicators that it is working.

victormunoz commented 6 years ago

I have tested the updated code. It now works correctly, but only if the chargepoint id has been previously added manually with steve (in the chargepoint section, "add new"). This behavior is different from a real chargepoint (at least from the one that I have), because when I restart the chargepoint, steve receives its Boot Notification even if it is not present in the chargepoints section. Do you have any idea of what can be missing?

goekay commented 6 years ago

the behaviour is correct. i fail to see where the problem is.

victormunoz commented 6 years ago

I should explain me better. I have modified the steve source code, so that when a BootNotification is received, the chargebox is automatically added to the database (a kind of plug-n-play). I have modified the function CentralSystemService16_Service/bootNotification. This works fine with real chargeboxes. They send the Boot Notification on startup, steve receives it, my code is then executed and adds the chargebox to the database, and then any other message sent after is processed correctly.

But with this simulator, for some reason, the Boot Notification is not received in steve (therefore my code does not add the chargebox to the database, and so on), unless I add the simulator id to steve manually. There must be something different in these two cases, but can't find what.

goekay commented 6 years ago

are you using the ChargePoint in JSON mode?

victormunoz commented 6 years ago

Yes. Actually it gives me an exception with SOAP: Exception in thread "Thread-4" Exception in thread "Thread-5" Exception in thread "Thread-6" Exception in thread "Thread-7" java.lang.NullPointerException at eu.chargetime.ocpp.SOAPCommunicator$SOAPParser.(SOAPCommunicator.java:250) at eu.chargetime.ocpp.SOAPCommunicator.parse(SOAPCommunicator.java:234) at eu.chargetime.ocpp.Communicator$EventHandler.receivedMessage(Communicator.java:237) at eu.chargetime.ocpp.WebServiceTransmitter.lambda$sendRequest$0(WebServiceTransmitter.java:84) at eu.chargetime.ocpp.WebServiceTransmitter$$Lambda$3/1543237999.run(Unknown Source) at java.lang.Thread.run(Thread.java:745)

goekay commented 6 years ago

i cannot explain the exception with SOAP, @TVolden should look into it.

in case of JSON, as I have said "steve can only accept or reject WebSocket connection attempts based on their id being in the database or not". the phrasing of this sentence was deliberate and not a mistake. the decision to accept a WebSocket connection attempt happens somewhere else in the code, here.

a BootNotification can only arrive if the WebSocket connection is established. if you did not modify the part that i highlighted above, you should see exception like:

HandshakeFailureException("ChargeBoxId '" + chargeBoxId + "' is not registered")
V2G-UK commented 6 years ago

Victor,

SteVe works fine for me when using WS/JSON as described by Sevket.

If you modify SteVe then you're on your own! Unless Sevket graciously offers to help of course?

Jim

victormunoz commented 6 years ago

Thank you very much @goekay I certainly did not get the point in your sentence about the websocket. Now everything makes sense and it is working like a charm. I am going to close this issue.

Regarding the exception with SOAP, I will investigate further before raising a new issue. Thanks again!