gt: 		if(api != null) {
context: /**
   * Copyright (c) 2010-2015, openHAB.org and others.
   *
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   */
  package org.openhab.binding.dscalarm.internal;
  
  import java.util.Collections;
  import java.util.Dictionary;
  import java.util.EventObject;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.apache.commons.lang.StringUtils;
  import org.openhab.binding.dscalarm.DSCAlarmBindingConfig;
  import org.openhab.binding.dscalarm.DSCAlarmBindingProvider;
  import org.openhab.binding.dscalarm.internal.connector.DSCAlarmConnectorType;
  import org.openhab.binding.dscalarm.internal.model.DSCAlarmDeviceType;
  import org.openhab.binding.dscalarm.internal.protocol.API;
  import org.openhab.binding.dscalarm.internal.protocol.APICode;
  import org.openhab.binding.dscalarm.internal.protocol.APIMessage;
  import org.openhab.core.binding.AbstractActiveBinding;
  import org.openhab.core.binding.BindingProvider;
  import org.openhab.core.items.Item;
  import org.openhab.core.types.Command;
  import org.osgi.service.cm.ConfigurationException;
  import org.osgi.service.cm.ManagedService;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * DSCAlarmActiveBinding Class. Polls the DSC Alarm panel,
   * responds to item commands, and also handles events coming 
   * from the DSC Alarm panel.
   * 
   * @author Russell Stephens
   * @since 1.6.0
   */
  
  public class DSCAlarmActiveBinding extends AbstractActiveBinding<DSCAlarmBindingProvider> implements ManagedService, DSCAlarmEventListener {
  
  	private static final Logger logger = LoggerFactory.getLogger(DSCAlarmActiveBinding.class);
  
  	private long refreshInterval = 5000;
  
  	private DSCAlarmConnectorType connectorType = null;
  
  	/** Default Poll Period. **/
  	public static final long DEFAULT_POLL_PERIOD = 1;
  	
  	/** The serial port name of the DSC-IT100 Serial Interface
  	 * 	Valid values are e.g. COM1 for Windows and /dev/ttyS0 or /dev/ttyUSB0 for Linux
  	 * */
  	private String serialPort = null;
  
  	/** The IP address of the EyezOn Envisalink 3/2DS DSC Alarm Interface*/
  	private String ipAddress = null;
  	
  	/** Baud rate for a serial connection */
  	private int baudRate = 0;
  
  	/** User name for EyezOn Envisalink 3/2DS authentication */
  	/**private String username = null;
  
  	/** Password for EyezOn Envisalink 3/2DS authentication */
  	private String password = null;
  
  	/** User Code for some DSC Alarm commands */
  	private String userCode = null;
  
  	/** API Session for EyezOn Envisalink 3/2DS */
  	private API api = null;
  	private boolean connected = false;
  	
  	private long pollTime = 0;
  	private long pollTimeStart = 0;
  	private long pollPeriod = DEFAULT_POLL_PERIOD;
  	
  	/**
  	 * New items or items needing to be refreshed get added to refreshmao
  	 * the worker thread will refresh and remove them
  	 */
  	private Map<String, DSCAlarmBindingConfig> dscAlarmUpdateMap = Collections.synchronizedMap(new HashMap<String, DSCAlarmBindingConfig>());
  	private DSCAlarmItemUpdate dscAlarmItemUpdate = new DSCAlarmItemUpdate();
  	private int itemCount = 0;
  	private boolean itemHasChanged = false;
  	private boolean processUpdates = false;
  	
  	/**
  	 * Activates the binding. Actually does nothing, because on activation
  	 * OpenHAB always calls updated to indicate that the config is updated
  	 * Activation is done there
  	 */
  	public void activate() {
  		logger.debug("Activate DSC Alarm");
  	}
  	
  	/**
  	 * Deactivates the binding
  	 */
  	public void deactivate() {
  		logger.debug("Deactivate DSC Alarm");
  		closeConnection();
  	}
  
  	/**
  	 * @{inheritDoc
  	 */
  	@Override
  	protected void execute() {
  		logger.debug("DSC Alarm Execute");
  
  		if(api != null) {
  			connected = api.isConnected();
  		}
  		
  		if(connected) {
  			if(pollTimeStart == 0) {
  				pollTimeStart = System.currentTimeMillis();
  			}
  			
  			pollTime = ((System.currentTimeMillis() - pollTimeStart) / 1000) / 60;
  			
  			//Send Poll command to the DSC Alarm if idle for 'pollPeriod' minutes
  			if(pollTime >= pollPeriod) {
  				api.sendCommand(APICode.Poll);
  				pollTimeStart = 0;
  				logger.debug("execute(): Poll Command Sent to DSC Alarm.");
  			}
  		}
  		else {
  			closeConnection();
  			logger.error("execute(): Not Connected to the DSC Alarm!");
  			reconnect();
  		}
  
  		//Need to allow one cycle to pass before processing item updates after binding changes.
  		if(itemHasChanged) {
  			if(processUpdates) {
  				processUpdateMap();
  				itemHasChanged = false;
  				processUpdates = false;
  				if(connected) {
  					//Get a status report from API.
  					api.sendCommand(APICode.StatusReport);
  				}
  			}
  			else
  				processUpdates = true;
  		}
  	}
  
  	/**
  	 * {@inheritDoc}
  	 */
  	@Override
  	public void bindingChanged(BindingProvider provider, String itemName) {
  		logger.debug("bindingChanged(): Item Name: {}", itemName);
  		
  		boolean itemRemoved = false;
  		int icount = provider.getItemNames().size();
  
  		if(icount < itemCount) {
  			itemRemoved = true;
  		}
  		
  		if(itemRemoved) {
  			dscAlarmUpdateMap.clear();
  		} else {
  
  			DSCAlarmBindingProvider dscAlarmBindingProvider = (DSCAlarmBindingProvider) provider;
  			
  			if(dscAlarmBindingProvider != null) {
  				DSCAlarmBindingConfig dscAlarmBindingConfig = dscAlarmBindingProvider.getDSCAlarmBindingConfig(itemName);
  				if(dscAlarmBindingConfig != null) {
  					dscAlarmUpdateMap.put(itemName, dscAlarmBindingConfig);
  				}
  			}
  		}
  
  		itemCount = provider.getItemNames().size();
  		itemHasChanged = true;
  	}
  	
  	/**
  	 * @{inheritDoc
  	 */
  	@Override
  	protected void internalReceiveCommand(String itemName, Command command) {
  		DSCAlarmBindingConfig dscAlarmBindingConfig = null;
  		Item item = null;
  		for (DSCAlarmBindingProvider prov : providers) {
  			dscAlarmBindingConfig = prov.getDSCAlarmBindingConfig(itemName);
  			item = prov.getItem(itemName);
  			if( dscAlarmBindingConfig != null) {
  				DSCAlarmDeviceType dscAlarmDeviceType = dscAlarmBindingConfig.getDeviceType(); 
  				int partitionId;
  				int zoneId;
  		
  				logger.debug("internalReceiveCommand():  Item Name: {} Command: {} Item Device Type: {}",itemName,command,dscAlarmDeviceType);
  
  				if(connected) {
  					switch(dscAlarmDeviceType) {
  						case PANEL:
  							switch (dscAlarmBindingConfig.getDSCAlarmItemType()) {
  								case PANEL_CONNECTION:
  									if(command.toString() == "0") {
  										closeConnection();
  										if(!connected) {
  											dscAlarmItemUpdate.setConnected(false);
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 0, "Disconnected");
  										}
  									}
  									break;
  								case PANEL_COMMAND:
  									int cmd = Integer.parseInt(command.toString());
  									switch (cmd) {
  									case 0: api.sendCommand(APICode.Poll);
  										break;
  									case 1: api.sendCommand(APICode.StatusReport);
  										break;
  									case 2: api.sendCommand(APICode.LabelsRequest);
  										break;
  									case 8: api.sendCommand(APICode.DumpZoneTimers);
  										break;
  									case 10: api.sendCommand(APICode.SetTimeDate);
  										break;
  									case 200: api.sendCommand(APICode.CodeSend);
  										break;
  									default:
  										break;
  									}
  
  									itemName = getItemName(DSCAlarmItemType.PANEL_COMMAND,0,0);
  									if(itemName != "") {
  										updateDeviceProperties(itemName,-1,"");
  										updateItem(itemName);
  									}
  									break;
  								default:
  									break;
  							}
  							
  							break;
  						case PARTITION:
  							partitionId = dscAlarmBindingConfig.getPartitionId();
  							switch(dscAlarmBindingConfig.getDSCAlarmItemType()) {
  								case PARTITION_ARM_MODE:
  									if(command.toString().equals("0")) {
  										if(api.sendCommand(APICode.PartitionDisarmControl, String.valueOf(partitionId))) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 0, "Partition Disarmed");
  										}
  									}else if(command.toString().equals("1")) {
  										if(api.sendCommand(APICode.PartitionArmControlAway, String.valueOf(partitionId))) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 1, "Partition Armed (Away)");
  										}
  									}else if(command.toString().equals("2")) {
  										if(api.sendCommand(APICode.PartitionArmControlStay, String.valueOf(partitionId))) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 2, "Partition Armed (Stay)");
  										}
  									}else if(command.toString().equals("3")) {
  										if(api.sendCommand(APICode.PartitionArmControlZeroEntryDelay, String.valueOf(partitionId))) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 3, "Partition Armed (Zero Entry Delay)");
  										}
  									}else if(command.toString().equals("4")) {
  										if(api.sendCommand(APICode.PartitionArmControlWithUserCode, String.valueOf(partitionId))) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 4, "Partition Armed (With User Code)");
  										}
  									}
  									break;
  								default:
  									break;
  							}
  							
  							dscAlarmUpdateMap.put(itemName, dscAlarmBindingConfig);
  							processUpdateMap();
  							break;
  						case ZONE:
  							partitionId = dscAlarmBindingConfig.getPartitionId();
  							zoneId = dscAlarmBindingConfig.getZoneId();
  							switch(dscAlarmBindingConfig.getDSCAlarmItemType()) {
  								case ZONE_BYPASS_MODE:
  									if(command.toString().equals("0")) {
  										String data = String.valueOf(partitionId) + "*1" + String.format("%02d", zoneId) + "#";
  										if(api.sendCommand(APICode.KeySequence, data)) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 0, "Zone Armed");
  										}
  									}else if(command.toString().equals("1")) {
  										String data = String.valueOf(partitionId) + "*1" + String.format("%02d", zoneId) + "#";
  										if(api.sendCommand(APICode.KeySequence, data)) {
  											dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 1, "Zone Bypassed");
  										}										
  									}
  									break;
  	
  										
  								default:
  									break;
  							}
  							
  							break;
  						default:
  							logger.debug("internalReceiveCommand(): No Command Sent.");
  							break;
  					}
  				}
  				else {
  					if(dscAlarmDeviceType == DSCAlarmDeviceType.PANEL) {
  						if(dscAlarmBindingConfig.getDSCAlarmItemType() == DSCAlarmItemType.PANEL_CONNECTION) {
  							if(command.toString().equals("1")) {
  								if (api != null) {
  									openConnection();
  									if(connected){
  										dscAlarmItemUpdate.setConnected(true);
  										dscAlarmItemUpdate.updateDeviceProperties(item, dscAlarmBindingConfig, 1, "Connected");
  									}
  								}
  							}
  						}
  					}
  				}
  				/*dscAlarmUpdateMap.put(itemName, dscAlarmBindingConfig);
  				itemHasChanged = true;*/
  			}
  		}
  	}
  	
  
  	/**
  	 * @{inheritDoc
  	 */
  	@Override
  	protected long getRefreshInterval() {
  		return refreshInterval;
  	}
  
  	/**
  	 * @{inheritDoc
  	 */
  	@Override
  	protected String getName() {
  		return "DSC Alarm Monitor Service";
  	}
  
  	/**
  	 * @{inheritDoc
  	 */
  	public void updated(Dictionary<String, ?> config) throws ConfigurationException {
  		logger.debug("updated(): Configuration updated, config {}", config != null ? true:false);
  		
  		if (config != null) {
  			
  			if(StringUtils.isNotBlank((String) config.get("serialPort"))) {
  				serialPort = (String) config.get("serialPort");
  			}
  
  			if(StringUtils.isNotBlank((String) config.get("ip"))) {
  				ipAddress = (String) config.get("ip");
  			}
  
  			if(serialPort != null && ipAddress != null) {
  				logger.error("updated(): Can only configure one connection type at a time: Serial Port or Ip Address!");
  				return;
  			}
  
  			if(serialPort != null) {
  				connectorType = DSCAlarmConnectorType.SERIAL;
  				try {
  					if(StringUtils.isNotBlank((String) config.get("baud")))
  						baudRate = Integer.parseInt((String) config.get("baud"));
  				} catch(NumberFormatException numberFormatException) {
  					logger.error("updated(): Baud Rate not configured correctly!");
  					return;
  				}
  			}
  			
  			if(ipAddress != null) {
  				connectorType = DSCAlarmConnectorType.TCP;
  			}
  			
  			logger.debug("updated(): Connector Type: {}",connectorType);
  			
  			
  			if(StringUtils.isNotBlank((String) config.get("password"))) {
  				password = (String) config.get("password");
  			}
  
  			if(StringUtils.isNotBlank((String) config.get("usercode"))) {
  				userCode = (String) config.get("usercode");
  			}
  			
  			if(StringUtils.isNotBlank((String) config.get("pollPeriod"))) {
  				try {
  					pollPeriod = Integer.parseInt((String) config.get("pollperiod"));
  				} catch(NumberFormatException numberFormatException) {
  					logger.error("updated(): Poll Period not configured correctly!");
  					return;
  				}
  
  				if(pollPeriod > 15) {
  					pollPeriod = 15;
  				}
  				else if(pollPeriod < 1) {
  					pollPeriod = 1;
  				}
  			} else {
  				pollPeriod = DEFAULT_POLL_PERIOD;
  			}
  		}
  		else {
  			logger.debug("updated(): No Configuration!");
  			return;
  		}
  		
  		initialize();
  	}
  
  	/**
  	 * Initializes the binding
  	 */
   	private void initialize() {
  
  		//Check to see if openHAB read in our items while the binding was configuring, and add them to dscAlarmUpdateMap. 
  		 if(dscAlarmUpdateMap.isEmpty() && itemHasChanged == false) {
  			 buildUpdateMap();
  			 itemHasChanged = true;
  		 }
  		
  		//Open a connection to the DSC Alarm Panel
  		openConnection();
  		if(!connected) {
  			dscAlarmItemUpdate.setConnected(false);
  		}
  		else {
  			dscAlarmItemUpdate.setConnected(true);
  		}
  		
  		this.setProperlyConfigured(true);
  		logger.debug("initialize(): Binding initialized!");
   	}
  
   	/**
  	 * Build the Update Items Map
  	 */
  	private void buildUpdateMap() {
  		DSCAlarmBindingConfig config;
  
  		for (DSCAlarmBindingProvider prov : providers) {
  	 		if(!prov.getItemNames().isEmpty()) {
  	 			itemCount = prov.getItemNames().size();	 			
  				dscAlarmUpdateMap.clear();
  				for (String iName : prov.getItemNames()) {
  					config = prov.getDSCAlarmBindingConfig(iName); 
  					if(config != null) {
  						dscAlarmUpdateMap.put(iName, config);
  					}
  				}
  			}
  		}
  	}
  	
  	/**
  	 * Processes the Update Items Map
  	 */
  	private void processUpdateMap() {
  	
  		if (dscAlarmUpdateMap.size() == 0) {
  			logger.debug("processUpdateMap(): Nothing to update.");
  			return;
  		}
  		
  		Map<String, DSCAlarmBindingConfig> itemsMap = new HashMap<String, DSCAlarmBindingConfig>(dscAlarmUpdateMap);
  	
  		for (String itemName : itemsMap.keySet()) {
  			DSCAlarmBindingConfig dscAlarmBindingConfig = itemsMap.get(itemName);
  			dscAlarmUpdateMap.remove(itemName);
  			Item item = null;
  			for (DSCAlarmBindingProvider provider : providers) {
  				item = provider.getItem(itemName);
  			}
  
  			dscAlarmItemUpdate.updateDeviceItem(item, dscAlarmBindingConfig, eventPublisher, null);
  			logger.debug("processUpdateMap(): Updated item: {}", itemName);
  		}
  	}
  
  	/**
  	 * Open a TCP or Serial connection to the DSC Alarm Panel
  	 */
   	private void openConnection() {
  
      	switch (connectorType) {
  	    	case SERIAL:
  	     		if (api == null) {
  	    			api = new API(serialPort, baudRate);
  	    		}
  	     		break;
  	    	case TCP:
  	     		if (api == null) {
  	    			api = new API(ipAddress, password, userCode);
  	    		}
     			break;
  	        default:
  	        	connected = false;
  				logger.debug("openConnection(): Unable to make a connection!");
  				return;
      	}
  
      	connected = api.open();
  
  		if(connected){
  			api.addEventListener(this);
  		}
  	}
  	
  	/**
  	 * Attempt to reconnect to TCP or Serial connection
  	 */
  	private void reconnect() {
  		String itemName;
  		logger.debug("reconnect(): API Reconnection!");	
  
  		openConnection();
  		
  		if(connected) {
  			dscAlarmItemUpdate.setConnected(true);
  			itemName = getItemName(DSCAlarmItemType.PANEL_CONNECTION,0,0);
  			if(itemName != "") {
  				updateItem(itemName);
  			}
  
  			buildUpdateMap();
  			itemHasChanged = true;
  		}
  		else {
  			dscAlarmItemUpdate.setSysMessage("PANEL DISCONNECTED!!!");
  			itemName = getItemName(DSCAlarmItemType.PANEL_MESSAGE,0,0);
  			if(itemName != "") {
  				updateItem(itemName);
  			}
  			logger.error("reconnect(): API reconnection failed!");	
  		}
  	}
  
  	/**
  	 * Close TCP or Serial connection to the DSC Alarm Panel and remove the Event Listener
  	 */
  	private void closeConnection() {
  		String itemName;
  
  