/// <summary> /// This will broadcast data to the Socket /// </summary> /// <param name="guid">Client guid</param> /// <param name="data">data to write</param> private void Broadcast(Guid guid, string data) { var buffer = Encoding.ASCII.GetBytes(data + Environment.NewLine); lock (lockObj) { clients[guid].GetStream().Write(buffer, 0, buffer.Length); } LogHelp.LogWrite(guid, data, LogHelp.LogLevel.debug); }
/// <summary> /// Send Command to Pump, will add STX, ETX and Calc CD byte and Add to the data stream /// </summary> /// <param name="Message"></param> protected void SendCMD(Guid guid, string Message) { byte[] Send = MakeCMDLine(Message); lock (lockObj) { clients[guid].GetStream().Write(Send, 0, Send.Length); } string Data = System.Text.Encoding.UTF8.GetString(Send); if (Message.Substring(0, 4).Contains("28")) { LogHelp.LogWrite(guid, Data, LogHelp.LogLevel.debug); } else { LogHelp.LogWrite(guid, Data, LogHelp.LogLevel.info); } }
private void HandleClients(object id) { var guid = (Guid)id; TcpClient client = null; lock (lockObj) { client = clients[guid]; } bool quit = false; while (!quit) { var networkStream = client.GetStream(); var buffer = new byte[1024]; int byteCount = 0; try { byteCount = networkStream.Read(buffer, 0, buffer.Length); } catch { } if (byteCount == 0) { break; } else { var data = Encoding.ASCII.GetString(buffer, 0, byteCount); if (!CommandHandler(guid, byteCount, buffer)) { switch (data) { case "hi": Broadcast(guid, $"Hi Guest, it is now {DateTime.Now:T}"); break; case "hello": Broadcast(guid, $"hi Guest, it is the {DateTime.Now:D}"); break; case "hej": Broadcast(guid, $"Hi Guest, it is the {DateTime.Now:D} and the time is {DateTime.Now:T}"); break; case "time": SendCMD(guid, $"T{DateTime.Now:T}"); break; case "date": SendCMD(guid, $"D{DateTime.Now:D}"); //Broadcast(guid, DateTime.Now.ToShortDateString()); break; case "now": SendCMD(guid, $"DT{DateTime.Now:Z}"); break; case "datetime": SendCMD(guid, $"DT{DateTime.Now:D} {DateTime.Now:T}"); break; case "quit": quit = true; break; default: SendCMD(guid, data); break; } } } } LogHelp.LogWrite(guid, " Stream Closed"); lock (lockObj) { clients.Remove(guid); client.Client.Shutdown(SocketShutdown.Both); client.Close(); } }
private bool CommandHandler(Guid guid, int byteCount, byte[] buffer) { var data = Encoding.ASCII.GetString(buffer, 0, byteCount); TcpClient client = null; lock (lockObj) { client = clients[guid]; } LogHelp.localEndpoint = tcpListener.LocalEndpoint; LogHelp.remoteEndPoint = clients[guid].Client.RemoteEndPoint; // If FE only show in DEBUG mode. if (data.Contains("FE")) { LogHelp.LogRead(guid, data, LogHelp.LogLevel.debug); } else { LogHelp.LogRead(guid, data, LogHelp.LogLevel.info); } if (buffer[0].Equals(2)) // Byte0 = STX, start of Command { int pump = 0; try { pump = Convert.ToInt16(data.Substring(2, 2)); } catch { } switch (Convert.ToChar(buffer[1])) { /* STX B xx C ETX CD * B - Message identifier * xx- Pump No * C - Cancel identifier * Pump No = 1 * Sample command = STX B 01 C ETX CD * * STX B xx xxxxxxx ETX CD * Finalize Command Character=B * Pump #=XX (01 to 32) * xxxxxxxx = EHM$VPL * * • Pump 1 * * Sample Command = STX B 01 EHM$VPL ETX CD */ case 'B': //Pump Cancel or Finalize if (data.Substring(4, 1) == "C") // Cancel Pump { ThisStation.SetStatus(pump, PumpStatusEnum.Idle); } else if (data.Substring(4, 7) == "EHM$VPL") // Get Finalization { if (ThisStation.Pumps[pump].PumpStatus.Equals(PumpStatusEnum.DispenseCompleted)) { /* 01H2M1$0000000000V0000000000P002600L010000 * SendCMD(guid, $"07H2M0$0000002000V0000009217P002170L002000f"); * 07 H2 M0 $0000002000 V0000009217 P002170 L002000 * Pump=07 * Hose=2 * M=0 (flag?) * Amount:00000020.00 * Volume:0000009.217 * PPU:002.170 * Limit:0020.00 * Final sales data for pump 7, Hose=2, Amt=20.00, Vol=9.217, PPU=2.170 (L=20.00) */ Pump.Pump Fpump = ThisStation.Pumps[pump]; decimal vol = Fpump.Volume; vol = vol.Equals(0) ? 1 : vol; SendCMD(guid, $"{pump:00}" + // Pump $"H{Fpump.Hose:0}" + //Hose $"M{Fpump.Flag:0}" + //Flag $"${Fpump.Amount * 100:0000000000}" + //amount * 100 $"V{Fpump.Volume * 1000:0000000000}" + //volume liter * 1000 $"P{(Fpump.Amount / (vol)) * 1000:000000}" + // price per unit * 1000 $"L{Fpump.Limit * 100:000000}" + // original limith * 100 $""); ThisStation.SetStatus(pump, PumpStatusEnum.Idle); } } break; /* * STX A Pump# Hose# Flag $$$$.$$ vvv.vvv ETX CD * In the actual command, decimal points are implied only. * Authorize Command Character=A * Pump #=XX (01 to 32) * Hose #=X (0 to 8, with 0 authorizing any hose — also see Multi-grade Lock Authorization which follows) * Flag=X (Type of authorization — see Description) * Dollar Limit Amount=$$$$.$$ (0000.01 to 9999.99) * Volume Limit Amount=vvv.vvv (000.001 to 999.999) * * • Pump 1 * • Hose 1 * • $25.00 * * Sample Command = STX A 0101002500000000 ETX CD */ case 'A': // Authorize int hose = Convert.ToInt16(data.Substring(4, 1)); string flag = data.Substring(5, 1); decimal dollarLimit = Convert.ToDecimal(data.Substring(6, 6).Insert(4, ".")); decimal volumeLimit = Convert.ToDecimal(data.Substring(12, 6).Insert(3, ".")); if (ThisStation.Pumps[pump].PumpStatus.Equals(PumpStatusEnum.Reserved)) { Pump.Pump Npump = ThisStation.Pumps[pump]; Npump.Limit = dollarLimit; Npump.Volume = volumeLimit; Npump.Hose = hose; Npump.Flag = flag; if (ThisStation.Pumps.ContainsKey(pump)) { ThisStation.Pumps.Remove(pump); } ThisStation.Pumps.Add(pump, Npump); ThisStation.SetStatus(pump, PumpStatusEnum.Authorized); } break; /* * 1, Check current pump state which should be idle * 2. If match, sending reserve message to ISIS by sending pumpId and ZapOrderId. * * STX M xx ETX CD * * M Reserve identifier * xx Pump No * Pump No = 1 * * Sample command = STX M 01 ETX CD * Failure command = STX M 01 1 ETX CD */ case 'M': // Reserve if (ThisStation.Pumps[pump].PumpStatus.Equals(PumpStatusEnum.Idle)) { ThisStation.SetStatus(pump, PumpStatusEnum.Reserved); } else { SendCMD(guid, $"M{pump:00}{0x01}"); LogHelp.LogWrite(guid, $"Pump #{pump:00}: is already reserved", LogHelp.LogLevel.debug); } break; /* * Request Pump Status * Get Status Command Character=FE * * Sample Command = STX FE ETX CD * Response Command = STX 28000000000000000000000000000000000000000000000000000000000000000 ETX CD * (64 chars) */ case 'F': // Request Pump Status if (data.Substring(1, 1) != "E") { //Do Timer tick here //storyman.StoryHandler.TimerTick(); string PumpStatus = ""; foreach (KeyValuePair <int, Pump.Pump> item in ThisStation.Pumps) { if (!item.Key.Equals(0)) { PumpStatus += item.Value.Status; } } for (int i = ThisStation.Pumps.Count; i < 66; i++) { PumpStatus += 0x00; PumpStatus += 0x00; } PumpStatus = PumpStatus.Substring(0, 64); SendCMD(guid, $"28{PumpStatus}"); } break; case 'G': // Get Status on pump SendCMD(guid, $"G{pump:00}{ThisStation.Pumps[pump].Status}"); break; case 'S': // Change Status on pump string Status = data.Substring(4, 2); ThisStation.SetStatusText(pump, Status); break; case 'V': // Change Volume on pump decimal volume = Convert.ToDecimal(data.Substring(4, 6).Insert(3, ".")); ThisStation.SetVolume(pump, volume); break; case 'D': // Change Amount on pump decimal Amount = Convert.ToDecimal(data.Substring(4, 6).Insert(3, ".")); ThisStation.SetAmount(pump, Amount); break; case 'I': // Pump Info decimal vol1 = ThisStation.Pumps[pump].Volume; vol1 = vol1.Equals(0) ? 1 : vol1; SendCMD(guid, $"I{pump:00}" + // Pump $"S{ThisStation.Pumps[pump].Status}" + $"H{ThisStation.Pumps[pump].Hose:0}" + //Hose $"M{ThisStation.Pumps[pump].Flag:0}" + //Flag $"${ThisStation.Pumps[pump].Amount * 100:0000000000}" + //amount * 100 $"V{ThisStation.Pumps[pump].Volume * 1000:0000000000}" + //volume liter * 1000 $"P{(ThisStation.Pumps[pump].Amount / (vol1)) * 1000:000000}" + // price per unit * 1000 $"L{ThisStation.Pumps[pump].Limit * 100:000000}" + // original limith * 100 $""); break; default: SendCMD(guid, data); break; } return(true); } else { return(false); } }