using Evcb.Domain.Model; using Evcb.Repository; using Evcb.Service; using SuperSocket.Common; using SuperWebSocket; using SuperWebSocket.SubProtocol; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace OCPPServer.Protocol { public class OCPPWSServer : WebSocketServer { /// /// 可允許連線Clinet數 /// public int connectNum { get; set; } /// /// 是否限制連線Clinet數 /// public bool beConnectLimit { get; set; } /// /// Initializes a new instance of the class. /// /// The sub protocols. public OCPPWSServer(IEnumerable> subProtocols) : base(subProtocols) { } /// /// Initializes a new instance of the class. /// /// The sub protocol. public OCPPWSServer(ISubProtocol subProtocol) : base(subProtocol) { } /// /// Initializes a new instance of the class. /// public OCPPWSServer() : base(new List>()) { } protected override bool ValidateHandshake(ClientData session, string origin) { //初始化ClientData session.InitialPileData(); //確認電樁所送的電樁識別碼是否包含在request path中 string[] words = session.Path.Split('/'); using (var db = new PhihongDbContext()) { if (this.beConnectLimit == true) { var connectPile = db.Machine.Where(c => c.Online == true).ToList(); if (connectPile.Count >= this.connectNum) { byte[] m_SwitchResponse; var responseBuilder = new StringBuilder(); responseBuilder.AppendWithCrCf("HTTP/1.1 403"); //403 Forbidden : 用戶端並無訪問權限,所以伺服器給予應有的回應。 responseBuilder.AppendWithCrCf("Upgrade: WebSocket"); responseBuilder.AppendWithCrCf("Connection: Upgrade"); responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion); responseBuilder.AppendWithCrCf(); m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString()); session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length); return false; } } IUnitOfWork uow = new UnitOfWork(db); IMachineService machineSrv = new MachineService(uow); var machine = machineSrv.GetByCustomId(words.Last()); if (machine == null) { byte[] m_SwitchResponse; var responseBuilder = new StringBuilder(); responseBuilder.AppendWithCrCf("HTTP/1.1 404"); responseBuilder.AppendWithCrCf("Upgrade: WebSocket"); responseBuilder.AppendWithCrCf("Connection: Upgrade"); responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion); responseBuilder.AppendWithCrCf(); m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString()); session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length); return false; //session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This machine can't be recognized."); } session.MachineCustomIdTemp = words.Last(); uow.Dispose(); } //session.MachineCustomIdTemp = "RDTEST101"; //確認電樁連線所送的SubProtocol是否被Server支援 if (session.SecWebSocketProtocol.ToLower() != "ocpp1.6") { const string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; const string SecWebSocketKey = "Sec-WebSocket-Key"; const string ResponseHeadLine10 = "HTTP/1.1 101 Switching Protocols"; const string Upgrade = "Upgrade"; const string ResponseUpgradeLine = Upgrade + ": WebSocket"; const string Connection = "Connection"; const string ResponseConnectionLine = Connection + ": Upgrade"; const string ResponseAcceptLine = "Sec-WebSocket-Accept: {0}"; var responseBuilder = new StringBuilder(); var secWebSocketKey = session.Items.GetValue(SecWebSocketKey, string.Empty); if (string.IsNullOrEmpty(secWebSocketKey)) { return false; } string secKeyAccept = string.Empty; try { secKeyAccept = Convert.ToBase64String(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(secWebSocketKey + m_Magic))); } catch (Exception) { return false; } responseBuilder.AppendWithCrCf(ResponseHeadLine10); responseBuilder.AppendWithCrCf(ResponseUpgradeLine); responseBuilder.AppendWithCrCf(ResponseConnectionLine); responseBuilder.AppendFormatWithCrCf(ResponseAcceptLine, secKeyAccept); responseBuilder.AppendWithCrCf(); byte[] data = Encoding.UTF8.GetBytes(responseBuilder.ToString()); session.SendRawData(data, 0, data.Length); session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This SubProtocol can't be supported."); return false; } //session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler(WSServer.ReceivedMessage); return true; } } }