<commit_before>package org.eclipse.kura.net.admin.modem.telit.generic;

import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

import org.eclipse.kura.KuraErrorCode;
import org.eclipse.kura.KuraException;
import org.eclipse.kura.comm.CommConnection;
import org.eclipse.kura.comm.CommURI;
import org.eclipse.kura.linux.net.modem.SerialModemComm;
import org.eclipse.kura.linux.net.modem.SerialModemDriver;
import org.eclipse.kura.linux.net.modem.SupportedSerialModemInfo;
import org.eclipse.kura.linux.net.modem.SupportedSerialModemsInfo;
import org.eclipse.kura.linux.net.modem.SupportedUsbModemInfo;
import org.eclipse.kura.linux.net.modem.SupportedUsbModems;
import org.eclipse.kura.linux.net.modem.SupportedUsbModemsInfo;
import org.eclipse.kura.linux.net.util.KuraConstants;
import org.eclipse.kura.net.NetConfig;
import org.eclipse.kura.net.admin.modem.telit.he910.TelitHe910;
import org.eclipse.kura.net.modem.CellularModem.SerialPortType;
import org.eclipse.kura.net.modem.ModemDevice;
import org.eclipse.kura.net.modem.ModemTechnologyType;
import org.eclipse.kura.net.modem.SerialModemDevice;
import org.eclipse.kura.usb.UsbModemDevice;
import org.osgi.service.io.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class TelitModem {
	
	private static final Logger s_logger = LoggerFactory.getLogger(TelitModem.class);
	private static final String OS_VERSION = System.getProperty("kura.os.version");
	private static final String TARGET_NAME = System.getProperty("target.device");
	
	protected static Object s_atLock = new Object(); 
	
	protected String m_model;
	protected String m_manufacturer;
	protected String m_serialNumber;
	protected String m_revisionId;
	protected int m_rssi;
	protected Boolean m_gpsSupported;
	protected String m_imsi;
	protected String m_iccid;
	
	private boolean m_gpsEnabled;
	private ModemDevice m_device;
	private String m_platform;
	private ConnectionFactory m_connectionFactory;
	private ModemTechnologyType m_technologyType;
	private List<NetConfig> m_netConfigs = null;
	
	public TelitModem(ModemDevice device, String platform,
			ConnectionFactory connectionFactory,
			ModemTechnologyType technologyType) {
		
		m_device = device;
		m_platform = platform;
		m_connectionFactory = connectionFactory;
		m_technologyType = technologyType;
		m_gpsEnabled = false;
	}
	
	public void reset() throws KuraException {

		boolean status = false;
		int resetAttempts = 5;

		sleep(5000);
		while (resetAttempts > 0) {
			try {
				status = turnOff();
				if (status) {
					status = turnOn();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (status) {
				s_logger.info("reset() :: modem reset successful");
				break;
			} else {
				resetAttempts--;
				s_logger.info("reset() :: modem reset failed, attempts left: {}", resetAttempts);
				sleep(1000);
			}
		}
	}
	
	public String getModel() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_model == null) {
	    		s_logger.debug("sendCommand getModelNumber :: " + TelitModemAtCommands.getModelNumber.getCommand());
		    	byte[] reply = null;
		    	CommConnection commAtConnection = openSerialPort(getAtPort());
		    	if (!isAtReachable(commAtConnection)) {
		    		closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getModelNumber.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
					m_model = getResponseString(reply);
					reply = null;
				}
	    	}
    	}
        return m_model;
    }
	
	public String getManufacturer() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_manufacturer == null) {
		    	s_logger.debug("sendCommand getManufacturer :: " + TelitModemAtCommands.getManufacturer.getCommand());
		    	byte[] reply = null;
		    	CommConnection commAtConnection = openSerialPort(getAtPort());
		    	if (!isAtReachable(commAtConnection)) {
		    		closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
		    	try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getManufacturer.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
		    	closeSerialPort(commAtConnection);
				if (reply != null) {
				    m_manufacturer = getResponseString(reply); 
					reply = null;
				}
	    	}
    	}
        return m_manufacturer;
    }
	
	public String getSerialNumber() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_serialNumber == null) {
	    		s_logger.debug("sendCommand getSerialNumber :: " + TelitModemAtCommands.getSerialNumber.getCommand());
	    		byte[] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getSerialNumber.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
				    String serialNum = getResponseString(reply);
				    if(serialNum != null && !serialNum.isEmpty()) {
				    	if (serialNum.startsWith("#CGSN:")) {
				    		serialNum = serialNum.substring("#CGSN:".length()).trim();
				    	}
				    	m_serialNumber = serialNum;        
				    }
				}
	    	}
    	}
        return m_serialNumber;
    }
	
	public String getRevisionID() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_revisionId == null) {
	    		s_logger.debug("sendCommand getRevision :: " + TelitModemAtCommands.getRevision.getCommand());
	    		byte [] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
	    		try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getRevision.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
	    		closeSerialPort(commAtConnection);
				if (reply != null) {
					m_revisionId = getResponseString(reply);
				}
	    	}
    	}
        return m_revisionId;
    }
    
	public boolean isReachable() throws KuraException {
    	boolean ret = false;
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getAtPort());
    		ret = isAtReachable(commAtConnection);
    		closeSerialPort(commAtConnection);
    	}
		return ret;
	}
	
	public int getSignalStrength() throws KuraException {
    	
    	int signalStrength = -113;
    	synchronized (s_atLock) {
    		String atPort = getAtPort();
    		String gpsPort = getGpsPort();
			if ((atPort.equals(getDataPort()) || (atPort.equals(gpsPort)
					&& m_gpsEnabled)) && (m_rssi < 0)) {
				return m_rssi;
			}
	    	s_logger.debug("sendCommand getSignalStrength :: " + TelitModemAtCommands.getSignalStrength.getCommand());
	    	byte[] reply = null;
	    	CommConnection commAtConnection = openSerialPort(atPort);
	    	if (!isAtReachable(commAtConnection)) {
	    		closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
			try {
				reply = commAtConnection.sendCommand(TelitModemAtCommands.getSignalStrength.getCommand().getBytes(), 1000, 100);
			} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
			closeSerialPort(commAtConnection);
			if (reply != null) {
				String [] asCsq = null;
				String sCsq = this.getResponseString(reply);
				if (sCsq.startsWith("+CSQ:")) {
					sCsq = sCsq.substring("+CSQ:".length()).trim();
					s_logger.trace("getSignalStrength() :: +CSQ={}", sCsq);
					asCsq = sCsq.split(",");
					if (asCsq.length == 2) {
						int rssi = Integer.parseInt(asCsq[0]);
						if (rssi < 99) {
							signalStrength = -113 + 2 * rssi;
						}
						s_logger.trace("getSignalStrength() :: signalStrength={}", signalStrength);
					}
				}
				reply = null;
			}
    	}
    	m_rssi = signalStrength;
        return signalStrength;
    }
	
    public boolean isGpsSupported() throws KuraException {
    	synchronized (s_atLock) {
    		if (m_gpsSupported == null) {
	    		s_logger.debug("sendCommand isGpsSupported :: " + TelitModemAtCommands.isGpsPowered.getCommand());
	    		byte[] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
	    		
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.isGpsPowered.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
				    String sReply = getResponseString(reply);
				    if((sReply != null) && !sReply.isEmpty()) {
				    	if (sReply.startsWith("$GPSP:")) {
				    		m_gpsSupported = true;
				    	}
				    }
				}
    		}
    	}
    	boolean ret = false;
    	if (m_gpsSupported != null) {
    		ret = m_gpsSupported;
    	}
    	return ret;
    }
    
    public void enableGps() throws KuraException {
    	if ((m_gpsSupported == null) || (m_gpsSupported == false)) {
    		m_gpsEnabled = false;
    		return;
    	}
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getGpsPort());
    		if (!isAtReachable(commAtConnection)) {
    			closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
   
    		byte[] reply = null;
    		try {
    			if (!isGpsPowered(commAtConnection)) {
    				s_logger.debug("sendCommand gpsPowerUp :: " + TelitModemAtCommands.gpsPowerUp.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsPowerUp.getCommand().getBytes(), 1000, 100);
    			}
    			
    			s_logger.debug("sendCommand gpsEnableNMEA :: " + TelitModemAtCommands.gpsEnableNMEA.getCommand());
				reply = commAtConnection.sendCommand(TelitModemAtCommands.gpsEnableNMEA.getCommand().getBytes(), 3000, 100);
    		} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
    		closeSerialPort(commAtConnection);
    		
    		if (reply != null) {
			    String sReply = getResponseString(reply);
			    if((sReply != null) && !sReply.isEmpty()) {
			    	if (sReply.startsWith("CONECT"))
			    	s_logger.debug("NMEA Enabled");
			    }
    		}
    	}
    	
    	m_gpsEnabled = true;
    }
    
    public void disableGps() throws KuraException {
    	if ((m_gpsSupported == null) || (m_gpsSupported == false)) {
    		m_gpsEnabled = false;
    		return;
    	}
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getGpsPort());
    		if (!isAtReachable(commAtConnection)) {
    			closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
   
    		try {
    			if (!isGpsPowered(commAtConnection)) {
    				s_logger.debug("sendCommand gpsDisableNMEA :: " + TelitModemAtCommands.gpsDisableNMEA.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsDisableNMEA.getCommand().getBytes(), 1000, 100);
    				
    				s_logger.debug("sendCommand gpsPowerDown :: " + TelitModemAtCommands.gpsPowerDown.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsPowerDown.getCommand().getBytes(), 1000, 100);
    			}
    		} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
    		closeSerialPort(commAtConnection);
    	}
    	
    	m_gpsEnabled = false;
    }
    
    public String getMobileSubscriberIdentity() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_imsi == null) {
	    		if (isSimCardReady()) {
		    		s_logger.debug("sendCommand getIMSI :: " + TelitModemAtCommands.getIMSI.getCommand());
		    		byte[] reply = null;
		    		CommConnection commAtConnection = openSerialPort(getAtPort());
		    		if (!isAtReachable(commAtConnection)) {
		    			closeSerialPort(commAtConnection);
			    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
			    	}
					try {
						reply = commAtConnection.sendCommand(TelitModemAtCommands.getIMSI.getCommand().getBytes(), 1000, 100);
					} catch (IOException e) {
						closeSerialPort(commAtConnection);
						throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
					}
					closeSerialPort(commAtConnection);
					if (reply != null) {
					    String imsi = getResponseString(reply);
					    if(imsi != null && !imsi.isEmpty()) {
					    	if (imsi.startsWith("#CIMI:")) {
					    		imsi = imsi.substring("#CIMI:".length()).trim();
					    	}
					    	m_imsi = imsi;        
					    }
					}
	    		}
	    	}
    	}
        return m_imsi;
    }
    
    public String getIntegratedCirquitCardId() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_iccid == null) {
	    		if (isSimCardReady()) {
		    		s_logger.debug("sendCommand getICCID :: " + TelitModemAtCommands.getICCID.getCommand());
		    		byte[] reply = null;
		    		CommConnection commAtConnection = openSerialPort(getAtPort());
		    		if (!isAtReachable(commAtConnection)) {
		    			closeSerialPort(commAtConnection);
			    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
			    	}
					try {
						reply = commAtConnection.sendCommand(TelitModemAtCommands.getICCID.getCommand().getBytes(), 1000, 100);
					} catch (IOException e) {
						closeSerialPort(commAtConnection);
						throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
					}
					closeSerialPort(commAtConnection);
					if (reply != null) {
					    String iccid = getResponseString(reply);
					    if(iccid != null && !iccid.isEmpty()) {
					    	if (iccid.startsWith("#CCID:")) {
					    		iccid = iccid.substring("#CCID:".length()).trim();
					    	}
					    	m_iccid = iccid;        
					    }
					}
	    		}
	    	}
    	}
        return m_iccid;
    }
    
    public String getDataPort() throws KuraException {
    	
    	String port = null;
    	List <String> ports = m_device.getSerialPorts();
    	if ((ports != null) && (ports.size() > 0)) {
	    	if (m_device instanceof UsbModemDevice) {
	    		SupportedUsbModemInfo usbModemInfo = SupportedUsbModemsInfo.getModem((UsbModemDevice)m_device);
	    		if (usbModemInfo != null)  {
	    			port = ports.get(usbModemInfo.getDataPort());
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No PPP serial port available");
	    		}
	    	} else if (m_device instanceof SerialModemDevice) {
	    		SupportedSerialModemInfo serialModemInfo = SupportedSerialModemsInfo.getModem();
	    		if (serialModemInfo != null) {
	    			port = serialModemInfo.getDriver().getComm().getDataPort();
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No PPP serial port available");
	    		}
	    	} else {
	    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Unsupported modem device");
	    	}
    	} else {
    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No serial ports available");
    	}
		
    	return port;
	}
	
    
    public String getAtPort() throws KuraException {
		
    	String port = null;
    	List <String> ports = m_device.getSerialPorts();
    	if ((ports != null) && (ports.size() > 0)) {
	    	if (m_device instanceof UsbModemDevice) {
	    		SupportedUsbModemInfo usbModemInfo = SupportedUsbModemsInfo.getModem((UsbModemDevice)m_device);
	    		if (usbModemInfo != null) {
	    			port = ports.get(usbModemInfo.getAtPort());
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No AT serial port available");
	    		}
	    	} else if (m_device instanceof SerialModemDevice) {
	    		SupportedSerialModemInfo serialModemInfo = SupportedSerialModemsInfo.getModem();
	    		if (serialModemInfo != null) {
	    			port = serialModemInfo.getDriver().getComm().getAtPort();
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No AT serial port available");
	    		}
	    	} else {
	    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Unsupported modem device");
	    	}
    	} else {
    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No serial ports available");
    	}
    	
    	return port;
	}
    
    public String getGpsPort() throws KuraException {
    	
    	String port = null;
    	if (OS_VERSION.equals(KuraConstants.Mini_Gateway.getImageName() + "_" + KuraConstants.Mini_Gateway.getImageVersion()) &&
    			TARGET_NAME.equals(KuraConstants.Mini_Gateway.getTargetName())) {
    		port = SerialModemComm.MiniGateway.getAtPort();
    	} else {
    		port = getAtPort();
    	}
    	return port;
    }
	
    public ModemDevice getModemDevice() {
        return m_device;
    }
    
    public List<NetConfig> getConfiguration() {
		return m_netConfigs;
	}

	public void setConfiguration(List<NetConfig> netConfigs) {
		m_netConfigs = netConfigs;
	}
	
	public ModemTechnologyType getTechnologyType() {
		return m_technologyType;
	}
	
	public CommURI getSerialConnectionProperties(SerialPortType portType) throws KuraException {
		try {
			String port;
			if (portType == SerialPortType.ATPORT) {
				port = getAtPort();
			} else if (portType == SerialPortType.DATAPORT) {
				port = this.getDataPort();
			} else if (portType == SerialPortType.GPSPORT) {
				port = getGpsPort();
			} else {
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Invalid Port Type");
			}
			StringBuffer sb = new StringBuffer();
			sb.append("comm:").append(port).append(";baudrate=115200;databits=8;stopbits=1;parity=0");
			return CommURI.parseString(sb.toString());
			
		} catch (URISyntaxException e) {
			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "URI Syntax Exception");
		}
	}
	
	public boolean isGpsEnabled() {
		return m_gpsEnabled;
	}
	
	public abstract boolean isSimCardReady() throws KuraException;
	
	protected CommConnection openSerialPort (String port) throws KuraException {
    	
    	CommConnection connection = null;
		if(m_connectionFactory != null) {
			String uri = new CommURI.Builder(port)
							.withBaudRate(115200)
							.withDataBits(8)
							.withStopBits(1)
							.withParity(0)
							.withTimeout(2000)
							.build().toString();
				
			try {
				connection = (CommConnection) m_connectionFactory
						.createConnection(uri, 1, false);
			} catch (Exception e) {
				s_logger.debug("Exception creating connection: " + e);
				throw new KuraException(KuraErrorCode.CONNECTION_FAILED, e);
			}<commit_msg>exception handling<commit_after>package org.eclipse.kura.net.admin.modem.telit.generic;

import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

import org.eclipse.kura.KuraErrorCode;
import org.eclipse.kura.KuraException;
import org.eclipse.kura.comm.CommConnection;
import org.eclipse.kura.comm.CommURI;
import org.eclipse.kura.linux.net.modem.SerialModemComm;
import org.eclipse.kura.linux.net.modem.SerialModemDriver;
import org.eclipse.kura.linux.net.modem.SupportedSerialModemInfo;
import org.eclipse.kura.linux.net.modem.SupportedSerialModemsInfo;
import org.eclipse.kura.linux.net.modem.SupportedUsbModemInfo;
import org.eclipse.kura.linux.net.modem.SupportedUsbModems;
import org.eclipse.kura.linux.net.modem.SupportedUsbModemsInfo;
import org.eclipse.kura.linux.net.util.KuraConstants;
import org.eclipse.kura.net.NetConfig;
import org.eclipse.kura.net.admin.modem.telit.he910.TelitHe910;
import org.eclipse.kura.net.modem.CellularModem.SerialPortType;
import org.eclipse.kura.net.modem.ModemDevice;
import org.eclipse.kura.net.modem.ModemTechnologyType;
import org.eclipse.kura.net.modem.SerialModemDevice;
import org.eclipse.kura.usb.UsbModemDevice;
import org.osgi.service.io.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class TelitModem {
	
	private static final Logger s_logger = LoggerFactory.getLogger(TelitModem.class);
	private static final String OS_VERSION = System.getProperty("kura.os.version");
	private static final String TARGET_NAME = System.getProperty("target.device");
	
	protected static Object s_atLock = new Object(); 
	
	protected String m_model;
	protected String m_manufacturer;
	protected String m_serialNumber;
	protected String m_revisionId;
	protected int m_rssi;
	protected Boolean m_gpsSupported;
	protected String m_imsi;
	protected String m_iccid;
	
	private boolean m_gpsEnabled;
	private ModemDevice m_device;
	private String m_platform;
	private ConnectionFactory m_connectionFactory;
	private ModemTechnologyType m_technologyType;
	private List<NetConfig> m_netConfigs = null;
	
	public TelitModem(ModemDevice device, String platform,
			ConnectionFactory connectionFactory,
			ModemTechnologyType technologyType) {
		
		m_device = device;
		m_platform = platform;
		m_connectionFactory = connectionFactory;
		m_technologyType = technologyType;
		m_gpsEnabled = false;
	}
	
	public void reset() throws KuraException {

		boolean status = false;
		int resetAttempts = 5;

		sleep(5000);
		while (resetAttempts > 0) {
			try {
				status = turnOff();
				if (status) {
					status = turnOn();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (status) {
				s_logger.info("reset() :: modem reset successful");
				break;
			} else {
				resetAttempts--;
				s_logger.info("reset() :: modem reset failed, attempts left: {}", resetAttempts);
				sleep(1000);
			}
		}
	}
	
	public String getModel() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_model == null) {
	    		s_logger.debug("sendCommand getModelNumber :: " + TelitModemAtCommands.getModelNumber.getCommand());
		    	byte[] reply = null;
		    	CommConnection commAtConnection = openSerialPort(getAtPort());
		    	if (!isAtReachable(commAtConnection)) {
		    		closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getModelNumber.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
					m_model = getResponseString(reply);
					reply = null;
				}
	    	}
    	}
        return m_model;
    }
	
	public String getManufacturer() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_manufacturer == null) {
		    	s_logger.debug("sendCommand getManufacturer :: " + TelitModemAtCommands.getManufacturer.getCommand());
		    	byte[] reply = null;
		    	CommConnection commAtConnection = openSerialPort(getAtPort());
		    	if (!isAtReachable(commAtConnection)) {
		    		closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
		    	try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getManufacturer.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
		    	closeSerialPort(commAtConnection);
				if (reply != null) {
				    m_manufacturer = getResponseString(reply); 
					reply = null;
				}
	    	}
    	}
        return m_manufacturer;
    }
	
	public String getSerialNumber() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_serialNumber == null) {
	    		s_logger.debug("sendCommand getSerialNumber :: " + TelitModemAtCommands.getSerialNumber.getCommand());
	    		byte[] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getSerialNumber.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
				    String serialNum = getResponseString(reply);
				    if(serialNum != null && !serialNum.isEmpty()) {
				    	if (serialNum.startsWith("#CGSN:")) {
				    		serialNum = serialNum.substring("#CGSN:".length()).trim();
				    	}
				    	m_serialNumber = serialNum;        
				    }
				}
	    	}
    	}
        return m_serialNumber;
    }
	
	public String getRevisionID() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_revisionId == null) {
	    		s_logger.debug("sendCommand getRevision :: " + TelitModemAtCommands.getRevision.getCommand());
	    		byte [] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
	    		try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.getRevision.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
	    		closeSerialPort(commAtConnection);
				if (reply != null) {
					m_revisionId = getResponseString(reply);
				}
	    	}
    	}
        return m_revisionId;
    }
    
	public boolean isReachable() throws KuraException {
    	boolean ret = false;
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getAtPort());
    		ret = isAtReachable(commAtConnection);
    		closeSerialPort(commAtConnection);
    	}
		return ret;
	}
	
	public int getSignalStrength() throws KuraException {
    	
    	int signalStrength = -113;
    	synchronized (s_atLock) {
    		String atPort = getAtPort();
    		String gpsPort = getGpsPort();
			if ((atPort.equals(getDataPort()) || (atPort.equals(gpsPort)
					&& m_gpsEnabled)) && (m_rssi < 0)) {
				return m_rssi;
			}
	    	s_logger.debug("sendCommand getSignalStrength :: " + TelitModemAtCommands.getSignalStrength.getCommand());
	    	byte[] reply = null;
	    	CommConnection commAtConnection = openSerialPort(atPort);
	    	if (!isAtReachable(commAtConnection)) {
	    		closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
			try {
				reply = commAtConnection.sendCommand(TelitModemAtCommands.getSignalStrength.getCommand().getBytes(), 1000, 100);
			} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
			closeSerialPort(commAtConnection);
			if (reply != null) {
				String [] asCsq = null;
				String sCsq = this.getResponseString(reply);
				if (sCsq.startsWith("+CSQ:")) {
					sCsq = sCsq.substring("+CSQ:".length()).trim();
					s_logger.trace("getSignalStrength() :: +CSQ={}", sCsq);
					asCsq = sCsq.split(",");
					if (asCsq.length == 2) {
						int rssi = Integer.parseInt(asCsq[0]);
						if (rssi < 99) {
							signalStrength = -113 + 2 * rssi;
						}
						s_logger.trace("getSignalStrength() :: signalStrength={}", signalStrength);
					}
				}
				reply = null;
			}
    	}
    	m_rssi = signalStrength;
        return signalStrength;
    }
	
    public boolean isGpsSupported() throws KuraException {
    	synchronized (s_atLock) {
    		if (m_gpsSupported == null) {
	    		s_logger.debug("sendCommand isGpsSupported :: " + TelitModemAtCommands.isGpsPowered.getCommand());
	    		byte[] reply = null;
	    		CommConnection commAtConnection = openSerialPort(getAtPort());
	    		if (!isAtReachable(commAtConnection)) {
	    			closeSerialPort(commAtConnection);
		    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
		    	}
	    		
				try {
					reply = commAtConnection.sendCommand(TelitModemAtCommands.isGpsPowered.getCommand().getBytes(), 1000, 100);
				} catch (IOException e) {
					closeSerialPort(commAtConnection);
					throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
				}
				closeSerialPort(commAtConnection);
				if (reply != null) {
				    String sReply = getResponseString(reply);
				    if((sReply != null) && !sReply.isEmpty()) {
				    	if (sReply.startsWith("$GPSP:")) {
				    		m_gpsSupported = true;
				    	}
				    }
				}
    		}
    	}
    	boolean ret = false;
    	if (m_gpsSupported != null) {
    		ret = m_gpsSupported;
    	}
    	return ret;
    }
    
    public void enableGps() throws KuraException {
    	if ((m_gpsSupported == null) || (m_gpsSupported == false)) {
    		m_gpsEnabled = false;
    		return;
    	}
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getGpsPort());
    		if (!isAtReachable(commAtConnection)) {
    			closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
   
    		byte[] reply = null;
    		try {
    			if (!isGpsPowered(commAtConnection)) {
    				s_logger.debug("sendCommand gpsPowerUp :: " + TelitModemAtCommands.gpsPowerUp.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsPowerUp.getCommand().getBytes(), 1000, 100);
    			}
    			
    			s_logger.debug("sendCommand gpsEnableNMEA :: " + TelitModemAtCommands.gpsEnableNMEA.getCommand());
				reply = commAtConnection.sendCommand(TelitModemAtCommands.gpsEnableNMEA.getCommand().getBytes(), 3000, 100);
    		} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
    		closeSerialPort(commAtConnection);
    		
    		if (reply != null) {
			    String sReply = getResponseString(reply);
			    if((sReply != null) && !sReply.isEmpty()) {
			    	if (sReply.startsWith("CONECT"))
			    	s_logger.debug("NMEA Enabled");
			    }
    		}
    	}
    	
    	m_gpsEnabled = true;
    }
    
    public void disableGps() throws KuraException {
    	if ((m_gpsSupported == null) || (m_gpsSupported == false)) {
    		m_gpsEnabled = false;
    		return;
    	}
    	synchronized (s_atLock) {
    		CommConnection commAtConnection = openSerialPort(getGpsPort());
    		if (!isAtReachable(commAtConnection)) {
    			closeSerialPort(commAtConnection);
	    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
	    	}
   
    		try {
    			if (!isGpsPowered(commAtConnection)) {
    				s_logger.debug("sendCommand gpsDisableNMEA :: " + TelitModemAtCommands.gpsDisableNMEA.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsDisableNMEA.getCommand().getBytes(), 1000, 100);
    				
    				s_logger.debug("sendCommand gpsPowerDown :: " + TelitModemAtCommands.gpsPowerDown.getCommand());
    				commAtConnection.sendCommand(TelitModemAtCommands.gpsPowerDown.getCommand().getBytes(), 1000, 100);
    			}
    		} catch (IOException e) {
				closeSerialPort(commAtConnection);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
			}
    		closeSerialPort(commAtConnection);
    	}
    	
    	m_gpsEnabled = false;
    }
    
    public String getMobileSubscriberIdentity() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_imsi == null) {
	    		if (isSimCardReady()) {
		    		s_logger.debug("sendCommand getIMSI :: " + TelitModemAtCommands.getIMSI.getCommand());
		    		byte[] reply = null;
		    		CommConnection commAtConnection = openSerialPort(getAtPort());
		    		if (!isAtReachable(commAtConnection)) {
		    			closeSerialPort(commAtConnection);
			    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
			    	}
					try {
						reply = commAtConnection.sendCommand(TelitModemAtCommands.getIMSI.getCommand().getBytes(), 1000, 100);
					} catch (IOException e) {
						closeSerialPort(commAtConnection);
						throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
					}
					closeSerialPort(commAtConnection);
					if (reply != null) {
					    String imsi = getResponseString(reply);
					    if(imsi != null && !imsi.isEmpty()) {
					    	if (imsi.startsWith("#CIMI:")) {
					    		imsi = imsi.substring("#CIMI:".length()).trim();
					    	}
					    	m_imsi = imsi;        
					    }
					}
	    		}
	    	}
    	}
        return m_imsi;
    }
    
    public String getIntegratedCirquitCardId() throws KuraException {
    	synchronized (s_atLock) {
	    	if (m_iccid == null) {
	    		if (isSimCardReady()) {
		    		s_logger.debug("sendCommand getICCID :: " + TelitModemAtCommands.getICCID.getCommand());
		    		byte[] reply = null;
		    		CommConnection commAtConnection = openSerialPort(getAtPort());
		    		if (!isAtReachable(commAtConnection)) {
		    			closeSerialPort(commAtConnection);
			    		throw new KuraException(KuraErrorCode.NOT_CONNECTED, "Modem not available for AT commands: " + TelitHe910.class.getName());
			    	}
					try {
						reply = commAtConnection.sendCommand(TelitModemAtCommands.getICCID.getCommand().getBytes(), 1000, 100);
					} catch (IOException e) {
						closeSerialPort(commAtConnection);
						throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e);
					}
					closeSerialPort(commAtConnection);
					if (reply != null) {
					    String iccid = getResponseString(reply);
					    if(iccid != null && !iccid.isEmpty()) {
					    	if (iccid.startsWith("#CCID:")) {
					    		iccid = iccid.substring("#CCID:".length()).trim();
					    	}
					    	m_iccid = iccid;        
					    }
					}
	    		}
	    	}
    	}
        return m_iccid;
    }
    
    public String getDataPort() throws KuraException {
    	
    	String port = null;
    	List <String> ports = m_device.getSerialPorts();
    	if ((ports != null) && (ports.size() > 0)) {
	    	if (m_device instanceof UsbModemDevice) {
	    		SupportedUsbModemInfo usbModemInfo = SupportedUsbModemsInfo.getModem((UsbModemDevice)m_device);
	    		if (usbModemInfo != null)  {
	    			port = ports.get(usbModemInfo.getDataPort());
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No PPP serial port available");
	    		}
	    	} else if (m_device instanceof SerialModemDevice) {
	    		SupportedSerialModemInfo serialModemInfo = SupportedSerialModemsInfo.getModem();
	    		if (serialModemInfo != null) {
	    			port = serialModemInfo.getDriver().getComm().getDataPort();
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No PPP serial port available");
	    		}
	    	} else {
	    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Unsupported modem device");
	    	}
    	} else {
    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No serial ports available");
    	}
		
    	return port;
	}
	
    
    public String getAtPort() throws KuraException {
		
    	String port = null;
    	List <String> ports = m_device.getSerialPorts();
    	if ((ports != null) && (ports.size() > 0)) {
	    	if (m_device instanceof UsbModemDevice) {
	    		SupportedUsbModemInfo usbModemInfo = SupportedUsbModemsInfo.getModem((UsbModemDevice)m_device);
	    		if (usbModemInfo != null) {
	    			port = ports.get(usbModemInfo.getAtPort());
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No AT serial port available");
	    		}
	    	} else if (m_device instanceof SerialModemDevice) {
	    		SupportedSerialModemInfo serialModemInfo = SupportedSerialModemsInfo.getModem();
	    		if (serialModemInfo != null) {
	    			port = serialModemInfo.getDriver().getComm().getAtPort();
	    		} else {
	    			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No AT serial port available");
	    		}
	    	} else {
	    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Unsupported modem device");
	    	}
    	} else {
    		throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "No serial ports available");
    	}
    	
    	return port;
	}
    
    public String getGpsPort() throws KuraException {
    	
    	String port = null;
    	if (OS_VERSION.equals(KuraConstants.Mini_Gateway.getImageName() + "_" + KuraConstants.Mini_Gateway.getImageVersion()) &&
    			TARGET_NAME.equals(KuraConstants.Mini_Gateway.getTargetName())) {
    		port = SerialModemComm.MiniGateway.getAtPort();
    	} else {
    		port = getAtPort();
    	}
    	return port;
    }
	
    public ModemDevice getModemDevice() {
        return m_device;
    }
    
    public List<NetConfig> getConfiguration() {
		return m_netConfigs;
	}

	public void setConfiguration(List<NetConfig> netConfigs) {
		m_netConfigs = netConfigs;
	}
	
	public ModemTechnologyType getTechnologyType() {
		return m_technologyType;
	}
	
	public CommURI getSerialConnectionProperties(SerialPortType portType) throws KuraException {
		try {
			String port;
			if (portType == SerialPortType.ATPORT) {
				port = getAtPort();
			} else if (portType == SerialPortType.DATAPORT) {
				port = this.getDataPort();
			} else if (portType == SerialPortType.GPSPORT) {
				port = getGpsPort();
			} else {
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "Invalid Port Type");
			}
			StringBuffer sb = new StringBuffer();
			sb.append("comm:").append(port).append(";baudrate=115200;databits=8;stopbits=1;parity=0");
			return CommURI.parseString(sb.toString());
			
		} catch (URISyntaxException e) {
			throw new KuraException(KuraErrorCode.INTERNAL_ERROR, "URI Syntax Exception");
		}
	}
	
	public boolean isGpsEnabled() {
		return m_gpsEnabled;
	}
	
	public abstract boolean isSimCardReady() throws KuraException;
	
	protected CommConnection openSerialPort (String port) throws KuraException {
    	
    	CommConnection connection = null;
		if(m_connectionFactory != null) {
			String uri = new CommURI.Builder(port)
							.withBaudRate(115200)
							.withDataBits(8)
							.withStopBits(1)
							.withParity(0)
							.withTimeout(2000)
							.build().toString();
				
			try {
				connection = (CommConnection) m_connectionFactory
						.createConnection(uri, 1, false);
			} catch (Exception e) {
				s_logger.debug("Exception creating connection: " + e);
				throw new KuraException(KuraErrorCode.INTERNAL_ERROR, e, "Connection Failed");
			}
{'fraction_non_alphanumeric': 0.10930733252493256, 'fraction_numerical': 0.008364473260907224, 'mean_word_length': 3.2816274634456453, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2899005', 'n_tokens_mistral': 15135, 'n_tokens_neox': 13159, 'n_words': 2313}