/*
Copyright (C) 2005-2006 Nokia Corporation
Copyright (C) 2008-2011, Dirk Trossen, airs@dirk-trossen.de
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation as version 2.1 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.airs.platform;
import com.airs.helper.SerialPortLogger;
/**
* Class to handle discovery requests sent by remote application server
* Implements a {@link Callback} for the PUBLISH methods being created
*/
public class Discovery implements Callback, Runnable
{
private EventComponent current_EC;
private DIALOG_INFO dialog=null;
private int polltime=15000;
private String TO = new String("REMONT AS");
private String event_name = new String("available");
private void debug(String msg)
{
SerialPortLogger.debug(msg);
}
/**
* Sleep function
* @param millis
*/
private void sleep(long millis)
{
try
{
Thread.sleep(millis);
}
catch (InterruptedException ignore)
{
}
}
/**
* Constructor, starting the internal discovery thread
* @param current_EC Reference to the {@link EventComponent} that instantiates this component
*/
public Discovery(EventComponent current_EC)
{
this.current_EC = current_EC;
// start receiving thread in EventComponent
new Thread(this).start();
}
/**
* Runnable thread of this class for local discovery of sensors and generating PUBLISH methods
*/
public void run()
{
Sensor discovery_old, current, found;
boolean discover_changed;
int i;
char EOL;
StringBuffer discovery_data;
// form new line characters
EOL=13;
// sleep until connected to application server -> event component will signal this!
while(current_EC.connected == false)
sleep(1000);
while(true)
{
debug("Discovery::run: start Discovery");
// copy old list
discovery_old = SensorRepository.root_sensor;
// start new list
SensorRepository.deleteSensor();
// run through all handlers and discover locally first
for (i=0; i<HandlerManager.max_handlers;i++)
{
// is there any handler entry?
if (HandlerManager.handlers[i] != null)
// call discovery function of handler
HandlerManager.handlers[i].Discover();
}
discover_changed = false;
// now determine if new sensors are old sensors
current = discovery_old;
while(current!=null)
{
// can old sensor still be found in new ones?
if ((found = SensorRepository.findSensor(current.Symbol))!=null)
current.discovered = found.discovered = true;
else
discover_changed = true;
current = current.next;
}
// if all old ones are found, let's see if there are any new ones?
if (discover_changed == false)
{
current = SensorRepository.root_sensor;
while(current != null)
{
// something discovered that was not in old discovery?
if (current.discovered == false)
discover_changed = true;
current=current.next;
}
}
// now run through list for garbage collection
current = discovery_old;
while(current!=null)
{
found = current.next;
// dereference for garbage collection
current = null;
current = found;
}
// did anything change -> publish!
if (discover_changed == true)
{
debug("Discovery::run: ran through all handlers -> read Repository now!");
discovery_data = new StringBuffer();
i= 0 ;
current = SensorRepository.root_sensor;
while(current != null)
{
discovery_data.append(current.Symbol + "::" + current.Description + "::" + current.Unit + "::" + current.type + "::" + current.scaler + "::" + current.min + "::" + current.max);
discovery_data.append(EOL);
current = current.next;
i++;
}
// if there's no dialog -> create one
debug("Discovery::run: send out PUBLISH with " + i + " sensors");
if (dialog == null)
dialog=current_EC.Publish(TO.getBytes(), event_name.getBytes(), discovery_data.toString().getBytes(), (int)polltime/1000 + 5, this);
else
current_EC.Publish(dialog, TO.getBytes(), event_name.getBytes(), discovery_data.toString().getBytes(), (int)polltime/1000 + 5);
}
else
debug("Discovery::there is no change in the sensors -> No PUBLISH!");
sleep(polltime);
}
}
/**
* Callback function for CONFIRMs of the (discovery) publications
* @param dialog Reference to the {@link DIALOG_INFO} for the CONFIRM dialog
*/
public void callback(DIALOG_INFO dialog)
{
debug("Discovery::callback:received method");
debug("...FROM : " + new String(dialog.current_method.FROM.string));
debug("...TO : " + new String(dialog.current_method.TO.string));
// what method type??
switch(dialog.current_method.method_type)
{
case method_type.method_CONFIRM:
// set state rightin order to send further NOTIFYs
dialog.dialog_state = dialog_state.PUBLICATION_VALID;
debug("...it's a CONFIRM - doing nothing");
// unlock dialog -> do not forget otherwise the dialog becomes unusuable!
dialog.locked = false;
break;
default:
// unlock dialog -> do not forget otherwise the dialog becomes unusuable!
dialog.locked = false;
debug("...there is another method - shouldn't happen");
}
}
}