178 lines
8.2 KiB
C#
178 lines
8.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Independentsoft.Sip;
|
|
using Independentsoft.Sip.Methods;
|
|
using SipComponent.Excera;
|
|
|
|
namespace SipComponent
|
|
{
|
|
/// <summary>
|
|
/// An implementation of the abstract class SipClientClass, used for Excera
|
|
/// </summary>
|
|
public class SipClientClassExcera : SipClientClassSimoco
|
|
{
|
|
|
|
#region Fields
|
|
|
|
private ExceraSipMessageGenerator _sipMessageGenerator = new ExceraSipMessageGenerator();
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Constructor for the SipClientClassExcera
|
|
/// </summary>
|
|
/// <param name="repeaterIP">domain name, name or IP address of sip server</param>
|
|
/// <param name="repeaterSipPort">port number of the sip server</param>
|
|
/// <param name="localSipPort">port number of the local computer used for sip protocol</param>
|
|
/// <param name="userName">user name on the sip server</param>
|
|
/// <param name="registrationInterval">interval to send sip registration requests. Value is in seconds</param>
|
|
/// <param name="bufferMiliseconds">Miliseconds for the buffer that stores the received voice packets</param>
|
|
/// <param name="requestTimeout">Number of ms to wait before the sip request times out</param>
|
|
/// <param name="localIPAddress">Local Ip adress. If not specified, the class will search for a local ip on the same network with the repeater's ip</param>
|
|
public SipClientClassExcera(string repeaterIP, int repeaterSipPort, int localSipPort,
|
|
string userName, int registrationInterval, int bufferMiliseconds, int requestTimeout, string localIPAddress = null)
|
|
:base(repeaterIP, repeaterSipPort, localSipPort, userName, registrationInterval, bufferMiliseconds, requestTimeout, localIPAddress)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
#region Public Members
|
|
|
|
/// <summary>
|
|
/// Method used to send a Ping command to an Excera radio
|
|
/// </summary>
|
|
/// <param name="idToSendPing">The Excera ID of the radio</param>
|
|
public override void SendPing(string idToSendPing)
|
|
{
|
|
base.SendExceraPing(idToSendPing);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Non-Public Members Overrinding
|
|
|
|
/// <summary>
|
|
/// Function that processes all the received Sip Message requests
|
|
/// </summary>
|
|
/// <param name="sipMessageRequest">The Sip Message request</param>
|
|
/// <param name="senderID">The ID of the sender</param>
|
|
protected override void ProcessReceivedSipMessage(Request sipMessageRequest, string senderID)
|
|
{
|
|
if (sipMessageRequest.Header.Contains("Ais-Msg-id"))
|
|
{
|
|
string msgId = sipMessageRequest.Header["Ais-Msg-id"];
|
|
if (msgId.Contains("emerg-alarm"))
|
|
{
|
|
EmergencyReceived?.Invoke(this, new SipEventArgs(senderID));
|
|
}
|
|
}
|
|
// Handle messages when working with Excera
|
|
// Get Ais-Msg-Options Header value - this is used for Gps periodically reports
|
|
if (sipMessageRequest.Header.Contains("Ais-Msg-Options"))
|
|
{
|
|
string ais_options = sipMessageRequest.Header["Ais-Msg-Options"];
|
|
switch (ais_options)
|
|
{
|
|
case "service-attributes;transmission-type=raw;coding=nmea;rate=half":
|
|
// GPS periodically report
|
|
double lat, lon, speed;
|
|
DateTime time;
|
|
// Get latitude, longitude, speed and time
|
|
Simoco.Utils.GPSInfo(Convert.FromBase64String(sipMessageRequest.Body), out lat, out lon, out speed, out time);
|
|
// Raise Event
|
|
OnGpsPeriodicallyReportReceived(new GpsDataEventArgs(
|
|
senderID, lat, lon, speed, time));
|
|
break;
|
|
case "service-attributes; coding=iso8":
|
|
// Management message report
|
|
// Get the Type and the command bytes
|
|
byte[] data = Convert.FromBase64String(sipMessageRequest.Body);
|
|
byte type = SipComponent.Simoco.SP6.GetType(data);
|
|
byte command = SipComponent.Simoco.SP6.GetCommand(data);
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
// GPS position report
|
|
byte[] nmeaData = new byte[10];
|
|
Array.Copy(data, 5, nmeaData, 0, nmeaData.Length);
|
|
// Get latitude, longitude, speed and time from nmea data
|
|
Simoco.Utils.GPSInfo(nmeaData, out lat, out lon, out speed, out time);
|
|
// Raise event
|
|
OnSimocoGpsReportReceived(new GpsDataEventArgs(senderID, lat, lon, speed, time));
|
|
break;
|
|
case 1:
|
|
// Device status
|
|
switch (command)
|
|
{
|
|
case 1:
|
|
// Device status report
|
|
// Sent on request or when alarm conditions change
|
|
// Is sent to remote radio to acknowledge receipt of alarm conditions
|
|
|
|
// Get GPS from status report
|
|
Simoco.Utils.GetGPSFromStatusReport(data, out lat, out lon);
|
|
Simoco.AlarmType alarmType = Simoco.SP6.GetAlarmType(data);
|
|
if (alarmType != Simoco.AlarmType.NO_ALARM)
|
|
{
|
|
// Save the message in a dictionary
|
|
// It have to be resent to the radio to confirm the receipt
|
|
AddSimocoAlarmToDictionary(senderID, sipMessageRequest.Body);
|
|
}
|
|
// Raise event
|
|
OnSimocoStatusReportReceived(new SimocoDeviceStatusReportEventArgs(
|
|
senderID, lat, lon, alarmType));
|
|
break;
|
|
}
|
|
break;
|
|
case 255:
|
|
// Ping
|
|
int nbOfReceivedBytes = data.Length - 5;
|
|
byte[] pingData = new byte[nbOfReceivedBytes];
|
|
Array.Copy(data, 5, pingData, 0, pingData.Length);
|
|
if (HandleSimocoPingResponse(senderID, pingData))
|
|
{
|
|
// Fire Event
|
|
OnSimocoPingResponseReceived(new SipEventArgs(senderID));
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
// This is surelly incorect - TO DO
|
|
// Sms from Simoco
|
|
string text = sipMessageRequest.Body;
|
|
if (text != null) // body is null in case of status message - future implementation - TO DO
|
|
{
|
|
OnSmsReceived(new SmsReceivedEventsArgs(senderID,
|
|
Encoding.BigEndianUnicode.GetString(Convert.FromBase64String(text))
|
|
));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
internal override SipMessageGenerator SipMessageGenerator
|
|
{
|
|
get
|
|
{
|
|
return _sipMessageGenerator;
|
|
}
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region events
|
|
|
|
public event EventHandler<SipEventArgs> EmergencyReceived;
|
|
|
|
#endregion
|
|
}
|
|
}
|