314 lines
13 KiB
C#
314 lines
13 KiB
C#
|
using System;
|
|||
|
using System.Net;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Text;
|
|||
|
using MotoTRBO_GW;
|
|||
|
using System.Threading;
|
|||
|
using SafeMobileLib;
|
|||
|
|
|||
|
namespace MotoTrbo_GW
|
|||
|
{
|
|||
|
public class ARSThread
|
|||
|
{
|
|||
|
private Int32 port;
|
|||
|
|
|||
|
private Boolean capacityPlus;
|
|||
|
private String trboLocalIP = "";
|
|||
|
private String trboRemoteIP = "";
|
|||
|
private String trboID = "";
|
|||
|
private UdpMulticast udpMulticast;
|
|||
|
public static DBvehiclesManager vehiclesManager;
|
|||
|
private UdpClient udpClient=null;
|
|||
|
private String mIP;
|
|||
|
private Int32 mPort;
|
|||
|
|
|||
|
public ARSThread(GatewayID_IP trboID_IP, Int32 arsPort, Boolean capPlus, String multicastIP, String multicastPort)
|
|||
|
{
|
|||
|
vehiclesManager = new DBvehiclesManager(Main.DBServer, Main.DBSchema, Main.DBUser, Main.DBPass, Main.DBPort);
|
|||
|
port = arsPort;
|
|||
|
capacityPlus = capPlus;
|
|||
|
SafeMobileLib.Utils.WriteLine("trboID_IP.localIP:" + trboID_IP.localIP + " trboID_IP.remoteIP:" + trboID_IP.remoteIP);
|
|||
|
trboLocalIP = trboID_IP.localIP;
|
|||
|
trboRemoteIP = trboID_IP.remoteIP;
|
|||
|
trboID = trboID_IP.ID;
|
|||
|
mIP = multicastIP;
|
|||
|
try
|
|||
|
{
|
|||
|
mPort = Convert.ToInt32(multicastPort);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Erorr conver port:"+ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void handleConnection()
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS Thread - Initialized on port " + port + " for " + trboLocalIP);
|
|||
|
try
|
|||
|
{
|
|||
|
IPEndPoint ie;
|
|||
|
if (!capacityPlus)
|
|||
|
{
|
|||
|
IPAddress ipAddress = IPAddress.Parse(trboLocalIP);
|
|||
|
ie = new IPEndPoint(ipAddress, port);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ie = new IPEndPoint(IPAddress.Any, port);
|
|||
|
}
|
|||
|
udpClient = new UdpClient(ie);
|
|||
|
//Console.ReadKey();
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("\ntrboLocalIP:" + trboLocalIP);
|
|||
|
SafeMobileLib.Utils.WriteLine("ARSThread handleConnection exception INIT udpclient: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
udpMulticast = new UdpMulticast(mIP,mPort);
|
|||
|
udpMulticast.OnNewDataRecv += new UdpMulticast.newData4Send(udpMulticast_OnNewDataRecv);
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS thread successfully registered to multicast group");
|
|||
|
udpMulticast.StartListen(Main.LocalIP);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS Thread exception while joining the multicast group: " + ex.ToString());
|
|||
|
}
|
|||
|
|
|||
|
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS Thread - Waiting for ARS");
|
|||
|
while (true)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine(" ARS step 1");
|
|||
|
// Blocks until a message returns on this socket from a remote host.
|
|||
|
Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint);
|
|||
|
//SafeMobileLib.Utils.WriteLine(" ARS step 2");
|
|||
|
char[] separator = { '.' };
|
|||
|
string[] su = remoteIpEndPoint.Address.ToString().Split(separator);
|
|||
|
uint radioID = (Convert.ToUInt32(su[1])) * 256 * 256 + (Convert.ToUInt32(su[2])) * 256 + Convert.ToUInt32(su[3]);
|
|||
|
string suid = radioID.ToString();
|
|||
|
//SafeMobileLib.Utils.WriteLine(" ARS step 3");
|
|||
|
header_T reth = DecodePacket(receivedBytes);
|
|||
|
SafeMobileLib.Utils.WriteLine($"Reth event: >>>>>>>>>>>>>>>> {reth.events.ToString()}", ConsoleColor.Cyan);
|
|||
|
//SafeMobileLib.Utils.WriteLine(" ARS step 4");
|
|||
|
if (reth.events == header_event.Initial_Event || reth.events == header_event.Refresh_Event)
|
|||
|
{
|
|||
|
//register route
|
|||
|
if (!capacityPlus)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("ARSThread received ARS from field unit with ID "
|
|||
|
+ suid + " on gateway radio with IP " + trboLocalIP, ConsoleColor.Magenta);
|
|||
|
if (RouteManager.NetworkIDs_Hash.ContainsKey(trboRemoteIP))
|
|||
|
{
|
|||
|
RoutingUtils.addRoute(suid, trboRemoteIP, RouteManager.NetworkIDs_Hash[trboRemoteIP].ToString());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("RouteManager.NetworkIDs_Hash does not contain a key for " + trboRemoteIP);
|
|||
|
}
|
|||
|
//RoutingUtils.displayRoutes();
|
|||
|
}
|
|||
|
|
|||
|
// Sends ACK
|
|||
|
Byte[] sendBytes = { 0x00, 0x02, 0xBF, 0x00 };
|
|||
|
int i = udpClient.Send(sendBytes, sendBytes.Length, remoteIpEndPoint.Address.ToString(), remoteIpEndPoint.Port);
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS ACK sent to " + remoteIpEndPoint.Address.ToString() + ":" + remoteIpEndPoint.Port.ToString());
|
|||
|
}
|
|||
|
|
|||
|
if (reth.pdu_type == 0x00)
|
|||
|
{
|
|||
|
int report_time = vehiclesManager.getReportingInterval(radioID.ToString());
|
|||
|
LocationThread.SendTriggeredLocationRequest(suid, report_time);
|
|||
|
}
|
|||
|
|
|||
|
//SafeMobileLib.Utils.WriteLine("ARS Thread received data from radio " + radioID + ": ");
|
|||
|
//Utils.printBytesArray(receivedBytes);
|
|||
|
|
|||
|
//put information on message bus
|
|||
|
byte[] arsStatus = new byte[] {(byte)'O',(byte)'N'};
|
|||
|
bool isOn = true;
|
|||
|
switch (reth.pdu_type)
|
|||
|
{
|
|||
|
case 0x00: arsStatus = arsStatus = new byte[] { (byte)'O', (byte)'N' }; isOn = true; break;
|
|||
|
case 0x01: arsStatus = arsStatus = new byte[] { (byte)'O', (byte)'F', (byte)'F' }; isOn = false; break;
|
|||
|
default: break;
|
|||
|
}
|
|||
|
if (reth.pdu_type == 0x00 || reth.pdu_type == 0x01)
|
|||
|
{
|
|||
|
string sequenceID = "";
|
|||
|
|
|||
|
// trigger ARS received event
|
|||
|
Int64 suId = 0;
|
|||
|
Int64.TryParse(suid, out suId);
|
|||
|
OnArsReceived?.Invoke(suId, isOn);
|
|||
|
|
|||
|
Byte[] toSendMulticast = Utils.createMulticastMessage(130, suid, arsStatus, out sequenceID);
|
|||
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|||
|
//SafeMobileLib.Utils.WriteLine("ARS thread successfully sent data to message bus");
|
|||
|
}
|
|||
|
//send Subscriber system location
|
|||
|
string seqID = "0.0";
|
|||
|
//build string
|
|||
|
string fullSource = Main.GWID.ToString() + "#" + trboRemoteIP + "#" + suid;
|
|||
|
if (capacityPlus) fullSource = Main.GWID.ToString() + "#" + Main.masterRadioIP + "#" + suid;
|
|||
|
|
|||
|
string test = "#139#" + fullSource + "#";
|
|||
|
String cmdok = "#" + seqID + test; Int32 tmp = cmdok.Length + 1; tmp += tmp.ToString().Length; cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
System.Text.Encoding enc = System.Text.Encoding.ASCII;
|
|||
|
byte[] buf = enc.GetBytes(cmdok);
|
|||
|
|
|||
|
//send to messagebus
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
Thread.Sleep(100);
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("##### ARSThread Exception #########\n" + e.ToString(), ConsoleColor.Red);
|
|||
|
Thread.Sleep(15000);
|
|||
|
//break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void udpMulticast_OnNewDataRecv(byte[] data, int dataLen)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string str = System.Text.Encoding.ASCII.GetString(data, 0, dataLen);
|
|||
|
String[] tempArray = str.Trim().Split('#');
|
|||
|
if (tempArray.Length > 3)
|
|||
|
{
|
|||
|
if (tempArray[3].Equals("154"))
|
|||
|
{
|
|||
|
Int64 gwid_recv = Convert.ToInt64((tempArray[4].Split('.'))[0]);
|
|||
|
if (gwid_recv == Main.GWID)
|
|||
|
{
|
|||
|
|
|||
|
//SafeMobileLib.Utils.WriteLine("ARSThread received from multicast bus: " + str.Trim());
|
|||
|
string SUID = (tempArray[4].Split('.'))[2];
|
|||
|
//QuerryUnit(SUID);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
struct header_T
|
|||
|
{
|
|||
|
public bool ext, ack, priority, cntl;
|
|||
|
public byte pdu_type;
|
|||
|
public SafeMobileLib.header_event events;
|
|||
|
public byte encoding;
|
|||
|
}
|
|||
|
|
|||
|
//todo: delete when commands are coming on multicast bus
|
|||
|
header_T DecodePacket(Byte[] data)
|
|||
|
{
|
|||
|
int i, pdata;
|
|||
|
|
|||
|
pdata = (int)data[0];
|
|||
|
pdata <<= 8;
|
|||
|
pdata |= (int)data[1];
|
|||
|
|
|||
|
// ----------------------------------------
|
|||
|
// parse header
|
|||
|
// ----------------------------------------
|
|||
|
header_T header = new header_T();
|
|||
|
header.ext = false;
|
|||
|
if ((data[2] & 0x80) != 0)
|
|||
|
header.ext = true;
|
|||
|
|
|||
|
header.ack = false;
|
|||
|
if ((data[2] & 0x40) != 0)
|
|||
|
header.ack = true;
|
|||
|
|
|||
|
header.priority = false;
|
|||
|
if ((data[2] & 0x20) != 0)
|
|||
|
header.priority = true;
|
|||
|
|
|||
|
header.cntl = false;
|
|||
|
if ((data[2] & 0x10) != 0)
|
|||
|
header.cntl = true;
|
|||
|
|
|||
|
header.pdu_type = (byte)(data[2] & 0x0F);
|
|||
|
|
|||
|
switch (header.pdu_type)
|
|||
|
{
|
|||
|
case 0x00: SafeMobileLib.Utils.WriteLine("ARS Registration"); break;
|
|||
|
case 0x0F: SafeMobileLib.Utils.WriteLine("Query ACK"); break;
|
|||
|
case 0x01: SafeMobileLib.Utils.WriteLine("Deregistration message"); break;
|
|||
|
default: SafeMobileLib.Utils.WriteLine("Unknown ARS message"); break;
|
|||
|
}
|
|||
|
|
|||
|
i = 3;
|
|||
|
if (i >= pdata + 2)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("--------------------");
|
|||
|
return header;
|
|||
|
}
|
|||
|
if (header.ext)
|
|||
|
{
|
|||
|
// read second header octet
|
|||
|
byte evt = data[i];
|
|||
|
evt &= 0x70;
|
|||
|
evt >>= 5;
|
|||
|
switch (evt)
|
|||
|
{
|
|||
|
case 0: header.events = header_event.Unqualified_Event; break;
|
|||
|
case 1: header.events = header_event.Initial_Event; break;
|
|||
|
case 2: header.events = header_event.Refresh_Event; break;
|
|||
|
default: header.events = header_event.UNKNOWN; break;
|
|||
|
}
|
|||
|
header.events = (header_event)evt;
|
|||
|
header.encoding = (byte)(data[i] & 0x0f);
|
|||
|
i++;
|
|||
|
}
|
|||
|
if (i >= pdata + 2)
|
|||
|
{
|
|||
|
return header;
|
|||
|
}
|
|||
|
|
|||
|
// ----------------------------------------
|
|||
|
// parse address len
|
|||
|
// ----------------------------------------
|
|||
|
int addr_len = data[i];
|
|||
|
i++;
|
|||
|
if (i >= pdata + 2)
|
|||
|
{
|
|||
|
return header;
|
|||
|
}
|
|||
|
i -= 2;
|
|||
|
return header;
|
|||
|
}
|
|||
|
|
|||
|
private void QuerryUnit(string SUID)
|
|||
|
{
|
|||
|
Byte[] sendBytes = { 0x00,
|
|||
|
0x01, // length in Bytes
|
|||
|
0x74 // querry
|
|||
|
};
|
|||
|
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
|
|||
|
SafeMobileLib.Utils.WriteLine("POLL ARS request sent to radio ID " + SUID);
|
|||
|
}
|
|||
|
|
|||
|
public delegate void ARSReceived(Int64 radioID, bool isON);
|
|||
|
public event ARSReceived OnArsReceived;
|
|||
|
}
|
|||
|
}
|