Added scanning button animation, detection of scannable controllers and scan start

This commit is contained in:
Ziver Koc 2021-06-09 22:17:32 +02:00
parent 6656882859
commit a80a1c5cdc
26 changed files with 100 additions and 70 deletions

View file

@ -132,4 +132,17 @@ body {
}
.c3-line {
stroke-width: 2px;
}
}
.anim-spin {
animation: spin 2s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}

View file

@ -50,15 +50,24 @@
<tr>
<td>{{.getClass().getName()}}</td>
<td>
{{#.isScannable()}}
<div class="btn-toolbar pull-right">
<form method="POST">
<input type="hidden" name="action" value="controller_scan">
<input type="hidden" name="controller" value="{{.getClass().getName()}}">
{{#.isScanning()}}
<button type="submit" class="btn btn-primary btn-xs" style="padding: 1px 20px;" disabled>
<span class="glyphicon glyphicon-refresh anim-spin"></span>
</button>
{{/.isScanning()}}
{{^.isScanning()}}
<button type="submit" class="btn btn-primary btn-xs" style="padding: 1px 20px;">
<span class="glyphicon glyphicon-search"></span>
</button>
{{/.isScanning()}}
</form>
{{/.isScannable()}}
</div>
</td>
</tr>

View file

@ -92,7 +92,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
}
Class<? extends HalEventController> c = event.getController();
HalEventController controller = controllerMap.get(c);
HalEventController controller = (HalEventController) controllerMap.get(c);
if (controller != null) {
logger.info("Deregistering event(id: " + event.getId() + "): " + event.getDeviceConfig().getClass());
controller.deregister(event.getDeviceConfig());
@ -175,14 +175,6 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
logger.warning("No controller found for event id: "+ event.getId());
}
/**
* @return all instantiated controllers.
*/
@Override
public Collection<HalEventController> getControllers() {
return controllerMap.values();
}
public static EventControllerManager getInstance(){
return instance;

View file

@ -4,8 +4,8 @@ import zutil.ClassUtil;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -19,7 +19,7 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
private static final Logger logger = LogUtil.getLogger();
/** A map of all instantiated controllers **/
protected HashMap<Class, T> controllerMap = new HashMap<>();
protected static Map<Class, HalAbstractController> controllerMap = new ConcurrentHashMap<>();
/** All available sensor plugins **/
protected List<Class<? extends C>> availableDeviceConfigs = new ArrayList<>();
@ -44,7 +44,7 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
@SuppressWarnings("unchecked")
Class<T> controllerClass = (Class<T>) deviceConfig.getDeclaredConstructor().newInstance().getDeviceControllerClass();
if (controllerClass.isAssignableFrom(HalAutoScannableController.class)) {
if (controllerClass.isAssignableFrom(HalAutostartController.class)) {
getControllerInstance(controllerClass); // Instantiate controller
}
} catch (Exception e) {
@ -111,14 +111,14 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
/**
* @return all active instantiated controllers.
*/
public Collection<T> getControllers() {
return controllerMap.values();
public static List<HalAbstractController> getControllers() {
return new ArrayList<>(controllerMap.values());
}
/**
* Will return a singleton controller instance of the given class.
* If a instance does not exist yet the a new instance will be allocated
* depending on if the controller is ready thorough the {@link HalAutoScannableController#isAvailable()} method.
* depending on if the controller is ready thorough the {@link HalAutostartController#isAvailable()} method.
*
* @param clazz is the class of the wanted object instance wanted
* @return A singleton instance of the input clazz or null if the class is unavailable or not ready to be instantiated.
@ -127,14 +127,14 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
T controller;
if (controllerMap.containsKey(clazz)) {
controller = controllerMap.get(clazz);
controller = (T) controllerMap.get(clazz);
} else {
try {
// Instantiate controller
controller = clazz.getDeclaredConstructor().newInstance();
if (controller instanceof HalAutoScannableController &&
! ((HalAutoScannableController) controller).isAvailable()) {
if (controller instanceof HalAutostartController &&
! ((HalAutostartController) controller).isAvailable()) {
logger.warning("Controller is not ready: " + clazz.getName());
return null;
}
@ -162,7 +162,7 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
* @param controller is the controller instance.
*/
protected void removeControllerIfEmpty(HalAbstractController controller){
if (controller instanceof HalAutoScannableController)
if (controller instanceof HalAutostartController)
return; // Don't do anything if controller is scannable
if (controller.size() < 0){

View file

@ -4,7 +4,7 @@ package se.hal.intf;
* A interface that indicates that the implementing
* controller can be auto started when HalServer starts up.
*/
public interface HalAutoScannableController {
public interface HalAutostartController {
/**
* Indicates if the controller has all the configuration

View file

@ -15,4 +15,13 @@ public interface HalScannableController {
* @return a boolean indication if a scan is still ongoing.
*/
boolean isScanning();
/**
* Function that can be used by template to identify a scannable controller.
*
* @return always true.
*/
default boolean isScannable() {
return true;
}
}

View file

@ -3,7 +3,7 @@ package se.hal.page;
import se.hal.EventControllerManager;
import se.hal.HalContext;
import se.hal.intf.HalWebPage;
import se.hal.struct.ClassConfigurationData;
import se.hal.util.ClassConfigurationFacade;
import se.hal.struct.Event;
import se.hal.struct.User;
import zutil.ObjectUtil;
@ -24,7 +24,7 @@ public class EventConfigWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/event_config.tmpl";
private ArrayList<ClassConfigurationData> eventConfigurations = new ArrayList<>();
private ArrayList<ClassConfigurationFacade> eventConfigurations = new ArrayList<>();
public EventConfigWebPage() {
@ -32,7 +32,7 @@ public class EventConfigWebPage extends HalWebPage {
super.getRootNav().createSubNav("Settings").createSubNav(this.getId(), "Event Settings").setWeight(200);
for (Class c : EventControllerManager.getInstance().getAvailableDeviceConfigs())
eventConfigurations.add(new ClassConfigurationData(c));
eventConfigurations.add(new ClassConfigurationFacade(c));
}
@Override

View file

@ -4,6 +4,7 @@ import se.hal.HalContext;
import se.hal.HalServer;
import se.hal.intf.HalAbstractController;
import se.hal.intf.HalAbstractControllerManager;
import se.hal.intf.HalScannableController;
import se.hal.intf.HalWebPage;
import zutil.ObjectUtil;
import zutil.io.file.FileUtil;
@ -52,25 +53,36 @@ public class PluginConfigWebPage extends HalWebPage {
case "controller_scan":
String controllerName = request.get("controller");
HalAbstractController controller = null;
for (HalAbstractController c : HalAbstractControllerManager.getControllers()) {
if (c.getClass().getName().equals(controllerName)) {
controller = c;
break;
}
}
if (controller != null) {
if (controller instanceof HalScannableController) {
((HalScannableController) controller).startScan();
HalAlertManager.getInstance().addAlert(new UserMessage(
MessageLevel.SUCCESS, "Initiated scanning on controller: " + controllerName, MessageTTL.ONE_VIEW));
} else {
HalAlertManager.getInstance().addAlert(new UserMessage(
MessageLevel.ERROR, "Controller " + controllerName + " does not support scanning.", MessageTTL.ONE_VIEW));
}
} else {
HalAlertManager.getInstance().addAlert(new UserMessage(
MessageLevel.ERROR, "Unable to find controller: " + controllerName, MessageTTL.ONE_VIEW));
}
break;
}
}
List<HalAbstractController> controllers = new LinkedList<>();
for (HalAbstractControllerManager manager : HalServer.getControllerManagers()) {
Collection<HalAbstractController> managerControllers = manager.getControllers();
if (!ObjectUtil.isEmpty(managerControllers)) {
for (HalAbstractController controller : managerControllers) {
if (!controllers.contains(controller))
controllers.add(controller);
}
}
}
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
tmpl.set("plugins", HalServer.getAllPlugins());
tmpl.set("controllers", controllers);
tmpl.set("controllers", HalAbstractControllerManager.getControllers());
return tmpl;
}
}

View file

@ -3,7 +3,7 @@ package se.hal.page;
import se.hal.HalContext;
import se.hal.SensorControllerManager;
import se.hal.intf.HalWebPage;
import se.hal.struct.ClassConfigurationData;
import se.hal.util.ClassConfigurationFacade;
import se.hal.struct.Sensor;
import se.hal.struct.User;
import zutil.ObjectUtil;
@ -23,7 +23,7 @@ public class SensorConfigWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/sensor_config.tmpl";
private ArrayList<ClassConfigurationData> sensorConfigurations;
private ArrayList<ClassConfigurationFacade> sensorConfigurations;
public SensorConfigWebPage() {
@ -32,7 +32,7 @@ public class SensorConfigWebPage extends HalWebPage {
sensorConfigurations = new ArrayList<>();
for (Class c : SensorControllerManager.getInstance().getAvailableDeviceConfigs())
sensorConfigurations.add(new ClassConfigurationData(c));
sensorConfigurations.add(new ClassConfigurationFacade(c));
}
@Override

View file

@ -4,7 +4,7 @@ import se.hal.HalContext;
import se.hal.TriggerManager;
import se.hal.intf.HalWebPage;
import se.hal.struct.Action;
import se.hal.struct.ClassConfigurationData;
import se.hal.util.ClassConfigurationFacade;
import se.hal.struct.Trigger;
import se.hal.struct.TriggerFlow;
import zutil.ObjectUtil;
@ -23,8 +23,8 @@ public class TriggerWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/trigger.tmpl";
private ArrayList<ClassConfigurationData> triggerConfigurators;
private ArrayList<ClassConfigurationData> actionConfigurators;
private ArrayList<ClassConfigurationFacade> triggerConfigurators;
private ArrayList<ClassConfigurationFacade> actionConfigurators;
public TriggerWebPage() {
@ -33,10 +33,10 @@ public class TriggerWebPage extends HalWebPage {
triggerConfigurators = new ArrayList<>();
for (Class c : TriggerManager.getInstance().getAvailableTriggers())
triggerConfigurators.add(new ClassConfigurationData(c));
triggerConfigurators.add(new ClassConfigurationFacade(c));
actionConfigurators = new ArrayList<>();
for (Class c : TriggerManager.getInstance().getAvailableActions())
actionConfigurators.add(new ClassConfigurationData(c));
actionConfigurators.add(new ClassConfigurationFacade(c));
}
@Override

View file

@ -1,4 +1,4 @@
package se.hal.struct;
package se.hal.util;
import zutil.ui.conf.Configurator;
import zutil.ui.conf.Configurator.ConfigurationParam;
@ -6,12 +6,12 @@ import zutil.ui.conf.Configurator.ConfigurationParam;
/**
* A Data class used by the dynamic class configuration pages
*/
public class ClassConfigurationData {
public class ClassConfigurationFacade {
public Class clazz;
public ConfigurationParam[] params;
public ClassConfigurationData(Class clazz) {
public ClassConfigurationFacade(Class clazz) {
this.clazz = clazz;
this.params = Configurator.getConfiguration(clazz);
}

View file

@ -39,7 +39,7 @@ import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HalMqttController implements HalAutoScannableController, MqttSubscriptionListener, HalEventController {
public class HalMqttController implements HalAutostartController, MqttSubscriptionListener, HalEventController {
private final Logger logger = LogUtil.getLogger();
private MulticastDnsServer mDns;

View file

@ -2,6 +2,6 @@
"version": 0.1,
"name": "Hal-MQTT",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.mqtt.HalMqttController"}
{"se.hal.intf.HalAutostartController": "se.hal.plugin.mqtt.HalMqttController"}
]
}

View file

@ -19,7 +19,7 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class NetScanController implements HalEventController, HalAutoScannableController, InetScanListener, Runnable {
public class NetScanController implements HalEventController, HalAutostartController, InetScanListener, Runnable {
public static Logger logger = LogUtil.getLogger();
private static final int NETWORK_SYNC_INTERVAL = 3 * 60 * 60 * 1000; // 3 hours
private static final int PING_INTERVAL = 10 * 1000; // 10 sec

View file

@ -2,7 +2,7 @@
"version": 1.0,
"name": "Hal-Network Scanner",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.netscan.NetScanController"},
{"se.hal.intf.HalAutostartController": "se.hal.plugin.netscan.NetScanController"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.netscan.NetworkDevice"}
]
}

View file

@ -49,7 +49,7 @@
package se.hal.plugin.nutups;
import se.hal.HalContext;
import se.hal.intf.HalAutoScannableController;
import se.hal.intf.HalAutostartController;
import se.hal.intf.HalDeviceConfig;
import se.hal.intf.HalDeviceReportListener;
import se.hal.intf.HalSensorController;
@ -64,7 +64,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
public class NutUpsController implements HalSensorController, HalAutoScannableController, Runnable {
public class NutUpsController implements HalSensorController, HalAutostartController, Runnable {
public static Logger logger = LogUtil.getLogger();
private static final int SYNC_INTERVAL = 60 * 1000;

View file

@ -2,7 +2,7 @@
"version": 1.0,
"name": "Hal-NUT UPS",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.nutups.NutUpsController"},
{"se.hal.intf.HalAutostartController": "se.hal.plugin.nutups.NutUpsController"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.nutups.NutUpsDevice"}
]
}

View file

@ -47,11 +47,6 @@ public class CameraControllerManager extends HalAbstractControllerManager<HalCam
}
@Override
public Collection<HalCameraController> getControllers() {
return null;
}
public void initialize(PluginManager pluginManager){
super.initialize(pluginManager);

View file

@ -29,7 +29,7 @@ import se.hal.intf.HalWebPage;
import se.hal.page.HalAlertManager;
import se.hal.plugin.nvr.CameraControllerManager;
import se.hal.plugin.nvr.struct.Camera;
import se.hal.struct.ClassConfigurationData;
import se.hal.util.ClassConfigurationFacade;
import se.hal.struct.User;
import zutil.ObjectUtil;
import zutil.db.DBConnection;
@ -47,7 +47,7 @@ public class CameraConfigWebPage extends HalWebPage {
private static final Logger logger = LogUtil.getLogger();
private static final String TEMPLATE = HalContext.RESOURCE_WEB_ROOT + "/camera_config.tmpl";
private ArrayList<ClassConfigurationData> cameraConfigurations;
private ArrayList<ClassConfigurationFacade> cameraConfigurations;
public CameraConfigWebPage() {
@ -56,7 +56,7 @@ public class CameraConfigWebPage extends HalWebPage {
cameraConfigurations = new ArrayList<>();
for (Class c : CameraControllerManager.getInstance().getAvailableDeviceConfigs())
cameraConfigurations.add(new ClassConfigurationData(c));
cameraConfigurations.add(new ClassConfigurationFacade(c));
}
@Override

View file

@ -46,7 +46,7 @@ import java.util.logging.Logger;
* communication and reporting to Hal
*/
public class TellstickSerialComm implements Runnable,
HalSensorController, HalEventController, HalAutoScannableController {
HalSensorController, HalEventController, HalAutostartController {
private static final Logger logger = LogUtil.getLogger();
private static String CONFIG_TELLSTICK_COM_PORT = "tellstick.com_port";

View file

@ -2,7 +2,7 @@
"version": 1.0,
"name": "Hal-Tellstick",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.tellstick.TellstickSerialComm"},
{"se.hal.intf.HalAutostartController": "se.hal.plugin.tellstick.TellstickSerialComm"},
{"se.hal.intf.HalSensorConfig": "se.hal.plugin.tellstick.device.Oregon0x1A2D"},
{"se.hal.intf.HalEventConfig": "se.hal.plugin.tellstick.device.NexaSelfLearning"}

View file

@ -36,7 +36,7 @@ import java.util.logging.Logger;
* <p>
* Rest documentatiuon for deConz: https://dresden-elektronik.github.io/deconz-rest-doc/
*/
public class DeConzZigbeeController implements HalSensorController, HalEventController, HalAutoScannableController {
public class DeConzZigbeeController implements HalSensorController, HalEventController, HalAutostartController {
private static final Logger logger = LogUtil.getLogger();
public static final String CONFIG_ZIGBEE_REST_URL = "zigbee.rest_url";

View file

@ -3,6 +3,6 @@
"name": "Hal-Zigbee-DeConz",
"description": "A Zigbee plugin interfacing with a DeConz service.",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.zigbee.deconz.zigbee.HalDeconzZigbeeController"}
{"se.hal.intf.HalAutostartController": "se.hal.plugin.zigbee.deconz.zigbee.HalDeconzZigbeeController"}
]
}

View file

@ -31,7 +31,7 @@ import java.util.logging.Logger;
*/
public class HalZigbeeController implements HalSensorController,
HalEventController,
HalAutoScannableController,
HalAutostartController,
ZigBeeAnnounceListener,
ZigBeeNetworkNodeListener,
HalScannableController {

View file

@ -3,6 +3,6 @@
"name": "Hal-Zigbee",
"description": "A Zigbee plugin for directly connecting to a CC2531 device over serial port.",
"interfaces": [
{"se.hal.intf.HalAutoScannableController": "se.hal.plugin.zigbee.HalZigbeeController"}
{"se.hal.intf.HalAutostartController": "se.hal.plugin.zigbee.HalZigbeeController"}
]
}

View file

@ -15,7 +15,7 @@ import java.util.logging.Logger;
*
* @author Ziver Koc
*/
public class HalZWaveController implements HalSensorController, HalEventController, HalAutoScannableController, NotificationWatcher {
public class HalZWaveController implements HalSensorController, HalEventController, HalAutostartController, NotificationWatcher {
private static final Logger logger = LogUtil.getLogger();
public static final String CONFIG_ZWAVE_PORT = "zwave.com_port";