OCPPWSServer.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using Evcb.Domain.Model;
  2. using Evcb.Repository;
  3. using Evcb.Service;
  4. using SuperSocket.Common;
  5. using SuperWebSocket;
  6. using SuperWebSocket.SubProtocol;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. namespace OCPPServer.Protocol
  12. {
  13. public class OCPPWSServer : WebSocketServer<ClientData>
  14. {
  15. /// <summary>
  16. /// 可允許連線Clinet數
  17. /// </summary>
  18. public int connectNum { get; set; }
  19. /// <summary>
  20. /// 是否限制連線Clinet數
  21. /// </summary>
  22. public bool beConnectLimit { get; set; }
  23. /// <summary>
  24. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  25. /// </summary>
  26. /// <param name="subProtocols">The sub protocols.</param>
  27. public OCPPWSServer(IEnumerable<ISubProtocol<ClientData>> subProtocols)
  28. : base(subProtocols)
  29. {
  30. }
  31. /// <summary>
  32. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  33. /// </summary>
  34. /// <param name="subProtocol">The sub protocol.</param>
  35. public OCPPWSServer(ISubProtocol<ClientData> subProtocol)
  36. : base(subProtocol)
  37. {
  38. }
  39. /// <summary>
  40. /// Initializes a new instance of the <see cref="WebSocketServer"/> class.
  41. /// </summary>
  42. public OCPPWSServer()
  43. : base(new List<ISubProtocol<ClientData>>())
  44. {
  45. }
  46. protected override bool ValidateHandshake(ClientData session, string origin)
  47. {
  48. //初始化ClientData
  49. session.InitialPileData();
  50. //確認電樁所送的電樁識別碼是否包含在request path中
  51. string[] words = session.Path.Split('/');
  52. using (var db = new PhihongDbContext())
  53. {
  54. if (this.beConnectLimit == true)
  55. {
  56. var connectPile = db.Machine.Where(c => c.Online == true).ToList();
  57. if (connectPile.Count >= this.connectNum)
  58. {
  59. byte[] m_SwitchResponse;
  60. var responseBuilder = new StringBuilder();
  61. responseBuilder.AppendWithCrCf("HTTP/1.1 403"); //403 Forbidden : 用戶端並無訪問權限,所以伺服器給予應有的回應。
  62. responseBuilder.AppendWithCrCf("Upgrade: WebSocket");
  63. responseBuilder.AppendWithCrCf("Connection: Upgrade");
  64. responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion);
  65. responseBuilder.AppendWithCrCf();
  66. m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString());
  67. session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length);
  68. return false;
  69. }
  70. }
  71. IUnitOfWork uow = new UnitOfWork(db);
  72. IMachineService machineSrv = new MachineService(uow);
  73. var machine = machineSrv.GetByCustomId(words.Last());
  74. if (machine == null)
  75. {
  76. byte[] m_SwitchResponse;
  77. var responseBuilder = new StringBuilder();
  78. responseBuilder.AppendWithCrCf("HTTP/1.1 404");
  79. responseBuilder.AppendWithCrCf("Upgrade: WebSocket");
  80. responseBuilder.AppendWithCrCf("Connection: Upgrade");
  81. responseBuilder.AppendWithCrCf("Sec-WebSocket-Version: " + session.SecWebSocketVersion);
  82. responseBuilder.AppendWithCrCf();
  83. m_SwitchResponse = Encoding.UTF8.GetBytes(responseBuilder.ToString());
  84. session.SendRawData(m_SwitchResponse, 0, m_SwitchResponse.Length);
  85. return false;
  86. //session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This machine can't be recognized.");
  87. }
  88. session.MachineCustomIdTemp = words.Last();
  89. uow.Dispose();
  90. }
  91. //session.MachineCustomIdTemp = "RDTEST101";
  92. //確認電樁連線所送的SubProtocol是否被Server支援
  93. if (session.SecWebSocketProtocol.ToLower() != "ocpp1.6")
  94. {
  95. const string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
  96. const string SecWebSocketKey = "Sec-WebSocket-Key";
  97. const string ResponseHeadLine10 = "HTTP/1.1 101 Switching Protocols";
  98. const string Upgrade = "Upgrade";
  99. const string ResponseUpgradeLine = Upgrade + ": WebSocket";
  100. const string Connection = "Connection";
  101. const string ResponseConnectionLine = Connection + ": Upgrade";
  102. const string ResponseAcceptLine = "Sec-WebSocket-Accept: {0}";
  103. var responseBuilder = new StringBuilder();
  104. var secWebSocketKey = session.Items.GetValue<string>(SecWebSocketKey, string.Empty);
  105. if (string.IsNullOrEmpty(secWebSocketKey))
  106. {
  107. return false;
  108. }
  109. string secKeyAccept = string.Empty;
  110. try
  111. {
  112. secKeyAccept = Convert.ToBase64String(System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(secWebSocketKey + m_Magic)));
  113. }
  114. catch (Exception)
  115. {
  116. return false;
  117. }
  118. responseBuilder.AppendWithCrCf(ResponseHeadLine10);
  119. responseBuilder.AppendWithCrCf(ResponseUpgradeLine);
  120. responseBuilder.AppendWithCrCf(ResponseConnectionLine);
  121. responseBuilder.AppendFormatWithCrCf(ResponseAcceptLine, secKeyAccept);
  122. responseBuilder.AppendWithCrCf();
  123. byte[] data = Encoding.UTF8.GetBytes(responseBuilder.ToString());
  124. session.SendRawData(data, 0, data.Length);
  125. session.CloseWithHandshake(session.ProtocolProcessor.CloseStatusClode.NormalClosure, "This SubProtocol can't be supported.");
  126. return false;
  127. }
  128. //session.m_ReceiveData += new ClientData.OCPPClientDataEventHandler<ClientData, String>(WSServer.ReceivedMessage);
  129. return true;
  130. }
  131. }
  132. }