package art.servers.pvvserver.controller;
import art.library.interop.InteropParameters;
import art.library.interop.serialization.Serialization;
import art.library.interop.serialization.SerializationException;
import art.library.model.devices.DeviceAction;
import art.library.model.devices.DeviceActionResult;
import art.library.model.devices.DeviceCommands;
import art.library.model.devices.vms.pvv.Pvv;
import art.library.model.devices.vms.pvv.PvvCommands;
import art.library.model.devices.vms.pvv.PvvStatus;
import art.library.utils.synchro.Mutex;
import art.servers.ServerException;
import art.servers.Shared;
import art.servers.pvvserver.protocols.dgt.clv.ClvDgtConstants;
import art.servers.pvvserver.protocols.dgt.clv.ClvDgtPDU;
import art.servers.pvvserver.protocols.dgt.clv.ClvDgtProtocolAnalyser;
import art.servers.pvvserver.protocols.dgt.clv.ClvDgtProtocolConstructor;
import java.util.List;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
public class ControllerClvDGTTcp extends ControllerPvv
{
private String name = null;
private boolean firstTime = true;
private final Mutex mutex = new Mutex();
private Socket socket = null;
private InputStream is = null;
private OutputStream os = null;
private boolean connected = false;
public ControllerClvDGTTcp(Pvv pvv)
{
super(pvv);
this.device = pvv;
this.name = Shared.getMessage("Controller pvv dgt tcp") + " " + pvv.toString();
this.setName(name);
if (device.getDeviceStatus() == null)
{
device.status = new PvvStatus();
}
}
public void run()
{
Shared.traceInformation(name, "Starting");
while ((isInterrupted() == false) && (exit == false))
{
long startTimestamp = System.currentTimeMillis();
try
{
if (art.servers.Shared.isServerEnabled() == true)
{
connect();
update();
}
} catch (Exception e)
{
}
long timetowait = (device.getDeviceInformation().polling * 1000) - (System.currentTimeMillis() - startTimestamp);
timetowait = Math.min(timetowait, (device.getDeviceInformation().polling * 1000));
if (timetowait > 0)
{
try
{
sleep(timetowait);
} catch (Exception e)
{
}
} else
{
try
{
sleep(50);
} catch (Exception e)
{
}
}
if (Shared.model.existsDevice(device.getIdentifier()) == false)
{
exit = true;
}
}
Shared.traceInformation(name, "Finishing");
}
//
private void update() throws Exception
{
mutex.lockWrite();
Pvv deviceclone = (Pvv) Serialization.clone(device);
try
{
deviceclone.getDeviceAlarms().clear();
readAlarms(deviceclone);
if (deviceclone.getAlarm("alarm_offline") > 0)
{
offline(deviceclone);
return;
}
readConfiguration(deviceclone);
readStatus(deviceclone);
online(deviceclone);
} catch (Exception e)
{
offline(deviceclone);
} finally
{
try
{
Shared.model.updateDevice(device, deviceclone);
} finally
{
mutex.releaseWrite();
}
}
}
private void offline(Pvv deviceclone) throws Exception
{
if ((device.alarms.alarm_offline <= 0) || (firstTime == true))
{
firstTime = false;
String message = art.servers.Shared.getMessage("Asf offline");
art.servers.Shared.println(name, message);
}
deviceclone.setAlarm("alarm_offline", System.currentTimeMillis());
Shared.model.updateDevice(device, deviceclone);
}
private void online(Pvv deviceclone) throws Exception
{
if ((device.alarms.alarm_offline > 0) || (firstTime == true))
{
firstTime = false;
String message = art.servers.Shared.getMessage("Asf online");
Shared.println(this.name, message);
}
deviceclone.setAlarm("alarm_offline", false);
deviceclone.setAlarm("alarm_invalid", false);
Shared.model.updateDevice(device, deviceclone);
}
private void readAlarms(Pvv deviceclone) throws Exception
{
try
{
byte[] command = ClvDgtProtocolConstructor.readAlarms(deviceclone.getDeviceInformation().connectionTcp.logicalAddress);
ClvDgtPDU response = read(command);
if ((response.function == ClvDgtConstants.STR_ICLV_ALR)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseEyA(deviceclone, response.information);
}
} catch (Exception e)
{
throw e;
}
}
private void readConfiguration(Pvv deviceclone) throws Exception
{
try
{
byte[] command = ClvDgtProtocolConstructor.readConfiguration(deviceclone.getDeviceInformation().connectionTcp.logicalAddress);
ClvDgtPDU response = read(command);
if ((response.function == ClvDgtConstants.STR_ICLV_PP)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponsePP(deviceclone, response.information);
}
} catch (Exception e)
{
throw e;
}
}
private void readStatus(Pvv deviceclone) throws Exception
{
try
{
byte[] command = ClvDgtProtocolConstructor.readMessage(deviceclone.getDeviceInformation().connectionTcp.logicalAddress);
ClvDgtPDU response = read(command);
if ((response.function == ClvDgtConstants.STR_ICLV_PP)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseEP(deviceclone, response.information);
}
} catch (Exception e)
{
e.printStackTrace();
throw e;
}
}
//
//
public DeviceAction[] sendCommands(InteropParameters parameters) throws ServerException, SerializationException, Exception
{
try
{
List result = new ArrayList<>();
PvvCommands pvvCommands = (PvvCommands) parameters.getBodyContentValue(PvvCommands.class);
Pvv clone = (Pvv) Serialization.clone(device);
if (pvvCommands.liberate == DeviceCommands.CONDITION_YES)
{
PvvCommands command = new PvvCommands();
command.liberate = pvvCommands.liberate;
result.add(liberate(parameters, command, clone));
}
if (pvvCommands.message != null)
{
PvvCommands command = new PvvCommands();
command.message = pvvCommands.message;
command.priority = pvvCommands.priority;
result.add(mep(parameters, command, clone));
}
if (pvvCommands.reset == PvvCommands.CONDITION_YES)
{
PvvCommands command = new PvvCommands();
command.reset = pvvCommands.reset;
result.add(reset(parameters, command, clone));
}
mutex.lockWrite();
{
Shared.model.updateDevice(device, clone);
}
mutex.releaseWrite();
return result.toArray(new DeviceAction[result.size()]);
} catch (Exception exception)
{
return (art.servers.pvvserver.Shared.responseError(device, parameters, exception));
}
}
/*
private DeviceAction mpp(InteropParameters parameters, PvvCommands command, Pvv deviceclone)
{
String language = (String) parameters.getParameterValue("language");
DeviceAction action = new DeviceAction(device, parameters, command);
action.actionName = command.getActionName();
try
{
int currentPriority = this.device.getDeviceStatus().priority;
if ((command.priority >= 0) && (command.priority < currentPriority))
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, Shared.getMessage("Insufficient priority"));
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
} else
{
byte[] commandByte = ClvDgtProtocolConstructor.mpp(deviceclone.getDeviceInformation().connectionTcp.logicalAddress, command, deviceclone);
ClvDgtPDU response = read(commandByte);
if ((response.function == ClvDgtConstants.STR_OCLV_MPP)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseMPP(deviceclone, response.information);
}
deviceclone.getDeviceStatus().priority = command.priority;
deviceclone.getDeviceStatus().timestampOrder = System.currentTimeMillis();
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_CORRECT);
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
} catch (Exception exception)
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, exception.getMessage());
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
}
*/
private DeviceAction reset(InteropParameters parameters, PvvCommands command, Pvv deviceclone)
{
String language = (String) parameters.getParameterValue("language");
DeviceAction action = new DeviceAction(device, parameters, command);
action.actionName = command.getActionName();
try
{
int currentPriority = this.device.getDeviceStatus().priority;
if ((command.priority >= 0) && (command.priority < currentPriority))
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, Shared.getMessage("Insufficient priority"));
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
} else
{
byte[] commandByte = ClvDgtProtocolConstructor.reset(deviceclone.getDeviceInformation().connectionTcp.logicalAddress);
ClvDgtPDU response = read(commandByte);
if ((response.function == ClvDgtConstants.STR_OCLV_RES)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseReset(response.information);
}
deviceclone.getDeviceStatus().priority = command.priority;
deviceclone.getDeviceStatus().timestampOrder = System.currentTimeMillis();
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_CORRECT);
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
} catch (Exception exception)
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, exception.getMessage());
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
}
/*
private DeviceAction timeout(InteropParameters parameters, PvvCommands command, Pvv deviceclone)
{
String language = (String) parameters.getParameterValue("language");
DeviceAction action = new DeviceAction(device, parameters, command);
action.actionName = command.getActionName();
try
{
int currentPriority = this.device.getDeviceStatus().priority;
if ((command.priority >= 0) && (command.priority < currentPriority))
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, Shared.getMessage("Insufficient priority"));
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
} else
{
byte[] commandByte = ClvDgtProtocolConstructor.timeout(deviceclone.getDeviceInformation().connectionTcp.logicalAddress, command, deviceclone);
ClvDgtPDU response = read(commandByte);
if ((response.function == ClvDgtConstants.STR_OCLV_MPP)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseTimeout(response.information);
}
deviceclone.getDeviceStatus().priority = command.priority;
deviceclone.getDeviceStatus().timestampOrder = System.currentTimeMillis();
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_CORRECT);
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
} catch (Exception exception)
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, exception.getMessage());
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
}
*/
private DeviceAction liberate(InteropParameters parameters, PvvCommands command, Pvv deviceclone)
{
String language = (String) parameters.getParameterValue("language");
DeviceAction action = new DeviceAction(device, parameters, command);
action.actionName = command.getActionName();
try
{
deviceclone.getDeviceStatus().priority = -1;
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_CORRECT);
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
} catch (Exception exception)
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, exception.getMessage());
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
}
private DeviceAction mep(InteropParameters parameters, PvvCommands command, Pvv deviceclone)
{
String language = (String) parameters.getParameterValue("language");
String username = (String) parameters.getParameterValue("username");
DeviceAction action = new DeviceAction(device, parameters, command);
action.actionName = command.getActionName();
try
{
int currentPriority = this.device.getDeviceStatus().priority;
if ((command.priority >= 0) && (command.priority < currentPriority))
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, Shared.getMessage("Insufficient priority"));
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
} else
{
byte[] commandByte = ClvDgtProtocolConstructor.mep(deviceclone.getDeviceInformation().connectionTcp.logicalAddress, command, deviceclone);
ClvDgtPDU response = read(commandByte);
if ((response.function == ClvDgtConstants.STR_OCLV_MEP)
&& (response.address == deviceclone.getDeviceInformation().connectionTcp.logicalAddress))
{
ClvDgtProtocolAnalyser.analyseResponseMEP(deviceclone, response.information);
}
deviceclone.getDeviceStatus().priority = command.priority;
deviceclone.getDeviceStatus().timestampOrder = System.currentTimeMillis();
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_CORRECT);
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
} catch (Exception exception)
{
DeviceActionResult actionResult = new DeviceActionResult(DeviceActionResult.RESULT_ERROR, exception.getMessage());
action.setResult(actionResult);
Shared.model.addAction(action);
return action;
}
}
//
//
private void connect()
{
try
{
if (socket != null)
{
if (this.connected == true)
{
return;
}
}
disconnect();
InetAddress inetAddress = InetAddress.getByName(device.getDeviceInformation().connectionTcp.address);
SocketAddress sockaddress = new InetSocketAddress(inetAddress, device.getDeviceInformation().connectionTcp.port);
socket = new Socket();
socket.connect(sockaddress, 2000);
socket.setSoLinger(true, 1);
socket.setSoTimeout(device.getDeviceInformation().connectionTcp.timeout);
is = socket.getInputStream();
os = socket.getOutputStream();
this.connected = true;
} catch (Exception e)
{
try
{
disconnect();
} catch (Exception ex)
{
};
}
}
public void disconnect() throws Exception
{
try
{
is.close();
} catch (Exception e)
{
}
try
{
os.close();
} catch (Exception e)
{
}
try
{
socket.close();
} catch (Exception e)
{
}
is = null;
os = null;
socket = null;
this.connected = false;
}
private ClvDgtPDU read(byte[] command) throws Exception
{
try
{
mutex.lockWrite();
send(command);
return (listen());
} catch (Exception e)
{
disconnect();
throw e;
} finally
{
mutex.releaseWrite();
}
}
private void send(byte[] command) throws Exception
{
connect();
if (is != null)
{
is.skip(0);
}
os.write(command);
os.flush();
}
private ClvDgtPDU listen() throws Exception
{
try
{
connect();
ClvDgtPDU pdu = new ClvDgtPDU();
pdu.stx = readByte();
if (pdu.stx == ClvDgtConstants.CLV_ACK)
{
pdu.ack = true;
return (pdu);
} else if (pdu.stx != ClvDgtConstants.CLV_STX)
{
while ((pdu.stx != ClvDgtConstants.CLV_STX)
&& (pdu.stx != ClvDgtConstants.CLV_ETX)
&& (pdu.stx != 0xFF)
&& (pdu.stx != ClvDgtConstants.CLV_ACK))
{
pdu.stx = readByte();
}
if (pdu.stx == ClvDgtConstants.CLV_ACK)
{
pdu.ack = true;
return (pdu);
}
if (pdu.stx != ClvDgtConstants.CLV_STX)
{
if (pdu.stx == ClvDgtConstants.CLV_ETX)
{
pdu.stx = readByte();
}
if (pdu.stx != ClvDgtConstants.CLV_STX)
{
throw new Exception("Message not start with STX: " + pdu.stx + " - " + readByte());
}
}
}
// Message starts with STX
pdu.address = readByte();
pdu.function = readByte();
ArrayList list = new ArrayList();
list.add(new Integer(pdu.stx));
list.add(new Integer(pdu.address));
list.add(new Integer(pdu.function));
// Read until the reading of ETX byte
int value = readByte();
while (value != ClvDgtConstants.CLV_ETX)
{
list.add(new Integer(value));
value = readByte();
}
list.add(new Integer(value));
pdu.etx = value;
int[] message = new int[list.size()];
for (int i = 0; i < message.length; i++)
{
message[i] = ((Integer) list.get(i)).intValue();
}
message = pdu.removeStuffing(message);
pdu.information = new int[message.length - 6];
System.arraycopy(message, 3, pdu.information, 0, pdu.information.length);
return pdu;
} catch (SocketTimeoutException e)
{
throw e;
} catch (Exception e)
{
int value = readByte();
try
{
while ((value != ClvDgtConstants.CLV_ETX)
&& (value != 0xFF))
{
value = readByte();
}
} catch (Exception ex)
{
}
throw e;
}
}
/**
* TCP Socket reading functions
*/
public int readByte() throws Exception
{
int value = is.read();
if (value < 0)
{
value += 256;
}
return (value);
}
public int readShort() throws Exception
{
return ((readByte() << 8) + readByte());
}
public int[] readBytes(int len) throws Exception
{
byte[] data = new byte[len];
is.read(data);
int[] result = new int[data.length];
for (int i = 0; i < result.length; i++)
{
result[i] = (int) data[i];
if (result[i] < 0)
{
result[i] += 256;
}
}
return (result);
}
//
}