public enum PhoneState : byte { Unknown = 0, Ringing = 1, Calling = 2, Connected = 3, Disconnected = 4, MicUp = 5, MicDown = 6 } class Device { /// /// Deklaracje zmiennych private /// private static Logger logger = LogManager.GetCurrentClassLogger(); private string _phoneNo; private string _lastPhoneNo; private Blob _crossRefId; private bool _isMonitored = false; private long _lastInvokeId; private PhoneState _oldState = PhoneState.Unknown; private PhoneState _newState = PhoneState.Unknown; /// /// Deklaracje zmiennych public /// public bool isMonitored { get { return _isMonitored; } set { _isMonitored = value; } } public string phoneNo { get { return _phoneNo; } set { _phoneNo = value; } } public string lastPhoneNo { get { return _lastPhoneNo; } set { _lastPhoneNo = value; } } public Blob crossRefId { get { return _crossRefId; } set { _crossRefId = value; } } public long lastInvokeId { get { return _lastInvokeId; } set { _lastInvokeId = value; } } public PhoneState newState { get { return _newState; } set { _oldState = _newState; _newState = value; } } public PhoneState oldState { get { return _oldState; } set { _oldState = value; } } /// /// Konstruktor /// /// Numer telefonu odpowiadający urządzeniu którego monitorowania chcemy rozpocząć public Device(string phoneNo) { this.phoneNo = phoneNo; MonitorStartArgument msa = new MonitorStartArgument(); msa.MonitorObject.Device.DialingNumber = this.phoneNo; CodeAndSend(msa, monitorStart_object.operationCode); } /// /// Pozwala wykonać połączenie wychodzącego na dowolny numer telefonu /// /// Numer telefonu na który ma zostać wykonane połączenie public void MakeCall(string phoneNo) { MakeCallArgument mca = new MakeCallArgument(); mca.CallingDevice.DialingNumber = this.phoneNo; mca.CalledDirectoryNumber.DeviceIdentifier.DeviceIdentifier.DialingNumber = phoneNo; CodeAndSend(mca, makeCall_object.operationCode); } /// /// Odbieranie rozmowy - działa tylko w przypadku telefonów ISDN z funkcją telefonu głośnomówiącego /// public void AnswerCall() { AnswerCallArgument aca = new AnswerCallArgument(); aca.CallToBeAnswered.Device.StaticID.DialingNumber = this.phoneNo; CodeAndSend(aca, answerCall_object.operationCode); } /// Obiekt zawierający dane które mają zostać wysłane do PBX/param> /// Kod operacji private void CodeAndSend(Unigone.Asn1RT.Type.Asn1Type argument, Unigone.Asn1RT.Type.Asn1Type operationCode) { Program.invokeId2phoneNo[Program.invokeId] = phoneNo; this.lastInvokeId = Program.invokeId; ROS rOS = new ROS(); rOS.Invoke.InvokeId.Present = Program.invokeId++; rOS.Invoke.Opcode.SetValue(operationCode); rOS.Invoke.Argument = argument; try { rOS.Validate(); Program.encoder.Encode(rOS); } catch (Asn1Exception ex) { logger.Error("ERROR WHILE CODING: " + argument.TypeName, ex); return; } PBXLink.Singleton.Write(Program.encoder.Data); } } class Program { private static Logger logger = LogManager.GetCurrentClassLogger(); private static string monitored = "C:\\monitored.tmp"; public static IEncoder encoder = CSTAp2Factory.CreateEncoder(); public static IDecoder decoder = CSTAp2Factory.CreateDecoder(); public static long invokeId; public static Dictionary Devices = new Dictionary(); public static Dictionary invokeId2phoneNo = new Dictionary(); public static Dictionary crossRefId2phoneNo = new Dictionary(); static void Main(string[] args) { /// Otwieramy polaczenie z PBX i podpinamy odpowiednią metodę która będzie parsowała /// dane w formacie ASN.1 przychodące z PBX'a PBXLink.Singleton.Open("COM1"); PBXLink.Singleton.OnMessage += new Message(PBXLink_OnMessage); /// Zatrzymujemy monitorowanie wszystkich urządzeń których crossRedIf mamy zapisane /// w tymczasowym pliku na dysku - ma to zapobiegać wielokrotnemu monitorowaniu tych samych urządzeń, /// co skutkuje otrzymywaniem tego samego eventu więcej niż jeden raz. StopMonitorOnAllDevices(); } /// /// Metoda zatrzymuje monitorowanie wszystkich urządzeń obecnie monitorowanych - słownik Devices /// oraz urządzeń monitorowanych w poprzedniej instancji aplikacji - plik tymczasowy na dysku /// private static void StopMonitorOnAllDevices() { } /// /// Parsuje dane ASN.1 na odpowiednie komunikaty CSTA i w zaleznosci od ich typu /// uruchamia (zdarzenie) handleEvent lub (rezultat) handleResult /// /// Dane zgodne z formatem ASN.1 które mają zostać przeparsowane private static void PBXLink_OnMessage(byte[] data) { byte[] pdu = data; ROS rOS = new ROS(); try { decoder.Decode(pdu, rOS); rOS.Validate(); } catch (Asn1Exception e) { logger.Error("Failed when parsing ASN.1", e); return; } logger.Info("ASN.1 data ok"); if (rOS.IsInvoke() && rOS.Invoke.Argument is CSTAEventReportArgument) { handleEvent((CSTAEventReportArgument) rOS.Invoke.Argument); } else if (rOS.IsReturnResult() || rOS.IsReturnError() || rOS.IsReject()) { handleReturn(rOS); } } private static void handleReturn(ROS rOS) { long invokeId; if (rOS.IsReturnResult()) invokeId = rOS.ReturnResult.InvokeId.Present; else if (rOS.IsReturnError()) invokeId = rOS.ReturnError.InvokeId.Present; else if (rOS.IsReject()) invokeId = rOS.Reject.InvokeId.Present; if (rOS.IsReturnResult() && rOS.ReturnResult.HasResult()) { if (rOS.ReturnResult.Result.Result is MonitorStartResult) { /// /// W obiekcie reprezentującym urządzenie ustawiamy propercje crossRedId (wymagana przy odczytywaniu pewnych eventów) /// oraz propercję isMonitored. /// /// Do crossRefId2phoneNo dopisujemy numer telefonu, aby mozna pozniej szybko na podstawie crossRefId odszukac /// odpowiedni obiekt w Devices. /// /// Dopisujemy crossRefId do tymczasowego pliku na dysku twardym, program przy każdym uruchomieniu usuwa monitory /// z wszystkich urządzen, których crossRefId znajduje się w tym pliku - zapobiega to wielokrotnemu /// otrzymywaniu eventów informujących o tych samych zdarzeniach. /// logger.Info("MonitorStartResult"); MonitorStartResult msr = (MonitorStartResult)rOS.ReturnResult.Result.Result; if (invokeId2phoneNo.ContainsKey(rOS.ReturnResult.InvokeId.Present)) { Devices[invokeId2phoneNo[rOS.ReturnResult.InvokeId.Present]].crossRefId = new Blob(msr.CrossRefIdentifier); Devices[invokeId2phoneNo[rOS.ReturnResult.InvokeId.Present]].isMonitored = true; crossRefId2phoneNo[new Blob(msr.CrossRefIdentifier)] = invokeId2phoneNo[rOS.ReturnResult.InvokeId.Present]; } TextWriter tw = new StreamWriter(monitored, true); tw.WriteLine(ByteArray.ByteArrayToHexString(msr.CrossRefIdentifier, "", 100)); tw.Close(); } else if (rOS.ReturnResult.Result.Result is MakeCallResult) { logger.Info("MakeCallResult"); } else if (rOS.ReturnResult.Result.Result is SendDTMFTonesResult) { logger.Info("SendDTMFTonesResult"); } else if (rOS.ReturnResult.Result.Result is SetFeatureResult) { logger.Info("SetFeatureResult"); } else { logger.Info("Other Result"); } } else { } } private static void handleEvent(CSTAEventReportArgument era) { if (era.EventSpecificInfo.IsCallEvent()) { logger.Info("-IsCallEvent"); if (era.EventSpecificInfo.CallEvent.IsOriginatedEvent()) { TCPServer.Singleton.WriteToUser(era.EventSpecificInfo.CallEvent.OriginatedEvent.CallingDevice.DeviceIdentifier.DeviceIdentifier.DialingNumber, "IsOriginatedEvent:" + era.EventSpecificInfo.CallEvent.OriginatedEvent.CalledDevice.DeviceIdentifier.DeviceIdentifier.DialingNumber); phoneNo2connId[era.EventSpecificInfo.CallEvent.OriginatedEvent.CallingDevice.DeviceIdentifier.DeviceIdentifier.DialingNumber] = new Blob(era.EventSpecificInfo.CallEvent.OriginatedEvent.OriginatedConnection.Call); connId2phoneNo[new Blob(era.EventSpecificInfo.CallEvent.OriginatedEvent.OriginatedConnection.Call)] = era.EventSpecificInfo.CallEvent.OriginatedEvent.CallingDevice.DeviceIdentifier.DeviceIdentifier.DialingNumber; logger.Info("IsOriginatedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsFailedEvent()) { logger.Info("IsFailedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsDeliveredEvent()) { logger.Info("IsDeliveredEvent"); } else if (era.EventSpecificInfo.CallEvent.IsConnectionClearedEvent()) { logger.Info("IsConnectionClearedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsEstablishedEvent()) { logger.Info("IsEstablishedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsDivertedEvent()) { logger.Info("IsDivertedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsHeldEvent()) { logger.Info("IsHeldEvent"); } else if (era.EventSpecificInfo.CallEvent.IsRetrievedEvent()) { logger.Info("IsRetrievedEvent"); } else if (era.EventSpecificInfo.CallEvent.IsServiceInitiatedEvent()) { Devices[era.EventSpecificInfo.CallEvent.ServiceInitiatedEvent.InitiatedConnection.Device.StaticID.DialingNumber].newState = PhoneState.MicUp; logger.Info("IsServiceInitiatedEvent"); } } } }