lorenzodonini / ocpp-go

Open Charge Point Protocol implementation in Go
MIT License
262 stars 125 forks source link

updateStatus needs timestamp parameter #20

Closed DerArtem closed 4 years ago

DerArtem commented 4 years ago

I have tried to register ocpp-go to the Steve OCPP backend.

Currently the registration fails as Steve needs a valid timestamp:

` [INFO ] 2020-07-01 10:34:31,150 de.rwth.idsg.steve.ocpp.ws.WebSocketLogger - [chargeBoxId=AM1, sessionId=7e7b0364-fa2e-9836-6a96-60c7a2cfabc3] Received: [2,"2854263694","StatusNotification",{"connectorId":0,"errorCode":"NoError","status" :"Available","timestamp":"0001-01-01T00:00:00Z"}]

[ERROR] 2020-07-01 10:34:31,298 de.rwth.idsg.steve.ocpp.ws.ocpp16.Ocpp16WebSocketEndpoint$Ocpp16CallHandler - Exception occurred org.jooq.exception.DataAccessException: SQL [insert into stevedb.connector_status (connector_pk, status_timestamp, status, error_code, error_info, vendor_id, vendor_error_code) values ((select stevedb.connector.con nector_pk from stevedb.connector where (stevedb.connector.charge_box_id = ? and stevedb.connector.connector_id = ?)), ?, ?, ?, ?, ?, ?)]; Data truncation: Incorrect datetime value: '0001-01-03 00:00:00' for column steve db.connector_status.status_timestamp at row 1 `

lorenzodonini commented 4 years ago

Thanks for finding this.

According to OCPP 1.6 specifications, the timestamp field is optional. In my implementation it currently uses a "zero" timestamp in case the value isn't set, which is definitely a bug and will be solved by making it a pointer. Will work on the fix asap.

There is also the option of setting a default value when initializing the struct, but this could cause inconsistencies in case the created message isn't sent right away, so I'd rather avoid that.

The easy fix for you right now is to explicitly send the timestamp in the request:

request.Timestamp = types.DateTime{Time: time.Now()}
lorenzodonini commented 4 years ago

@DerArtem It would be nice if you could test the linked pull request and let me know, whether the problem is solved.

DerArtem commented 4 years ago

Yes, it works. Now the StatusNotification is send without a timestamp.

But how to set a timestamp manually now? I think a timestamp variable should be added to the StatusNotification function.

lorenzodonini commented 4 years ago

The updateStatus you see in the example is just a helper function, you don't necessarily have to use it.

Check out the implementation of that function here.

Normally, to send a StatusNotification with optional parameters you would do this:

statusConfirmation, err := chargePoint.StatusNotification(connector, stateHandler.errorCode, status, func(request *core.StatusNotificationRequest) {
    request.Timestamp = types.NewDateTime(time.Now())
})
// Check for error and confirmation

It works the same for every request in which you want to pass optional parameters.

lorenzodonini commented 4 years ago

@DerArtem I quickly added the same functionality to updateStatus, so you can now invoke it like this:

updateStatus(stateHandler, 0, core.ChargePointStatusAvailable, func(request *core.StatusNotificationRequest) {
    request.Timestamp = types.NewDateTime(time.Now())
})

Let me know if this works for you, then I can merge the fix.

DerArtem commented 4 years ago

Yes, this looks great. Thanks!