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");
}
}
}
}