public string HandleBootNotification(OCPPMessage msgIn, OCPPMessage msgOut)
        {
            string errorCode  = null;
            string bootReason = null;

            try
            {
                Logger.LogTrace("Processing boot notification...");
                BootNotificationRequest bootNotificationRequest = JsonConvert.DeserializeObject <BootNotificationRequest>(msgIn.JsonPayload);
                Logger.LogTrace("BootNotification => Message deserialized");

                bootReason = bootNotificationRequest?.Reason.ToString();
                Logger.LogInformation("BootNotification => Reason={0}", bootReason);

                BootNotificationResponse bootNotificationResponse = new BootNotificationResponse();
                bootNotificationResponse.CurrentTime = DateTimeOffset.UtcNow;
                bootNotificationResponse.Interval    = 300; // 300 seconds

                bootNotificationResponse.StatusInfo                = new StatusInfoType();
                bootNotificationResponse.StatusInfo.ReasonCode     = string.Empty;
                bootNotificationResponse.StatusInfo.AdditionalInfo = string.Empty;

                bootNotificationResponse.CustomData          = new CustomDataType();
                bootNotificationResponse.CustomData.VendorId = VendorId;

                if (ChargePointStatus != null)
                {
                    // Known charge station => accept
                    bootNotificationResponse.Status = RegistrationStatusEnumType.Accepted;
                }
                else
                {
                    // Unknown charge station => reject
                    bootNotificationResponse.Status = RegistrationStatusEnumType.Rejected;
                }

                msgOut.JsonPayload = JsonConvert.SerializeObject(bootNotificationResponse);
                Logger.LogTrace("BootNotification => Response serialized");
            }
            catch (Exception exp)
            {
                Logger.LogError(exp, "BootNotification => Exception: {0}", exp.Message);
                errorCode = ErrorCodes.FormationViolation;
            }

            WriteMessageLog(ChargePointStatus.Id, null, msgIn.Action, bootReason, errorCode);
            return(errorCode);
        }
        public string HandleBootNotification(OCPPMessage msgIn, OCPPMessage msgOut)
        {
            string errorCode = null;

            try
            {
                Logger.LogTrace("Processing boot notification...");
                BootNotificationRequest bootNotificationRequest = JsonConvert.DeserializeObject <BootNotificationRequest>(msgIn.JsonPayload);
                Logger.LogTrace("BootNotification => Message deserialized");

                BootNotificationResponse bootNotificationResponse = new BootNotificationResponse();
                bootNotificationResponse.CurrentTime = DateTimeOffset.UtcNow;
                bootNotificationResponse.Interval    = 300; // 300 seconds

                if (ChargePointStatus != null)
                {
                    // Known charge station => accept
                    bootNotificationResponse.Status = BootNotificationResponseStatus.Accepted;
                }
                else
                {
                    // Unknown charge station => reject
                    bootNotificationResponse.Status = BootNotificationResponseStatus.Rejected;
                }

                msgOut.JsonPayload = JsonConvert.SerializeObject(bootNotificationResponse);
                Logger.LogTrace("BootNotification => Response serialized");
            }
            catch (Exception exp)
            {
                Logger.LogError(exp, "BootNotification => Exception: {0}", exp.Message);
                errorCode = ErrorCodes.FormationViolation;
            }

            WriteMessageLog(ChargePointStatus.Id, null, msgIn.Action, null, errorCode);
            return(errorCode);
        }
예제 #3
0
        /// <summary>
        /// Process all text messages of this web socket API.
        /// </summary>
        /// <param name="RequestTimestamp">The timestamp of the request.</param>
        /// <param name="Connection">The web socket connection.</param>
        /// <param name="EventTrackingId">The event tracking identification.</param>
        /// <param name="CancellationToken">The cancellation token.</param>
        /// <param name="TextMessage">The received text message.</param>
        protected async Task <WebSocketTextMessageRespose> ProcessTextMessages(DateTime RequestTimestamp,
                                                                               WebSocketConnection Connection,
                                                                               EventTracking_Id EventTrackingId,
                                                                               CancellationToken CancellationToken,
                                                                               String TextMessage)
        {
            JArray         JSON         = null;
            WSErrorMessage ErrorMessage = null;

            try
            {
                JSON = JArray.Parse(TextMessage?.Trim());

                #region MessageType 2: CALL       (Client-to-Server)

                // [
                //     2,                         // MessageType: CALL (Client-to-Server)
                //    "19223201",                 // RequestId
                //    "BootNotification",         // Action
                //    {
                //        "chargePointVendor": "VendorX",
                //        "chargePointModel":  "SingleSocketCharger"
                //    }
                // ]

                if (JSON.Count == 4 &&
                    JSON[0].Type == JTokenType.Integer &&
                    JSON[0].Value <Byte>() == 2 &&
                    JSON[1].Type == JTokenType.String &&
                    JSON[2].Type == JTokenType.String &&
                    JSON[3].Type == JTokenType.Object)
                {
                    #region Initial checks

                    var RequestId   = JSON[1].Value <String>()?.Trim();
                    var Action      = JSON[2].Value <String>()?.Trim();
                    var RequestData = JSON[3].Value <JObject>();

                    if (RequestId.IsNullOrEmpty())
                    {
                        ErrorMessage = new WSErrorMessage(
                            RequestId,
                            WSErrorCodes.ProtocolError,
                            "The given 'request identification' must not be null or empty!",
                            new JObject(
                                new JProperty("request", TextMessage)
                                ));
                    }

                    else if (Action.IsNullOrEmpty())
                    {
                        ErrorMessage = new WSErrorMessage(
                            RequestId,
                            WSErrorCodes.ProtocolError,
                            "The given 'action' must not be null or empty!",
                            new JObject(
                                new JProperty("request", TextMessage)
                                ));
                    }

                    #endregion

                    else
                    {
                        JObject OCPPResponseJSON = null;

                        switch (Action)
                        {
                            #region BootNotification

                        case "BootNotification":
                        {
                            #region Send OnBootNotificationWSRequest event

                            try
                            {
                                //OnBootNotificationSOAPRequest?.Invoke(DateTime.UtcNow,
                                //                                      SOAPServer.HTTPServer,
                                //                                      Request);
                            }
                            catch (Exception e)
                            {
                                e.Log(nameof(CentralSystemSOAPServer) + "." + nameof(OnBootNotificationSOAPRequest));
                            }

                            #endregion

                            BootNotificationResponse response = null;

                            try
                            {
                                if (BootNotificationRequest.TryParse(RequestData,
                                                                     out BootNotificationRequest bootNotificationRequest))
                                {
                                    #region Send OnBootNotificationRequest event

                                    try
                                    {
                                        OnBootNotificationRequest?.Invoke(bootNotificationRequest.RequestTimestamp,
                                                                          this,
                                                                          EventTrackingId,

                                                                          ChargeBox_Id.Parse("123"),        //OCPPHeader.ChargeBoxIdentity,

                                                                          bootNotificationRequest.ChargePointVendor,
                                                                          bootNotificationRequest.ChargePointModel,
                                                                          bootNotificationRequest.ChargePointSerialNumber,
                                                                          bootNotificationRequest.ChargeBoxSerialNumber,
                                                                          bootNotificationRequest.FirmwareVersion,
                                                                          bootNotificationRequest.Iccid,
                                                                          bootNotificationRequest.IMSI,
                                                                          bootNotificationRequest.MeterType,
                                                                          bootNotificationRequest.MeterSerialNumber);
                                    }
                                    catch (Exception e)
                                    {
                                        e.Log(nameof(CentralSystemSOAPServer) + "." + nameof(OnBootNotificationRequest));
                                    }

                                    #endregion

                                    #region Call async subscribers

                                    if (response == null)
                                    {
                                        var results = OnBootNotification?.
                                                      GetInvocationList()?.
                                                      SafeSelect(subscriber => (subscriber as BootNotificationDelegate)
                                                                     (DateTime.UtcNow,
                                                                     this,
                                                                     CancellationToken,
                                                                     EventTrackingId,
                                                                     ChargeBox_Id.Parse("123"),   //OCPPHeader.ChargeBoxIdentity,
                                                                     bootNotificationRequest)).
                                                      ToArray();

                                        if (results?.Length > 0)
                                        {
                                            await Task.WhenAll(results);

                                            response = results.FirstOrDefault()?.Result;
                                        }

                                        if (results == null || response == null)
                                        {
                                            response = BootNotificationResponse.Failed(bootNotificationRequest);
                                        }
                                    }

                                    #endregion

                                    #region Send OnBootNotificationResponse event

                                    try
                                    {
                                        OnBootNotificationResponse?.Invoke(response.ResponseTimestamp,
                                                                           this,
                                                                           EventTrackingId,

                                                                           ChargeBox_Id.Parse("123"),        //OCPPHeader.ChargeBoxIdentity,

                                                                           bootNotificationRequest.ChargePointVendor,
                                                                           bootNotificationRequest.ChargePointModel,
                                                                           bootNotificationRequest.ChargePointSerialNumber,
                                                                           bootNotificationRequest.ChargeBoxSerialNumber,
                                                                           bootNotificationRequest.FirmwareVersion,
                                                                           bootNotificationRequest.Iccid,
                                                                           bootNotificationRequest.IMSI,
                                                                           bootNotificationRequest.MeterType,
                                                                           bootNotificationRequest.MeterSerialNumber,

                                                                           response.Result,
                                                                           response.Status,
                                                                           response.CurrentTime,
                                                                           response.Interval,
                                                                           response.Runtime);
                                    }
                                    catch (Exception e)
                                    {
                                        e.Log(nameof(CentralSystemSOAPServer) + "." + nameof(OnBootNotificationResponse));
                                    }

                                    #endregion

                                    OCPPResponseJSON = response.ToJSON();
                                }

                                else
                                {
                                    ErrorMessage = new WSErrorMessage(RequestId,
                                                                      WSErrorCodes.FormationViolation,
                                                                      "The given 'BootNotification' request could not be parsed!",
                                                                      new JObject(
                                                                          new JProperty("request", TextMessage)
                                                                          ));
                                }
                            }
                            catch (Exception e)
                            {
                                ErrorMessage = new WSErrorMessage(RequestId,
                                                                  WSErrorCodes.FormationViolation,
                                                                  "Processing the given 'BootNotification' request led to an exception!",
                                                                  new JObject(
                                                                      new JProperty("request", TextMessage),
                                                                      new JProperty("exception", e.Message),
                                                                      new JProperty("stacktrace", e.StackTrace)
                                                                      ));
                            }


                            #region Send OnBootNotificationWSResponse event

                            try
                            {
                                //OnBootNotificationSOAPResponse?.Invoke(HTTPResponse.Timestamp,
                                //                                        SOAPServer.HTTPServer,
                                //                                        Request,
                                //                                        HTTPResponse);
                            }
                            catch (Exception e)
                            {
                                e.Log(nameof(CentralSystemSOAPServer) + "." + nameof(OnBootNotificationSOAPResponse));
                            }

                            #endregion
                        }
                        break;

                            #endregion
                        }


                        if (OCPPResponseJSON != null)
                        {
                            return(new WebSocketTextMessageRespose(RequestTimestamp,
                                                                   TextMessage,
                                                                   DateTime.UtcNow,
                                                                   new WSResponseMessage(WSMessageTypes.CALLRESULT,
                                                                                         RequestId,
                                                                                         OCPPResponseJSON).ToJSON().ToString()));
                        }
                    }
                }

                #endregion

                #region MessageType 3: CALLRESULT (Server-to-Client)

                // [
                //     3,                         // MessageType: CALLRESULT (Server-to-Client)
                //    "19223201",                 // RequestId copied from request
                //    {
                //        "status":            "Accepted",
                //        "currentTime":       "2013-02-01T20:53:32.486Z",
                //        "heartbeatInterval":  300
                //    }
                // ]

                else if (JSON.Count == 3 &&
                         JSON[0].Type == JTokenType.Integer &&
                         JSON[0].Value <Byte>() == 3 &&
                         JSON[1].Type == JTokenType.String &&
                         JSON[2].Type == JTokenType.Object)
                {
                }

                #endregion

                #region MessageType 4: CALLERROR  (Server-to-Client)

                // [
                //     4,                         // MessageType: CALLERROR (Server-to-Client)
                //    "19223201",                 // RequestId from request
                //    "<errorCode>",
                //    "<errorDescription>",
                //    {
                //        <errorDetails>
                //    }
                // ]

                // Error Code                    Description
                // -----------------------------------------------------------------------------------------------
                // NotImplemented                Requested Action is not known by receiver
                // NotSupported                  Requested Action is recognized but not supported by the receiver
                // InternalError                 An internal error occurred and the receiver was not able to process the requested Action successfully
                // ProtocolError                 Payload for Action is incomplete
                // SecurityError                 During the processing of Action a security issue occurred preventing receiver from completing the Action successfully
                // FormationViolation            Payload for Action is syntactically incorrect or not conform the PDU structure for Action
                // PropertyConstraintViolation   Payload is syntactically correct but at least one field contains an invalid value
                // OccurenceConstraintViolation  Payload for Action is syntactically correct but at least one of the fields violates occurence constraints
                // TypeConstraintViolation       Payload for Action is syntactically correct but at least one of the fields violates data type constraints (e.g. “somestring”: 12)
                // GenericError                  Any other error not covered by the previous ones

                else if (JSON.Count == 5 &&
                         JSON[0].Type == JTokenType.Integer &&
                         JSON[0].Value <Byte>() == 4 &&
                         JSON[1].Type == JTokenType.String &&
                         JSON[2].Type == JTokenType.String &&
                         JSON[3].Type == JTokenType.String &&
                         JSON[4].Type == JTokenType.Object)
                {
                }

                #endregion

                else
                {
                    ErrorMessage = new WSErrorMessage(JSON.Count >= 2 ? JSON[1].Value <String>()?.Trim() : "unknown",
                                                      WSErrorCodes.FormationViolation,
                                                      "The given OCPP request message is invalid!",
                                                      new JObject(
                                                          new JProperty("request", TextMessage)
                                                          ));
                }
            }
            catch (Exception e)
            {
                ErrorMessage = new WSErrorMessage(JSON != null && JSON.Count >= 2
                                                      ? JSON?[1].Value <String>()?.Trim()
                                                      : "Unknown request identification",
                                                  WSErrorCodes.FormationViolation,
                                                  "Processing the given OCPP request message led to an exception!",
                                                  new JObject(
                                                      new JProperty("request", TextMessage),
                                                      new JProperty("exception", e.Message),
                                                      new JProperty("stacktrace", e.StackTrace)
                                                      ));
            }

            return(new WebSocketTextMessageRespose(RequestTimestamp,
                                                   TextMessage,
                                                   DateTime.UtcNow,
                                                   ErrorMessage.ToJSON().ToString()));
        }