/*******************************************************************************
* Copyright (c) 2008, 2009 Bug Labs, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - 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.
* - Neither the name of Bug Labs, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* 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 OWNER 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 com.buglabs.bug.base;
import java.io.FileNotFoundException;
import java.util.Calendar;
import java.util.Date;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.servlet.ServletException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
import com.buglabs.application.IServiceProvider;
import com.buglabs.application.RunnableWithServices;
import com.buglabs.application.ServiceTrackerHelper;
import com.buglabs.bug.base.pub.IBUG20BaseControl;
import com.buglabs.bug.base.pub.IShellService;
import com.buglabs.bug.base.pub.ITimeProvider;
import com.buglabs.bug.input.pub.InputEventProvider;
import com.buglabs.device.ButtonEvent;
import com.buglabs.device.IButtonEventListener;
import com.buglabs.device.IButtonEventProvider;
import com.buglabs.support.SupportInfoTextFormatter;
import com.buglabs.support.SupportInfoXMLFormatter;
import com.buglabs.util.LogServiceUtil;
/**
* This bundle offers base unit features to the runtime, such as date/time and
* power information.
*
* @author kgilmer
*
*/
public class Activator implements BundleActivator, ITimeProvider, IButtonEventListener {
private static final String BUG_BASE_VERSION_KEY = "bug.base.version";
private static final String INFO_SERVLET_PATH = "/support";
private static final String INFO_SERVLET_HTML_PATH = "/support.html";
private static final String DEVNODE_BUGNAV = "/dev/input/user_button";
private static final String DEVNODE_BUGPOWER = "/dev/input/power_button";
private static Activator ref;
private ServiceRegistration timeReg;
//private ServiceRegistration audioReg;
private LogService logService;
private BUGBaseControl bbc;
private ServiceRegistration baseControlReg;
private ServiceTracker httpTracker;
private ServiceRegistration sr;
private InputEventProvider userbep;
private ServiceRegistration userBepReg;
private BundleContext context;
private InputEventProvider powerbep;
private ServiceRegistration powerBepReg;
public Date getTime() {
return Calendar.getInstance().getTime();
}
/**
* Register all the OSGi services that this bundle provides.
*
* @param context
*/
private void registerServices(BundleContext context) {
timeReg = context.registerService(ITimeProvider.class.getName(), this, null);
userBepReg = context.registerService(IButtonEventProvider.class.getName(), userbep, getUserButtonProperties());
powerBepReg = context.registerService(IButtonEventProvider.class.getName(), powerbep, getPowerButtonProperties());
if (bbc != null) {
baseControlReg = context.registerService(IBUG20BaseControl.class.getName(), bbc, getBaseControlServiceProperties());
}
/*if (soundplayer != null) {
audioReg = context.registerService(IBaseAudioPlayer.class.getName(), soundplayer, null);
}
try {
btReg = context.registerService(LocalDevice.class.getName(), LocalDevice.getLocalDevice(), null);
// I'm also going to need to figure out whether hci0 is the base
// bluetooth or whatever
// need to think this through more
} catch (BluetoothStateException e) {
logService.log(LogService.LOG_INFO, "No Bluetooth Device found. Not registering javax.bluetooth.LocalDevice as a service");
}
*/
}
private Dictionary<String, String> getPowerButtonProperties() {
Dictionary<String, String> d = new Hashtable<String, String>();
d.put("Provider", this.getClass().getName());
d.put("Button", "Power");
return d;
}
private Dictionary<String, String> getUserButtonProperties() {
Dictionary<String, String> d = new Hashtable<String, String>();
d.put("Provider", this.getClass().getName());
d.put("Button", "User");
return d;
}
/**
* @return A dictionary with properties for base control
*/
private Dictionary<String, String> getBaseControlServiceProperties() {
Dictionary<String, String> d = new Hashtable<String, String>();
d.put(BUG_BASE_VERSION_KEY, getBaseVersion());
return d;
}
/**
* @return version of BUG base this code is running on.
*/
private String getBaseVersion() {
return "2.0";
}
public void start(final BundleContext context) throws Exception {
this.context = context;
ref = this;
logService = LogServiceUtil.getLogService(context);
// Set base version property.
System.setProperty(BUG_BASE_VERSION_KEY, getBaseVersion());
try {
bbc = new BUGBaseControl();
//see http://redmine.buglabs.net/issues/show/1424
bbc.setLEDTrigger(IBUG20BaseControl.LED_POWER, IBUG20BaseControl.COLOR_BLUE, "none");
bbc.setLEDBrightness(IBUG20BaseControl.LED_POWER, 255);
} catch (FileNotFoundException e) {
logService.log(LogService.LOG_ERROR, "Unable to initialize LEDs. " + e.getMessage());
}
userbep = new InputEventProvider(DEVNODE_BUGNAV, logService);
userbep.start();
powerbep = new InputEventProvider(DEVNODE_BUGPOWER, logService);
powerbep.start();
//listen for the power button to be hit, then toggle the LED sequence for user feedback. see
//http://redmine.buglabs.net/issues/show/1429#note-4
powerbep.addListener(this);
registerServices(context);
// Create a ST for the HTTP Service, create the 'info' servlet when
// available.
httpTracker = ServiceTrackerHelper.createAndOpen(context, HttpService.class.getName(), new RunnableWithServices() {
public void allServicesAvailable(IServiceProvider serviceProvider) {
try {
logService.log(LogService.LOG_INFO, "Registering info service.");
HttpService httpService = (HttpService) serviceProvider.getService(HttpService.class);
// register xml version
httpService.registerServlet(INFO_SERVLET_PATH, new SupportServlet(new BUGSupportInfo(context), new SupportInfoXMLFormatter()), null, null);
// register html version
httpService.registerServlet(INFO_SERVLET_HTML_PATH, new SupportServlet(new BUGSupportInfo(context), new SupportInfoTextFormatter()), null, null);
} catch (ServletException e) {
logService.log(LogService.LOG_ERROR, "An error occurred launching Info servlet: " + e.getMessage());
} catch (NamespaceException e) {
logService.log(LogService.LOG_ERROR, "An error occurred launching Info servlet: " + e.getMessage());
}
}
public void serviceUnavailable(IServiceProvider serviceProvider, ServiceReference sr, Object service) {
((HttpService) serviceProvider.getService(HttpService.class)).unregister(INFO_SERVLET_PATH);
}
});
sr = context.registerService(IShellService.class.getName(), new ShellService(), null);
signalStartup();
}
/**
* Signal to user that OSGi runtime is up and running.
*/
private void signalStartup() {
Thread t = new Thread(new Runnable() {
public void run() {
try {
bbc.setLEDColor(IBUG20BaseControl.LED_POWER, IBUG20BaseControl.COLOR_RED, true);
Thread.sleep(300);
bbc.setLEDColor(IBUG20BaseControl.LED_POWER, IBUG20BaseControl.COLOR_GREEN, true);
Thread.sleep(300);
bbc.setLEDColor(IBUG20BaseControl.LED_POWER, IBUG20BaseControl.COLOR_BLUE, true);
} catch (Exception e) {
}
}
});
t.start();
}
private void signalShutdown() {
Thread t = new Thread(new Runnable() {
public void run() {
try {
logService.log(LogService.LOG_INFO, "Power Button engaged: base bundle signalling via LEDs shutdown sequence initiated");
bbc.setLEDTrigger(IBUG20BaseControl.LED_POWER , IBUG20BaseControl.COLOR_BLUE, "heartbeat");
} catch (Exception e) {
}
}
});
t.start();
}
public void stop(BundleContext context) throws Exception {
sr.unregister();
httpTracker.close();
unregisterServices(context);
}
private void unregisterServices(BundleContext context) {
timeReg.unregister();
if (baseControlReg !=null){
baseControlReg.unregister();
}
userBepReg.unregister();
powerBepReg.unregister();
}
public static Activator getDefault() {
return ref;
}
public BundleContext getBundleContext() {
return context;
}
@Override
public void buttonEvent(ButtonEvent event) {
if (event.getButton() == 116 && event.getAction() == ButtonEvent.KEY_UP){
logService.log(LogService.LOG_DEBUG, "base bundle received Power Button event: "+event.getButton());
signalShutdown();
}
}
}