/// <summary> /// Sends a Unlock-Request to the chargepoint /// </summary> private async Task UnlockConnector16(ChargePointStatus chargePointStatus, HttpContext apiCallerContext) { ILogger logger = _logFactory.CreateLogger("OCPPMiddleware.OCPP16"); ControllerOCPP16 controller16 = new ControllerOCPP16(_configuration, _logFactory, chargePointStatus); Messages_OCPP16.UnlockConnectorRequest unlockConnectorRequest = new Messages_OCPP16.UnlockConnectorRequest(); unlockConnectorRequest.ConnectorId = 0; string jsonResetRequest = JsonConvert.SerializeObject(unlockConnectorRequest); OCPPMessage msgOut = new OCPPMessage(); msgOut.MessageType = "2"; msgOut.Action = "UnlockConnector"; msgOut.UniqueId = Guid.NewGuid().ToString("N"); msgOut.JsonPayload = jsonResetRequest; msgOut.TaskCompletionSource = new TaskCompletionSource <string>(); // store HttpContext with MsgId for later answer processing (=> send anwer to API caller) _requestQueue.Add(msgOut.UniqueId, msgOut); // Send OCPP message with optional logging/dump await SendOcpp16Message(msgOut, logger, chargePointStatus.WebSocket); // Wait for asynchronous chargepoint response and processing string apiResult = await msgOut.TaskCompletionSource.Task; // apiCallerContext.Response.StatusCode = 200; apiCallerContext.Response.ContentType = "application/json"; await apiCallerContext.Response.WriteAsync(apiResult); }
/// <summary> /// Waits for new OCPP V1.6 messages on the open websocket connection and delegates processing to a controller /// </summary> private async Task Receive16(ChargePointStatus chargePointStatus, HttpContext context) { ILogger logger = _logFactory.CreateLogger("OCPPMiddleware.OCPP16"); ControllerOCPP16 controller16 = new ControllerOCPP16(_configuration, _logFactory, chargePointStatus); byte[] buffer = new byte[1024 * 4]; MemoryStream memStream = new MemoryStream(buffer.Length); while (chargePointStatus.WebSocket.State == WebSocketState.Open) { WebSocketReceiveResult result = await chargePointStatus.WebSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); if (result != null && result.MessageType != WebSocketMessageType.Close) { logger.LogTrace("OCPPMiddleware.Receive16 => Receiving segment: {0} bytes (EndOfMessage={1} / MsgType={2})", result.Count, result.EndOfMessage, result.MessageType); memStream.Write(buffer, 0, result.Count); if (result.EndOfMessage) { // read complete message into byte array byte[] bMessage = memStream.ToArray(); // reset memory stream für next message memStream = new MemoryStream(buffer.Length); string dumpDir = _configuration.GetValue <string>("MessageDumpDir"); if (!string.IsNullOrWhiteSpace(dumpDir)) { string path = Path.Combine(dumpDir, string.Format("{0}_ocpp16-in.txt", DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss-ffff"))); try { // Write incoming message into dump directory File.WriteAllBytes(path, bMessage); } catch (Exception exp) { logger.LogError(exp, "OCPPMiddleware.Receive16 => Error dumping incoming message to path: '{0}'", path); } } string ocppMessage = UTF8Encoding.UTF8.GetString(bMessage); Match match = Regex.Match(ocppMessage, MessageRegExp); if (match != null && match.Groups != null && match.Groups.Count >= 3) { string messageTypeId = match.Groups[1].Value; string uniqueId = match.Groups[2].Value; string action = match.Groups[3].Value; string jsonPaylod = match.Groups[4].Value; logger.LogInformation("OCPPMiddleware.Receive16 => OCPP-Message: Type={0} / ID={1} / Action={2})", messageTypeId, uniqueId, action); OCPPMessage msgIn = new OCPPMessage(messageTypeId, uniqueId, action, jsonPaylod); if (msgIn.MessageType == "2") { // Request from chargepoint to OCPP server OCPPMessage msgOut = controller16.ProcessRequest(msgIn); // Send OCPP message with optional logging/dump await SendOcpp16Message(msgOut, logger, chargePointStatus.WebSocket); } else if (msgIn.MessageType == "3" || msgIn.MessageType == "4") { // Process answer from chargepoint if (_requestQueue.ContainsKey(msgIn.UniqueId)) { controller16.ProcessAnswer(msgIn, _requestQueue[msgIn.UniqueId]); _requestQueue.Remove(msgIn.UniqueId); } else { logger.LogError("OCPPMiddleware.Receive16 => HttpContext from caller not found / Msg: {0}", ocppMessage); } } else { // Unknown message type logger.LogError("OCPPMiddleware.Receive16 => Unknown message type: {0} / Msg: {1}", msgIn.MessageType, ocppMessage); } } else { logger.LogWarning("OCPPMiddleware.Receive16 => Error in RegEx-Matching: Msg={0})", ocppMessage); } } } else { logger.LogInformation("OCPPMiddleware.Receive16 => WebSocket Closed: CloseStatus={0} / MessageType={1}", result?.CloseStatus, result?.MessageType); await chargePointStatus.WebSocket.CloseOutputAsync((WebSocketCloseStatus)3001, string.Empty, CancellationToken.None); } } logger.LogInformation("OCPPMiddleware.Receive16 => Websocket closed: State={0} / CloseStatus={1}", chargePointStatus.WebSocket.State, chargePointStatus.WebSocket.CloseStatus); ChargePointStatus dummy; _chargePointStatusDict.Remove(chargePointStatus.Id, out dummy); }