SafeDispatch/MotoTrbo_GW/ARSThread.cs
2024-02-22 18:43:59 +02:00

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