/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.societies.rfid.server;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.comm.xmpp.interfaces.ICommManager;
import org.societies.api.css.devicemgmt.IAction;
import org.societies.api.css.devicemgmt.IDevice;
import org.societies.api.css.devicemgmt.IDriverService;
import org.societies.api.css.devicemgmt.model.DeviceActionsConstants;
import org.societies.api.css.devicemgmt.model.DeviceMgmtConstants;
import org.societies.api.css.devicemgmt.model.DeviceMgmtDriverServiceNames;
import org.societies.api.css.devicemgmt.model.DeviceMgmtEventConstants;
import org.societies.api.css.devicemgmt.model.DeviceStateVariableConstants;
import org.societies.api.css.devicemgmt.model.DeviceTypeConstants;
import org.societies.api.identity.IIdentity;
import org.societies.api.identity.IIdentityManager;
import org.societies.api.internal.context.broker.ICtxBroker;
import org.societies.api.osgi.event.CSSEvent;
import org.societies.api.osgi.event.CSSEventConstants;
import org.societies.api.osgi.event.EventListener;
import org.societies.api.osgi.event.EventTypes;
import org.societies.api.osgi.event.IEventMgr;
import org.societies.api.osgi.event.InternalEvent;
import org.societies.rfid.client.api.remote.IRfidClient;
import org.societies.rfid.server.api.IRfidServer;
import org.springframework.osgi.context.BundleContextAware;
public class RfidServer extends EventListener implements IRfidServer, ServiceTrackerCustomizer, BundleContextAware {
private Logger logging = LoggerFactory.getLogger(this.getClass());
//private ServiceResourceIdentifier myServiceId;
//private List<String> myServiceTypes = new ArrayList<String>();
private Hashtable<String, String> tagToPasswordTable;
private Hashtable<String, String> tagtoIdentityTable;
private Hashtable<String, String> tagtoSymlocTable; //TAG TO SYMLOC
private Hashtable<String, String> wUnitToSymlocTable;
private IEventMgr eventMgr;
//private Hashtable<String, String> dpiToServiceID;
Hashtable<String, RFIDUpdateTimerTask> tagToTimerTable = new Hashtable<String, RFIDUpdateTimerTask>();
private IRfidClient rfidClientRemote;
private BundleContext bundleContext;
private ServiceTracker serviceTracker;
private IDevice iDevice;
private ContextRetriever ctxRetriever;
private ICommManager commManager;
private IIdentityManager idManager;
private IIdentity serverIdentity;
private ICtxBroker ctxBroker;
private RfidWebAppEventListener webAppEventListener;
@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
/**
* @return the eventMgr
*/
public IEventMgr getEventMgr() {
return eventMgr;
}
/**
* @param eventMgr the eventMgr to set
*/
public void setEventMgr(IEventMgr eventMgr) {
this.eventMgr = eventMgr;
}
public void initialiseRFIDServer(){
String stringFilter = "(&("+ Constants.OBJECTCLASS +"="+ IDevice.class.getName()+")("+DeviceMgmtConstants.DEVICE_TYPE+"="+DeviceTypeConstants.RFID_READER+"))";
Filter filter = null;
try {
filter = bundleContext.createFilter(stringFilter);
} catch (InvalidSyntaxException e) {
e.printStackTrace();
}
this.serviceTracker = new ServiceTracker(bundleContext, filter, this);
this.serviceTracker.open();
this.tagtoIdentityTable = new Hashtable<String, String>();
this.tagToPasswordTable = new Hashtable<String, String>();
this.tagtoSymlocTable = new Hashtable<String, String>();
//this.dpiToServiceID = new Hashtable<String, String>();
RFIDConfig rfidConfig = new RFIDConfig();
this.wUnitToSymlocTable = rfidConfig.getUnitToSymloc();
if (this.wUnitToSymlocTable==null){
this.wUnitToSymlocTable = new Hashtable<String, String>();
}
this.registerRFIDReaders();
this.ctxRetriever = new ContextRetriever(getCtxBroker(), this.serverIdentity);
this.tagtoIdentityTable = ctxRetriever.getTagToIdentity();
this.tagToPasswordTable = ctxRetriever.getTagToPassword();
this.tagtoSymlocTable = ctxRetriever.getTagToSymloc();
logging.debug("in initialisation - starting eventlistener");
this.webAppEventListener = new RfidWebAppEventListener(this);
}
private void registerRFIDReaders(){
String[] options = new String[]{"0.localhost","1.University addresses"};
//String str = (String) JOptionPane.showInputDialog(null, "Select Configuration", "Configuration", JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
String str = options[1];
if (str.equalsIgnoreCase(options[0])){
if (null != iDevice) {
this.registerForRFIDEvents(iDevice.getDeviceId());
IDriverService iDriverService = iDevice.getService(DeviceMgmtDriverServiceNames.RFID_READER_DRIVER_SERVICE);
IAction iAction = iDriverService.getAction(DeviceActionsConstants.RFID_CONNECT_ACTION);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
dic.put(DeviceStateVariableConstants.IP_ADDRESS_STATE_VARIABLE, "127.0.0.1");
iAction.invokeAction(dic);
}
//this.rfidDriver.connect("127.0.0.1");
}else{
if (null != iDevice)
{
this.registerForRFIDEvents(iDevice.getDeviceId());
IDriverService iDriverService = iDevice.getService(DeviceMgmtDriverServiceNames.RFID_READER_DRIVER_SERVICE);
IAction iAction = iDriverService.getAction(DeviceActionsConstants.RFID_CONNECT_ACTION);
Dictionary<String, Object> dic = new Hashtable<String, Object>();
dic.put(DeviceStateVariableConstants.IP_ADDRESS_STATE_VARIABLE, "137.195.27.197");
iAction.invokeAction(dic);
dic = new Hashtable<String, Object>();
dic.put(DeviceStateVariableConstants.IP_ADDRESS_STATE_VARIABLE, "137.195.27.198");
iAction.invokeAction(dic);
}
//this.rfidDriver.connect("137.195.27.197");
//this.rfidDriver.connect("137.195.27.198");
}
}
public RfidServer(){
logging.debug("started!");
UIManager.put("ClassLoader", ClassLoader.getSystemClassLoader());
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void registerForRFIDEvents(String deviceId){
String eventFilter = "(&" +
"(" + CSSEventConstants.EVENT_NAME + "=" + DeviceMgmtEventConstants.RFID_READER_EVENT + ")" +
"(" + CSSEventConstants.EVENT_SOURCE + "=" + deviceId + ")" +
")";
this.logging.debug("Registering for RFIDEvent: "+eventFilter);
this.eventMgr.subscribeInternalEvent(this, new String[]{EventTypes.RFID_UPDATE_EVENT}, eventFilter);
}
/*
* This method is called by the RFIDUpdateTimerTask every minute to
* send the symbolic locations to the appropriate user
*/
@Override
public void sendRemoteUpdate(String tagNumber, String symLoc){
if (this.tagtoIdentityTable.containsKey(tagNumber)){
String jid = this.tagtoIdentityTable.get(tagNumber);
updateTagToSymloc(symLoc, tagNumber);
//String clientServiceID = this.dpiToServiceID.get(dpi);
//this.sendUpdateMessage(dpi, clientServiceID, rfidTagNumber, symLoc);
this.rfidClientRemote.sendUpdate(jid, symLoc, tagNumber);
}
}
public void updateTagToSymloc(String symloc, String tag) {
this.tagtoSymlocTable.remove(tag);//remove last entry if exists
this.tagtoSymlocTable.put(tag,symloc);
this.ctxRetriever.setTagToSymloc(tagtoSymlocTable);
this.ctxRetriever.updateContext();
logging.debug("Tag to Symloc Updated!");
}
/*
* Method called when an RFID_UPDATE_EVENT is received
*/
public void sendUpdate(String wUnit, String rfidTagNumber) {
if (this.wUnitToSymlocTable.containsKey(wUnit)){
this.logging.debug("wUnit: "+wUnit+" matches symloc: "+wUnitToSymlocTable.get(wUnit));
if (this.tagToTimerTable.containsKey(rfidTagNumber)){
this.tagToTimerTable.get(rfidTagNumber).setSymLoc(this.wUnitToSymlocTable.get(wUnit));
this.logging.debug("setting symloc: "+this.wUnitToSymlocTable.get(wUnit)+" to: "+rfidTagNumber);
}else{
if (this.tagtoIdentityTable.containsKey(rfidTagNumber)){
this.logging.debug("tag "+rfidTagNumber+" registered to identity "+tagtoIdentityTable.get(rfidTagNumber));
RFIDUpdateTimerTask task = new RFIDUpdateTimerTask(this, rfidTagNumber, this.wUnitToSymlocTable.get(wUnit), this.tagtoIdentityTable.get(rfidTagNumber));
this.tagToTimerTable.put(rfidTagNumber, task);
Timer timer = new Timer();
timer.schedule(task, new Date(), 5000);
this.logging.debug("Created timer");
}
}
}else{
this.logging.debug("wUnit :"+wUnit+" doesn't match any symLoc");
}
}
@Override
public void registerRFIDTag(String tagNumber, String dpiAsString, String serviceID, String password) {
logging.debug("Received request to register RFID tag: "+tagNumber+" from identity: "+dpiAsString+" and serviceID: "+serviceID+" and password: "+password);
if (this.tagToPasswordTable.containsKey(tagNumber)){
String myPass = this.tagToPasswordTable.get(tagNumber);
logging.debug("Tag exists");
if (myPass.equalsIgnoreCase(password)){
this.removeOldRegistration(dpiAsString);
this.tagtoIdentityTable.put(tagNumber, dpiAsString);
this.ctxRetriever.setTagToIdentity(tagtoIdentityTable);
this.ctxRetriever.setTagToPassword(tagToPasswordTable);
this.ctxRetriever.setTagToSymloc(tagtoSymlocTable);//MAYBE DONT NEED?!
this.ctxRetriever.updateContext();
this.rfidClientRemote.acknowledgeRegistration(dpiAsString, 0);
logging.debug("Registration successfull. Sent Acknowledgement 0");
}else{
this.rfidClientRemote.acknowledgeRegistration(dpiAsString, 1);
logging.debug("Registration unsuccessfull. Sent Ack 1");
}
}else{
this.rfidClientRemote.acknowledgeRegistration(dpiAsString, 2);
logging.debug("Registration unsuccessfull. Sent Ack 2");
}
}
@Override
public void unregisterRFIDTag(String tagNumber, String dpiAsString, String serviceID, String password) {
logging.debug("Received request to unregister RFID tag: "+tagNumber+" from identity: "+dpiAsString+" and serviceID: "+serviceID+" and password: "+password);
this.tagtoIdentityTable.remove(tagNumber);
this.tagToPasswordTable.remove(tagNumber);
this.tagToPasswordTable.put(tagNumber, getPassword());
this.ctxRetriever.setTagToIdentity(tagtoIdentityTable);
this.ctxRetriever.setTagToPassword(tagToPasswordTable);
this.ctxRetriever.updateContext();
//TODO ACK's
this.rfidClientRemote.acknowledgeRegistration(dpiAsString, 3);
logging.debug("UnRegistration successfull. Sent Acknowledgement 3");
}
public void removeOldRegistration( String dpiAsString){
if (this.tagtoIdentityTable.contains(dpiAsString)){
Enumeration<String> tags = this.tagtoIdentityTable.keys();
while (tags.hasMoreElements()){
String tag = tags.nextElement();
String dpi = this.tagtoIdentityTable.get(tag);
if (dpi.equalsIgnoreCase(dpiAsString)){
this.tagtoIdentityTable.remove(tag);
/*if (this.dpiToServiceID.containsKey(dpiAsString)){
this.dpiToServiceID.remove(dpiAsString);
}*/
return;
}
}
}
}
@Override
public void deleteTag(String tag) {
this.tagtoIdentityTable.remove(tag);
this.tagToPasswordTable.remove(tag);
this.ctxRetriever.setTagToIdentity(tagtoIdentityTable);
this.ctxRetriever.setTagToPassword(tagToPasswordTable);
this.ctxRetriever.updateContext();
this.logging.debug("deleted rfidTag: "+tag);
this.printInformation();
}
//CHECKS IF TAG IS REGISTERED TO A USER, THEN REQUESTS TO UNREGISTER. OR DELETES TAG IF NO REG
public void requestDeleteTag(String tag){
String id = tagtoIdentityTable.get(tag);
if(id!=null)
{
this.rfidClientRemote.deleteTag(id, tag);
//this.rfidClientRemote.acknowledgeRegistration(identity, rStatus);
//TAG HAS BEEN REGISTERED WITH ID
}
else
{
deleteTag(tag);
}
}
private void printInformation(){
Enumeration<String> keys = this.tagToPasswordTable.keys();
int i=1;
while(keys.hasMoreElements()){
String nextElement = keys.nextElement();
if (this.tagtoIdentityTable.containsKey(nextElement)){
this.logging.debug("Rfid record "+i+") rfidTag: "+nextElement+", password: "+tagToPasswordTable.get(nextElement)+", identity: "+this.tagtoIdentityTable.get(nextElement));
}else{
this.logging.debug("Rfid record "+i+") rfidTag: "+nextElement+", password: "+tagToPasswordTable.get(nextElement));
}
i++;
}
}
public String getPassword() {
int n = 4;
char[] pw = new char[n];
int c = 'A';
int r1 = 0;
for (int i=0; i < n; i++)
{
r1 = (int)(Math.random() * 3);
switch(r1) {
case 0: c = '0' + (int)(Math.random() * 10); break;
case 1: c = 'a' + (int)(Math.random() * 26); break;
case 2: c = 'A' + (int)(Math.random() * 26); break;
}
pw[i] = (char)c;
}
return new String(pw);
}
public void addTag(String tagNumber, String password){
this.tagToPasswordTable.put(tagNumber, password);
this.tagtoIdentityTable.remove(tagNumber);
this.ctxRetriever.setTagToIdentity(tagtoIdentityTable);
this.ctxRetriever.setTagToPassword(tagToPasswordTable);
this.ctxRetriever.updateContext();
this.printInformation();
}
/**
* @return the rfidClient
*/
public IRfidClient getRfidClientRemote() {
return rfidClientRemote;
}
/**
* @param rfidClientRemote the rfidClient to set
*/
public void setRfidClientRemote(IRfidClient rfidClientRemote) {
this.rfidClientRemote = rfidClientRemote;
}
// /**
// * @return the rfidDriver
// */
// public IRfidDriver getRfidDriver() {
// return rfidDriver;
// }
//
// /**
// * @param rfidDriver the rfidDriver to set
// */
// public void setRfidDriver(IRfidDriver rfidDriver) {
// this.rfidDriver = rfidDriver;
// }
@Override
public void handleExternalEvent(CSSEvent arg0) {
}
@Override
public void handleInternalEvent(InternalEvent event) {
// if (event.geteventInfo() instanceof RFIDUpdateEvent){
// RFIDUpdateEvent rfidEvent = (RFIDUpdateEvent) event.geteventInfo();
// this.sendUpdate(rfidEvent.getWakeupUnit(), rfidEvent.getRFIDTagNumber());
// this.logging.debug("Received RFIDUpdateEvent: "+rfidEvent.getWakeupUnit()+" - "+rfidEvent.getRFIDTagNumber() );
// }
HashMap<String, String> payload = (HashMap<String, String>)event.geteventInfo();
this.logging.debug("Received RFIDUpdateEvent: "+payload.get("wakeupUnit")+" - "+ payload.get("tagNumber"));
this.sendUpdate(payload.get("wakeupUnit"), payload.get("tagNumber"));
this.logging.debug("Sent rfid update WU:"+payload.get("wakeupUnit")+" tag: "+payload.get("tagNumber"));
}
@Override
public Object addingService(ServiceReference reference) {
iDevice = (IDevice) bundleContext.getService(reference);
return iDevice;
}
@Override
public void modifiedService(ServiceReference reference, Object service) {
}
@Override
public void removedService(ServiceReference reference, Object service) {
}
public ICommManager getCommManager() {
return commManager;
}
public void setCommManager(ICommManager commManager) {
this.commManager = commManager;
idManager = commManager.getIdManager();
serverIdentity = idManager.getThisNetworkNode();
}
public ICtxBroker getCtxBroker() {
return ctxBroker;
}
public void setCtxBroker(ICtxBroker ctxBroker) {
this.ctxBroker = ctxBroker;
}
}