817 lines
30 KiB
C#
817 lines
30 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Net;
|
|||
|
using System.Collections;
|
|||
|
using System.ComponentModel;
|
|||
|
using SafeMobileLib;
|
|||
|
using SafeMobileLib.MessageDecoders;
|
|||
|
|
|||
|
namespace MotoRepeater
|
|||
|
{
|
|||
|
class WatcherServerThread
|
|||
|
{
|
|||
|
/* This field is used to define the type of the message. The size of this field is one byte
|
|||
|
* long. The data type for this field is unsigned integer.
|
|||
|
* Four messages are currently used by the DDMS:
|
|||
|
*
|
|||
|
* */
|
|||
|
public enum MessageID { RELIABLE_NOTIFY = 4, SUBSCRIBE_V2 = 20, DELETE_MOBILITY = 21, MOBILITY_UPDATE = 22 };
|
|||
|
public enum SubscriptionState { Rejected = 1, Accepted = 2, Terminated = 3, RefreshAccepted = 4 }
|
|||
|
|
|||
|
public readonly int DialogID = 1313;
|
|||
|
private readonly int ReadTimeout = 1000 * 60 * 60 * 24; // 24 hours
|
|||
|
|
|||
|
/*
|
|||
|
* The notification messages are sent over a negotiated TCP/IP connection when using the Confirmed Notify Interface
|
|||
|
*/
|
|||
|
private TcpClient client;
|
|||
|
|
|||
|
private Thread listenThread;
|
|||
|
private Thread intervalThread;
|
|||
|
private NetworkStream clientStream;
|
|||
|
byte[] message;
|
|||
|
private string p_ctrIP;
|
|||
|
private int port;
|
|||
|
int totalUsers;
|
|||
|
|
|||
|
public bool connDown = false;
|
|||
|
public bool prevConnDownState = true;
|
|||
|
|
|||
|
public WatcherServerThread(string _ctrlIP, int port)
|
|||
|
{
|
|||
|
//Utils.ConsWrite(DebugMSG_Type.CTRL, "WatcherServerThread Constructor");
|
|||
|
message = new byte[128];
|
|||
|
p_ctrIP = _ctrlIP;
|
|||
|
this.port = port;
|
|||
|
totalUsers = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public void Stop()
|
|||
|
{
|
|||
|
if (clientStream != null)
|
|||
|
{
|
|||
|
clientStream.Close();
|
|||
|
}
|
|||
|
if (listenThread!= null && listenThread.IsAlive)
|
|||
|
{
|
|||
|
if (intervalThread.IsAlive)
|
|||
|
{
|
|||
|
intervalThread.Abort();
|
|||
|
}
|
|||
|
else
|
|||
|
listenThread.Abort();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public void Start()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
client = new TcpClient();
|
|||
|
//serverEndPoint = new IPEndPoint("127.0.0.1", 3000);
|
|||
|
//client.Connect(serverEndPoint);
|
|||
|
client.Connect(p_ctrIP, port);
|
|||
|
Utils.WriteLine("••• Watcher Server Thread connected on " + p_ctrIP + ":" + port, ConsoleType.CTRL);
|
|||
|
clientStream = client.GetStream();
|
|||
|
if (clientStream != null)
|
|||
|
{
|
|||
|
//set read timeout to 35 seconds, according to Motorola Connect Plus PN_Watcher specifications
|
|||
|
clientStream.ReadTimeout = ReadTimeout;
|
|||
|
connDown = false;
|
|||
|
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(true);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
Utils.WriteLine("WatcherServerThread -> clientStream==null", ConsoleType.ALL);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Error WatcherServerThread connecting to " + p_ctrIP + " \n", ConsoleType.ALL);
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
listenThread = new Thread(new ThreadStart(HandleClientComm));
|
|||
|
listenThread.IsBackground = true;
|
|||
|
listenThread.Start();
|
|||
|
intervalThread = new Thread(new ThreadStart(HandleInterval));
|
|||
|
intervalThread.IsBackground = true;
|
|||
|
intervalThread.Start();
|
|||
|
Utils.WriteLine("»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»««««««««««««««««««««««««««««««", ConsoleType.CTRL);
|
|||
|
Utils.WriteLine(String.Format("»»»»»»»»»»»»»»»»» Watcher Server Listening «««««««««««««««««"), ConsoleType.CTRL);
|
|||
|
Utils.WriteLine("»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»««««««««««««««««««««««««««««««", ConsoleType.CTRL);
|
|||
|
}
|
|||
|
|
|||
|
public void RestartTCP()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
client = new TcpClient();
|
|||
|
//serverEndPoint = new IPEndPoint("127.0.0.1", 3000);
|
|||
|
//client.Connect(serverEndPoint);
|
|||
|
client.Connect(p_ctrIP, port);
|
|||
|
//Utils.WriteLine(ConsoleType.CTRL, "WatcherServerThread connected on " + p_ctrIP + ":" + port);
|
|||
|
Utils.WriteLine("♥♥♥ Watcher Server Thread connected on " + p_ctrIP + ":" + port);
|
|||
|
clientStream = client.GetStream();
|
|||
|
if (clientStream != null)
|
|||
|
{
|
|||
|
//set read timeout to 35 seconds, according to Motorola Connect Plus PN_Watcher specifications
|
|||
|
clientStream.ReadTimeout = ReadTimeout;
|
|||
|
|
|||
|
/*
|
|||
|
listenThread = new Thread(new ThreadStart(HandleClientComm));
|
|||
|
listenThread.IsBackground = true;
|
|||
|
listenThread.Start();
|
|||
|
*/
|
|||
|
//resend subscribe all
|
|||
|
Thread.Sleep(500);
|
|||
|
//SubscribeList(DialogID, new List<string>() { "101" });
|
|||
|
//SubscribeALL(1234);
|
|||
|
connDown = false;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(true);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
|
|||
|
Utils.WriteLine("Restart finnished ip" + p_ctrIP + " port:" + port, ConsoleType.CTRL);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
Utils.WriteLine("WatcherServerThread -> clientStream==null", ConsoleType.ALL);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("••• Connection with DDMS was not established!", ConsoleType.ALL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//IF THE UNIT IS NOT IN ht_SUInfo dont process the message
|
|||
|
private void HandleClientComm()
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
while (MotoRepeater_GW.isRunning)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (clientStream != null)
|
|||
|
{
|
|||
|
clientStream.ReadTimeout = ReadTimeout;
|
|||
|
//Utils.WriteLine("Watcher Server waiting...");
|
|||
|
//read LEN first
|
|||
|
byte[] msgLen = new byte[2];
|
|||
|
int result = clientStream.Read(msgLen, 0, msgLen.Length);
|
|||
|
int msgLength = msgLen[0] * 265 + msgLen[1];
|
|||
|
|
|||
|
message = new byte[msgLength];
|
|||
|
result = clientStream.Read(message, 0, msgLength);
|
|||
|
|
|||
|
|
|||
|
//Print(message, result, true);
|
|||
|
NotifyRespons resp = Decode(message, result);
|
|||
|
if (resp.Error)
|
|||
|
{
|
|||
|
|
|||
|
Utils.WriteLine("»»» Error response from " + resp.SUID, ConsoleType.ALL);
|
|||
|
Utils.WriteLine(Utils.PrintBytesArray(message), ConsoleColor.Yellow);
|
|||
|
|
|||
|
|
|||
|
//continue;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (resp.DialogID != 1234)
|
|||
|
{
|
|||
|
Utils.WriteLine("»»» One time resp from " + resp.SUID, ConsoleType.ALL);
|
|||
|
resp.PollResponse = true;
|
|||
|
}
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
OnARSReceived(Int64.Parse(resp.SUID), resp.Active);
|
|||
|
}
|
|||
|
catch (Exception) { }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (System.IO.IOException ex)
|
|||
|
{
|
|||
|
//Utils.ConsWrite(DebugMSG_Type.always, "I/O exception!!");
|
|||
|
if (MotoRepeater_GW.isRunning)
|
|||
|
Utils.WriteLine("φφφ Subscribe Exception: " + ex.ToString(), ConsoleType.ALL);
|
|||
|
|
|||
|
Thread.Sleep(500);
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if(MotoRepeater_GW.isRunning)
|
|||
|
Utils.WriteLine("φφφ Subscribe Exception: " + ex.ToString(), ConsoleType.ALL);
|
|||
|
Thread.Sleep(500);
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
}
|
|||
|
|
|||
|
while (MotoRepeater_GW.isRunning && connDown == true)
|
|||
|
{
|
|||
|
//Utils.WriteLine(ConsoleType.ALL, "HandleClientComm -> connDown==true Restarting TCP");
|
|||
|
if (++count % 20 == 0)
|
|||
|
{
|
|||
|
RestartTCP();
|
|||
|
count = 1;
|
|||
|
}
|
|||
|
Thread.Sleep(500);
|
|||
|
}
|
|||
|
//Thread.Sleep(100);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void HandleInterval()
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
while (MotoRepeater_GW.isRunning)
|
|||
|
{
|
|||
|
string suid = "";
|
|||
|
int dialogID = -1;
|
|||
|
try
|
|||
|
{
|
|||
|
//test if we have a change in reporting interval
|
|||
|
|
|||
|
if (++count % 3 == 0)
|
|||
|
{
|
|||
|
SUinfo info = SN_Queues.NewIntervalQueue.GetItem(100);
|
|||
|
if (info != null && info.ARSon)
|
|||
|
{
|
|||
|
suid = info.suid;
|
|||
|
Utils.WriteLine("Reporting interval changed for " + info.suid + " [" + info.repInterval + " sec]", ConsoleColor.Cyan);
|
|||
|
//dialogID = 0x1111;
|
|||
|
//SubscribeOneTime(dialogID, info.suid);
|
|||
|
if(LocationThread.SendTriggeredLocationRequestWithLOC(info.suid, info.repInterval))
|
|||
|
if (OnTriggeredLocationRequest != null)
|
|||
|
OnTriggeredLocationRequest(info.suid, info.repInterval);
|
|||
|
}
|
|||
|
count = 0;
|
|||
|
}
|
|||
|
|
|||
|
Thread.Sleep(500);
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{ Utils.WriteLine("Error HandleInterval for suid:" + suid + " dialogID:" + dialogID, ConsoleType.ALL); }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private NotifyRespons Decode(byte[] data, int recv)
|
|||
|
{
|
|||
|
//Console.WriteLine("Got notify message");
|
|||
|
NotifyRespons nResp = new NotifyRespons();
|
|||
|
|
|||
|
nResp.Active = false;
|
|||
|
nResp.DialogID = 0;
|
|||
|
nResp.Error = true;
|
|||
|
nResp.SUID = "0";
|
|||
|
|
|||
|
//int msgLength = data[0] * 265 + data[1];
|
|||
|
//length doesent match... return error
|
|||
|
//if (msgLength != recv-2) { Console.WriteLine("Received length({0}) doesent match with message length({1})..returning errror!!!",recv-2,msgLength); return nResp; }
|
|||
|
|
|||
|
//test if we got at least msgLen, msgID,dialogID,subscription state
|
|||
|
if (recv < 6)
|
|||
|
{
|
|||
|
Utils.WriteLine("Incorect message.Message does not have the minimum size of 6bytes. actual length=" + recv, ConsoleType.ALL);
|
|||
|
Utils.WriteLine("!!!!!!!!!!!!subscription state TLV missing!!!!!!!!!!!", ConsoleType.ALL);
|
|||
|
client.Close();
|
|||
|
|
|||
|
connDown = true;
|
|||
|
// fire event only when the state had changed
|
|||
|
if (prevConnDownState != connDown)
|
|||
|
OnDdmsConnectionStatusChanged(false);
|
|||
|
// save new state
|
|||
|
prevConnDownState = connDown;
|
|||
|
|
|||
|
return nResp;
|
|||
|
}
|
|||
|
|
|||
|
//decode message ID
|
|||
|
int msgID = data[0];
|
|||
|
if (msgID != (int)MessageID.RELIABLE_NOTIFY)
|
|||
|
{
|
|||
|
Utils.WriteLine(String.Format("Incorect msgID:{0}. MsgID must be 4(reliable notify message)", msgID), ConsoleType.ALL);
|
|||
|
return nResp;
|
|||
|
}
|
|||
|
|
|||
|
//decode dialog ID
|
|||
|
int dialogID = data[1] * 256 + data[2];
|
|||
|
nResp.DialogID = dialogID;
|
|||
|
//Console.WriteLine("DialogID:" + dialogID);
|
|||
|
|
|||
|
//next TLV are optional
|
|||
|
for (int i = 3; i < data.Length; i++)
|
|||
|
{
|
|||
|
switch (data[i])
|
|||
|
{
|
|||
|
case 3:
|
|||
|
//decode subscription state TLV
|
|||
|
byte tag = data[i];
|
|||
|
byte len = data[i + 1];
|
|||
|
byte value = data[i + 2];
|
|||
|
if (tag == 0x03 && len == 0x01)
|
|||
|
{
|
|||
|
switch (value)
|
|||
|
{
|
|||
|
case (byte)SubscriptionState.Accepted:
|
|||
|
//Utils.WriteLine("Subscription State: " + SubscriptionState.Accepted);
|
|||
|
break;
|
|||
|
case (byte)SubscriptionState.RefreshAccepted:
|
|||
|
//Utils.WriteLine("Subscription State: " + SubscriptionState.RefreshAccepted);
|
|||
|
break;
|
|||
|
case (byte)SubscriptionState.Rejected:
|
|||
|
Utils.WriteLine("!!! MNIS Subscription State: " + SubscriptionState.Rejected);
|
|||
|
break;
|
|||
|
case (byte)SubscriptionState.Terminated:
|
|||
|
//Utils.WriteLine("Subscription State: " + SubscriptionState.Terminated);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Utils.WriteLine("••• Unknown subscription state:" + value, ConsoleType.CTRL);
|
|||
|
}
|
|||
|
//jump to next tlv
|
|||
|
i += 1 + len;
|
|||
|
break;
|
|||
|
|
|||
|
//decode Expires TLV
|
|||
|
case 1:
|
|||
|
tag = data[i];
|
|||
|
len = data[i + 1];
|
|||
|
byte[] value_arr = new byte[len];
|
|||
|
Array.Copy(data, i + 2, value_arr, 0, len);
|
|||
|
int expireTime = ConvertByteArr2Int(value_arr);
|
|||
|
//Utils.WriteLine("TLV Expire " + expireTime);
|
|||
|
//jump to next tlv
|
|||
|
i += 1 + len;
|
|||
|
break;
|
|||
|
|
|||
|
//Decode Entity TLV
|
|||
|
case 10:
|
|||
|
tag = data[i];
|
|||
|
len = data[i + 1];
|
|||
|
value_arr = new byte[len];
|
|||
|
Array.Copy(data, i + 2, value_arr, 0, len);
|
|||
|
string suid = Encoding.Unicode.GetString(value_arr);
|
|||
|
nResp.SUID = suid;
|
|||
|
//Utils.WriteLine("TLV Entity " + suid);
|
|||
|
//jump to next tlv
|
|||
|
i += 1 + len;
|
|||
|
nResp.Error = false;
|
|||
|
break;
|
|||
|
|
|||
|
//Decode Event TLV ... "1" - Present, "2" - Absent
|
|||
|
case 2:
|
|||
|
tag = data[i];
|
|||
|
len = data[i + 1];
|
|||
|
value_arr = new byte[len];
|
|||
|
Array.Copy(data, i + 2, value_arr, 0, len);
|
|||
|
string event_string = Encoding.Unicode.GetString(value_arr);
|
|||
|
//nResp.Active = (event_string == "1");
|
|||
|
//Utils.WriteLine("TLV Event " + event_string);
|
|||
|
//jump to next tlv
|
|||
|
i += 1 + len;
|
|||
|
break;
|
|||
|
case 14:
|
|||
|
tag = data[i];
|
|||
|
len = data[i + 1];
|
|||
|
value_arr = new byte[len];
|
|||
|
Array.Copy(data, i + 2, value_arr, 0, len);
|
|||
|
string presence = Encoding.Unicode.GetString(value_arr);
|
|||
|
|
|||
|
switch (presence)
|
|||
|
{
|
|||
|
case "0":
|
|||
|
//Console.WriteLine("Presence state TLV: unknown value:" + presence);
|
|||
|
break;
|
|||
|
case "1":
|
|||
|
nResp.Active = true;
|
|||
|
//Console.WriteLine("Presence state TLV: present value:" + presence);
|
|||
|
break;
|
|||
|
case "2":
|
|||
|
nResp.Active = false;
|
|||
|
//Console.WriteLine("Presence state TLV: absent value:" + presence);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//jump to next tlv
|
|||
|
i += 1 + len;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return nResp;
|
|||
|
}
|
|||
|
|
|||
|
public void Send(byte[] data, int len)
|
|||
|
{
|
|||
|
if (clientStream != null)
|
|||
|
{
|
|||
|
clientStream.Write(data, 0, len);
|
|||
|
clientStream.Flush();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region Subscribe messages and PONG message
|
|||
|
/// <summary>
|
|||
|
/// Send the subcribe message to the controler
|
|||
|
/// </summary>
|
|||
|
/// <param name="dialogID">unique dialog ID</param>
|
|||
|
/// <param name="ID">ID of radio subscriber that is being watched</param>
|
|||
|
/// <param name="expiresTime">time to live of the subscription</param>
|
|||
|
public void Subscribe(int dialogID, int ID, byte expiresTime)
|
|||
|
{
|
|||
|
//Utils.WriteLine(ConsoleType.ALL, "DialogID:" + dialogID);
|
|||
|
byte[] tempID = convertInt2ByteLE(ID);
|
|||
|
|
|||
|
byte[] msg = new byte[18 + tempID.Length];
|
|||
|
//length
|
|||
|
msg[0] = 0x00;
|
|||
|
msg[1] = Convert.ToByte(0x10 + tempID.Length);
|
|||
|
// message ID
|
|||
|
msg[2] = 0x03;
|
|||
|
// Dialog ID
|
|||
|
byte[] tempDialogID = BitConverter.GetBytes(dialogID);
|
|||
|
msg[3] = tempDialogID[1];
|
|||
|
msg[4] = tempDialogID[0];
|
|||
|
//Message BODY
|
|||
|
//The Expires TLV Field
|
|||
|
msg[5] = 0x01;
|
|||
|
msg[6] = 0x01;
|
|||
|
msg[7] = expiresTime;
|
|||
|
//The TCPPort TLV Field
|
|||
|
msg[8] = 0x06;
|
|||
|
msg[9] = 0x02;
|
|||
|
byte[] tempPort = BitConverter.GetBytes(0x3344);
|
|||
|
msg[10] = tempPort[1];
|
|||
|
msg[11] = tempPort[0];
|
|||
|
//The Entities TLV Field
|
|||
|
msg[12] = 0x0a;
|
|||
|
msg[13] = Convert.ToByte(tempID.Length);
|
|||
|
// ID
|
|||
|
for (int i = 0; i < tempID.Length; i++)
|
|||
|
{
|
|||
|
msg[14 + i] = tempID[i];
|
|||
|
}
|
|||
|
|
|||
|
//The Events TLV Field
|
|||
|
msg[14 + tempID.Length] = 0x02;
|
|||
|
msg[14 + tempID.Length + 1] = 0x02;
|
|||
|
msg[14 + tempID.Length + 2] = 0x31;
|
|||
|
msg[14 + tempID.Length + 3] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
//Console.WriteLine("-----------Sent Subscribe to the controller-----");
|
|||
|
//Print(msg, msg.Length, false);
|
|||
|
}
|
|||
|
|
|||
|
public void SubscribeALL(int dialogID)
|
|||
|
{
|
|||
|
byte[] msg = new byte[23];
|
|||
|
//length
|
|||
|
msg[0] = 0x15;
|
|||
|
msg[1] = 0x00;
|
|||
|
// message ID
|
|||
|
msg[2] = 20;
|
|||
|
// Dialog ID
|
|||
|
byte[] tempDialogID = BitConverter.GetBytes(dialogID);
|
|||
|
msg[3] = tempDialogID[1];
|
|||
|
msg[4] = tempDialogID[0];
|
|||
|
|
|||
|
//Message BODY
|
|||
|
//The Expires TLV Field (2^32 secs = ~ 136 years)
|
|||
|
msg[5] = 0x01;
|
|||
|
msg[6] = 0x04;
|
|||
|
msg[7] = 0xff;
|
|||
|
msg[8] = 0xff;
|
|||
|
msg[9] = 0xff;
|
|||
|
msg[10] = 0xff;
|
|||
|
//The Entities TLV Field
|
|||
|
msg[11] = 0x0a;
|
|||
|
msg[12] = 0x02;
|
|||
|
// ID:all
|
|||
|
msg[13] = 0x2a;
|
|||
|
msg[14] = 0x00;
|
|||
|
//The Events TLV Field
|
|||
|
msg[15] = 0x02;
|
|||
|
msg[16] = 0x06;
|
|||
|
msg[17] = (byte)'1';
|
|||
|
msg[18] = 0x00;
|
|||
|
msg[19] = (byte)',';
|
|||
|
msg[20] = 0x00;
|
|||
|
msg[21] = (byte)'2';
|
|||
|
msg[22] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
Utils.WriteLine("««« Subscribe ALL Message to the controller");
|
|||
|
//Print(msg, msg.Length, false);
|
|||
|
}
|
|||
|
|
|||
|
public void SubscribeOneTime(int dialogID, string suid)// TLV expire =0
|
|||
|
{
|
|||
|
//Utils.ConsWrite(DebugMSG_Type.DEV, "DialogID:" + dialogID);
|
|||
|
char[] suidARR = suid.ToCharArray();
|
|||
|
|
|||
|
byte[] msg = new byte[18 + suidARR.Length*2];
|
|||
|
//length
|
|||
|
msg[0] = 0x00;
|
|||
|
msg[1] = (byte)(16 + suidARR.Length * 2);
|
|||
|
// message ID
|
|||
|
msg[2] = 0x03;
|
|||
|
// Dialog ID
|
|||
|
byte[] tempDialogID = BitConverter.GetBytes(dialogID);
|
|||
|
msg[3] = tempDialogID[1];
|
|||
|
msg[4] = tempDialogID[0];
|
|||
|
|
|||
|
//Message BODY
|
|||
|
//The Expires TLV Field
|
|||
|
msg[5] = 0x01;
|
|||
|
msg[6] = 0x01;
|
|||
|
msg[7] = 0x00;//one time
|
|||
|
//The Entities TLV Field
|
|||
|
msg[8] = 0x0a;
|
|||
|
msg[9] = (byte)(suidARR.Length*2);
|
|||
|
for (int i = 0; i < suidARR.Length; i++)
|
|||
|
{
|
|||
|
byte b = (byte)suidARR[i];
|
|||
|
//Console.WriteLine(b);
|
|||
|
msg[10 + i * 2] = b;
|
|||
|
msg[10 + i * 2 + 1] = 0x00;
|
|||
|
}
|
|||
|
//The Events TLV Field
|
|||
|
msg[10 + suidARR.Length * 2] = 0x02;
|
|||
|
msg[10 + suidARR.Length * 2 + 1] = 0x06;
|
|||
|
msg[10 + suidARR.Length * 2 + 2] = (byte)'1';
|
|||
|
msg[10 + suidARR.Length * 2 + 3] = 0x00;
|
|||
|
msg[10 + suidARR.Length * 2 + 4] = (byte)',';
|
|||
|
msg[10 + suidARR.Length * 2 + 5] = 0x00;
|
|||
|
msg[10 + suidARR.Length * 2 + 6] = (byte)'2';
|
|||
|
msg[10 + suidARR.Length * 2 + 7] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
//Console.WriteLine("-----------Sent Subscribe ALL to the controller-----");
|
|||
|
//Print(msg, msg.Length, false);
|
|||
|
}
|
|||
|
|
|||
|
public void SubscribeALL()
|
|||
|
{
|
|||
|
byte[] msg = new byte[17];
|
|||
|
//length
|
|||
|
msg[0] = 0x0f;
|
|||
|
msg[1] = 0x00;
|
|||
|
// message ID
|
|||
|
msg[2] = 20;
|
|||
|
// Dialog ID
|
|||
|
msg[3] = 0x33;
|
|||
|
msg[4] = 0x44;
|
|||
|
//Message BODY
|
|||
|
//The Expires TLV Field
|
|||
|
msg[5] = 0x01;
|
|||
|
msg[6] = 0x02;
|
|||
|
msg[7] = 0xff;
|
|||
|
msg[8] = 0xff;
|
|||
|
/*
|
|||
|
//The TCPPort TLV Field
|
|||
|
msg[8] = 0x06;
|
|||
|
msg[9] = 0x02;
|
|||
|
byte[] temp = BitConverter.GetBytes(0x3344);
|
|||
|
msg[10] = temp[1];
|
|||
|
msg[11] = temp[0];
|
|||
|
*/
|
|||
|
//The Entities TLV Field
|
|||
|
msg[9] = 0x0a;
|
|||
|
msg[10] = 0x02;
|
|||
|
// ID:all
|
|||
|
msg[11] = 0x2a;
|
|||
|
msg[12] = 0x00;
|
|||
|
//The Events TLV Field
|
|||
|
msg[13] = 0x02;
|
|||
|
msg[14] = 0x02;
|
|||
|
msg[15] = 0x2a;
|
|||
|
msg[16] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
Utils.WriteLine("««« Subscribe ALL Message to the controller");
|
|||
|
//Utils.ConsWrite(DebugMSG_Type.CTRL, "-----------Sent Subscribe to the controller-----");
|
|||
|
Print(msg, msg.Length, false);
|
|||
|
}
|
|||
|
|
|||
|
public void SubscribeList(int dialogID, List<string> suids)// TLV expire =0
|
|||
|
{
|
|||
|
//Utils.ConsWrite(DebugMSG_Type.DEV, "DialogID:" + dialogID);
|
|||
|
//create arr string: suid1,suid2,....,suidn
|
|||
|
string strSUIDS="";
|
|||
|
for (int i = 0; i < suids.Count; i++)
|
|||
|
{
|
|||
|
if (i != (suids.Count - 1))
|
|||
|
{
|
|||
|
strSUIDS += suids[i] + ",";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
strSUIDS += suids[i];
|
|||
|
}
|
|||
|
}
|
|||
|
//Utils.WriteLine(ConsoleType.ARS, "suids string:" + strSUIDS);
|
|||
|
|
|||
|
char[] suidARR = strSUIDS.ToCharArray();
|
|||
|
byte[] msg = new byte[15 + suidARR.Length * 2];
|
|||
|
//length
|
|||
|
msg[0] = 0x00;
|
|||
|
msg[1] = (byte)(13 + suidARR.Length * 2);
|
|||
|
// message ID
|
|||
|
msg[2] = 0x03;
|
|||
|
// Dialog ID
|
|||
|
byte[] tempDialogID = BitConverter.GetBytes(dialogID);
|
|||
|
msg[3] = tempDialogID[1];
|
|||
|
msg[4] = tempDialogID[0];
|
|||
|
|
|||
|
//Message BODY
|
|||
|
//The Expires TLV Field
|
|||
|
//msg[5] = 0x01;
|
|||
|
//msg[6] = 0x01;
|
|||
|
//msg[7] = 0x00;//one time
|
|||
|
//The Entities TLV Field
|
|||
|
msg[5] = 0x0a;
|
|||
|
msg[6] = (byte)(suidARR.Length * 2);
|
|||
|
for (int i = 0; i < suidARR.Length; i++)
|
|||
|
{
|
|||
|
byte b = (byte)suidARR[i];
|
|||
|
//Console.WriteLine(b);
|
|||
|
msg[7 + i * 2] = b;
|
|||
|
msg[7 + i * 2 + 1] = 0x00;
|
|||
|
}
|
|||
|
//The Events TLV Field
|
|||
|
msg[7 + suidARR.Length * 2] = 0x02;
|
|||
|
msg[7 + suidARR.Length * 2 + 1] = 0x06;
|
|||
|
msg[7 + suidARR.Length * 2 + 2] = (byte)'1';
|
|||
|
msg[7 + suidARR.Length * 2 + 3] = 0x00;
|
|||
|
msg[7 + suidARR.Length * 2 + 4] = (byte)',';
|
|||
|
msg[7 + suidARR.Length * 2 + 5] = 0x00;
|
|||
|
msg[7 + suidARR.Length * 2 + 6] = (byte)'2';
|
|||
|
msg[7 + suidARR.Length * 2 + 7] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
//Console.WriteLine("-----------Sent Subscribe ALL to the controller-----");
|
|||
|
//Print(msg, msg.Length, false);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//send PONG back to controller
|
|||
|
public void PONG()
|
|||
|
{
|
|||
|
byte[] msg = new byte[12];
|
|||
|
//length
|
|||
|
msg[0] = 0x00;
|
|||
|
msg[1] = 0x0a;
|
|||
|
// message ID
|
|||
|
msg[2] = 0xff;
|
|||
|
// body length
|
|||
|
msg[3] = 0x08;
|
|||
|
//PONG -utf16 LE string
|
|||
|
//P
|
|||
|
msg[4] = 0x50;
|
|||
|
msg[5] = 0x00;
|
|||
|
//O
|
|||
|
msg[6] = 0x4f;
|
|||
|
msg[7] = 0x00;
|
|||
|
//N
|
|||
|
msg[8] = 0x4e;
|
|||
|
msg[9] = 0x00;
|
|||
|
//G
|
|||
|
msg[10] = 0x47;
|
|||
|
msg[11] = 0x00;
|
|||
|
|
|||
|
Send(msg, msg.Length);
|
|||
|
Utils.WriteLine("««« PONG ");
|
|||
|
//Utils.WriteLine(ConsoleType.ALL, "-----------Sent PONG to the controller-----");
|
|||
|
//Print(msg, msg.Length, false, "PONG:");
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region AUX methods
|
|||
|
private void Print(byte[] data, int length, bool inOut)
|
|||
|
{
|
|||
|
//Console.Clear();
|
|||
|
Console.WriteLine("--------------------------------------------------------------------------- " + length);
|
|||
|
Console.Write("Data (" + ((inOut) ? "RECEIVED" : "SENT") + "): ");
|
|||
|
for (int i = 0; i < length; i++)
|
|||
|
Console.Write(" 0x" + data[i].ToString("X2"));
|
|||
|
Console.WriteLine("");
|
|||
|
Console.WriteLine("--------------------------------------------------------------------------- ");
|
|||
|
}
|
|||
|
|
|||
|
private static byte[] convertInt2ByteLE(int id)
|
|||
|
{
|
|||
|
Byte[] retBytes = Encoding.Unicode.GetBytes(id.ToString());
|
|||
|
return retBytes;
|
|||
|
}
|
|||
|
|
|||
|
private int ConvertByteArr2Int(byte[] arr)
|
|||
|
{
|
|||
|
byte[] worker = new byte[4];
|
|||
|
arr.CopyTo(worker, 0);
|
|||
|
return BitConverter.ToInt32(worker, 0);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
public delegate void ARSReceived(Int64 radioID, bool isON);
|
|||
|
public event ARSReceived OnARSReceived;
|
|||
|
|
|||
|
|
|||
|
public delegate void ConnectionStatusDEl(bool isUP);
|
|||
|
public event ConnectionStatusDEl OnDdmsConnectionStatusChanged;
|
|||
|
|
|||
|
public delegate void TriggeredLocationRequestDEl(String radioID, int reportingInterval);
|
|||
|
public event TriggeredLocationRequestDEl OnTriggeredLocationRequest;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public class NotifyRespons
|
|||
|
{
|
|||
|
private string suid;
|
|||
|
public string SUID
|
|||
|
{
|
|||
|
get { return suid; }
|
|||
|
set { suid = value; }
|
|||
|
}
|
|||
|
|
|||
|
private bool active;
|
|||
|
public bool Active
|
|||
|
{
|
|||
|
get { return active; }
|
|||
|
set { active = value; }
|
|||
|
}
|
|||
|
|
|||
|
private int dialogID;
|
|||
|
public int DialogID
|
|||
|
{
|
|||
|
get { return dialogID; }
|
|||
|
set { dialogID = value; }
|
|||
|
}
|
|||
|
|
|||
|
private bool error;
|
|||
|
public bool Error
|
|||
|
{
|
|||
|
get { return error; }
|
|||
|
set { error = value; }
|
|||
|
}
|
|||
|
|
|||
|
private bool pollResponse;
|
|||
|
|
|||
|
public bool PollResponse
|
|||
|
{
|
|||
|
get { return pollResponse; }
|
|||
|
set { pollResponse = value; }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|