diff --git a/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue b/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue
new file mode 100644
index 0000000000..84c876a584
--- /dev/null
+++ b/ScadaLTS-UI-1/src/components/form/SleepAndReactivationDS.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+ Stop
+ Sleep
+ None
+
+ It will disable the datasource
+ when the attempted connections fail and try reconnect according to the reactivity configuration
+
+
+
+
+
+
+
+
+
+ Minute
+ Hour
+ Day
+
+
+
+
+
+
+
time to next attempt to enable data source: {{timeToNextTryEnableDs | infoTime}}
+
+
+
+
+
+
+
+
+
+
diff --git a/ScadaLTS-UI-1/src/main.js b/ScadaLTS-UI-1/src/main.js
index 793acd7f79..6a5d21227c 100644
--- a/ScadaLTS-UI-1/src/main.js
+++ b/ScadaLTS-UI-1/src/main.js
@@ -8,6 +8,8 @@ import Test from './components/Test'
import IsAlive from './components/IsAlive'
import ExportImportPointHierarchy from './components/ExportImportPointHierarchy'
import SimpleComponentSVG from './components/SimpleComponentSVG'
+
+import SleepAndReactivationDS from './components/form/SleepAndReactivationDS'
import router from './router'
import VJsoneditor from 'vue-jsoneditor';
import Vuetify from 'vuetify';
@@ -52,7 +54,8 @@ new Vue({
el: '#app',
components: {
"simple-component-svg": SimpleComponentSVG,
- "export-import-ph": ExportImportPointHierarchy
+ "export-import-ph": ExportImportPointHierarchy,
+ "sleep-reactivation-ds": SleepAndReactivationDS,
}
})
diff --git a/WebContent/WEB-INF/classes/messages_de.properties b/WebContent/WEB-INF/classes/messages_de.properties
index 924f9a741b..31afc2899c 100644
--- a/WebContent/WEB-INF/classes/messages_de.properties
+++ b/WebContent/WEB-INF/classes/messages_de.properties
@@ -3162,6 +3162,10 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
+ds.state.startSleep=Data source has been started after sleeped
diff --git a/WebContent/WEB-INF/classes/messages_en.properties b/WebContent/WEB-INF/classes/messages_en.properties
index 8d218bd1fe..dc4a47feb0 100644
--- a/WebContent/WEB-INF/classes/messages_en.properties
+++ b/WebContent/WEB-INF/classes/messages_en.properties
@@ -3165,4 +3165,8 @@ ds.state.apiChangeEnableStateDs=\ With the use of the API, the on/off status of
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_es.properties b/WebContent/WEB-INF/classes/messages_es.properties
index 6956a84c67..a0b2a29ed4 100644
--- a/WebContent/WEB-INF/classes/messages_es.properties
+++ b/WebContent/WEB-INF/classes/messages_es.properties
@@ -3090,4 +3090,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_fi.properties b/WebContent/WEB-INF/classes/messages_fi.properties
index e08539e355..7b8d5b4989 100644
--- a/WebContent/WEB-INF/classes/messages_fi.properties
+++ b/WebContent/WEB-INF/classes/messages_fi.properties
@@ -2912,3 +2912,7 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
diff --git a/WebContent/WEB-INF/classes/messages_fr.properties b/WebContent/WEB-INF/classes/messages_fr.properties
index f6c856122b..07f6232258 100644
--- a/WebContent/WEB-INF/classes/messages_fr.properties
+++ b/WebContent/WEB-INF/classes/messages_fr.properties
@@ -3166,4 +3166,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_lu.properties b/WebContent/WEB-INF/classes/messages_lu.properties
index 6c48e7027c..52bc3f2a77 100644
--- a/WebContent/WEB-INF/classes/messages_lu.properties
+++ b/WebContent/WEB-INF/classes/messages_lu.properties
@@ -3176,4 +3176,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_nl.properties b/WebContent/WEB-INF/classes/messages_nl.properties
index 4ddcfacebf..77087b9771 100644
--- a/WebContent/WEB-INF/classes/messages_nl.properties
+++ b/WebContent/WEB-INF/classes/messages_nl.properties
@@ -2716,4 +2716,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_pl.properties b/WebContent/WEB-INF/classes/messages_pl.properties
index 1bb9c37996..37fe88cc5a 100644
--- a/WebContent/WEB-INF/classes/messages_pl.properties
+++ b/WebContent/WEB-INF/classes/messages_pl.properties
@@ -3078,4 +3078,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_pt.properties b/WebContent/WEB-INF/classes/messages_pt.properties
index fd2938b7fd..101fa714ed 100644
--- a/WebContent/WEB-INF/classes/messages_pt.properties
+++ b/WebContent/WEB-INF/classes/messages_pt.properties
@@ -3157,3 +3157,7 @@ ds.state.importChangeEnableStateDs=During the import, the on/off status of DataS
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
diff --git a/WebContent/WEB-INF/classes/messages_ru.properties b/WebContent/WEB-INF/classes/messages_ru.properties
index af512dc5a9..59836183bc 100644
--- a/WebContent/WEB-INF/classes/messages_ru.properties
+++ b/WebContent/WEB-INF/classes/messages_ru.properties
@@ -3127,4 +3127,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/classes/messages_zh.properties b/WebContent/WEB-INF/classes/messages_zh.properties
index b5b563a95a..4913c31152 100644
--- a/WebContent/WEB-INF/classes/messages_zh.properties
+++ b/WebContent/WEB-INF/classes/messages_zh.properties
@@ -2030,4 +2030,8 @@ ds.state.apiChangeEnableStateDs=With the use of the API, the on/off status of Da
ds.state.importChangeEnableStateDs=During the import, the on/off status of DataSource was changed
ds.state.scryptChangeEnable=The script has changed the on/off status of datasource
ds.state.userCpChangeEnableStateDs=The user has copied datasource. The datasource is off by default
-dsList.statusDescribe=Status description
\ No newline at end of file
+dsList.statusDescribe=Status description
+event.reactivation.sleep=Data source has been sleeped
+event.ds.describe={1}
+ds.state.startSleep=Data source has been started after sleeped
+ds.state.sleep=Data source has been sleeped after several attempted connections had failed
\ No newline at end of file
diff --git a/WebContent/WEB-INF/jsp/dataSourceEdit.jsp b/WebContent/WEB-INF/jsp/dataSourceEdit.jsp
index 47437c7beb..46326ded40 100644
--- a/WebContent/WEB-INF/jsp/dataSourceEdit.jsp
+++ b/WebContent/WEB-INF/jsp/dataSourceEdit.jsp
@@ -73,7 +73,7 @@
rowCreator: function(options) {
var tr = document.createElement("tr");
tr.mangoId = "p"+ options.rowData.id;
- tr.className = "row"+ (options.rowIndex % 2 == 0 ? "" : "Alt");
+ tr.className = ""+ (options.rowIndex % 2 == 0 ? "" : "rowAlt");
return tr;
},
cellCreator: function(options) {
diff --git a/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp b/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp
index bdb6a4ee75..6445cd7554 100644
--- a/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp
+++ b/WebContent/WEB-INF/jsp/dataSourceEdit/editHttpRetriever.jsp
@@ -18,8 +18,31 @@
--%>
<%@ include file="/WEB-INF/jsp/include/tech.jsp" %>
<%@page import="com.serotonin.mango.DataTypes"%>
+
+
@@ -146,12 +180,12 @@
-
Stop
- (It will disable the datasource
- when the attempted connections fail)
+
+
+
+
-
@@ -227,4 +261,5 @@
-
\ No newline at end of file
+
+<%@ include file="/WEB-INF/jsp/include/tech-vuejs.jsp"%>
\ No newline at end of file
diff --git a/src/com/serotonin/mango/rt/RuntimeManager.java b/src/com/serotonin/mango/rt/RuntimeManager.java
index 7f5b21f796..4dcf88e77d 100644
--- a/src/com/serotonin/mango/rt/RuntimeManager.java
+++ b/src/com/serotonin/mango/rt/RuntimeManager.java
@@ -25,6 +25,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import com.serotonin.mango.vo.dataSource.http.ICheckReactivation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
@@ -127,7 +128,14 @@ synchronized public void initialize(boolean safe) {
List> configs = dataSourceDao.getDataSources();
List> pollingRound = new ArrayList>();
for (DataSourceVO> config : configs) {
- if (config.isEnabled()) {
+
+ boolean isCheckToTrayEnableRun = (config instanceof ICheckReactivation);
+ boolean isToTrayEnable = false;
+ if (isCheckToTrayEnableRun) {
+ isToTrayEnable = ((ICheckReactivation) config).checkToTrayEnable();
+ }
+
+ if (config.isEnabled() || isToTrayEnable ) {
if (safe) {
config.setEnabled(false);
dataSourceDao.saveDataSource(config);
@@ -310,7 +318,7 @@ private boolean initializeDataSource(DataSourceVO> vo) {
return false;
// Ensure that the data source is enabled.
- Assert.isTrue(vo.isEnabled());
+ // Assert.isTrue(vo.isEnabled());
// Create and initialize the runtime version of the data source.
DataSourceRT dataSource = vo.createDataSourceRT();
diff --git a/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java b/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java
index 1443edf096..669eda1605 100644
--- a/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java
+++ b/src/com/serotonin/mango/rt/dataSource/DataSourceRT.java
@@ -21,10 +21,7 @@
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import com.serotonin.ShouldNeverHappenException;
import com.serotonin.mango.Common;
@@ -137,6 +134,15 @@ public void forcePointRead(@SuppressWarnings("unused") DataPointRT dataPoint) {
// No op by default. Override as required.
}
+ public static void raiseEvent(String describe, DataSourceVO vo) {
+ LocalizableMessage message = new LocalizableMessage("event.ds.describe", "", describe);
+ int urgentAlarmLevel = 2;
+ DataSourceEventType dset = new DataSourceEventType(vo.getId(), vo.getId(), urgentAlarmLevel, 0);
+ Map context = new HashMap();
+ context.put("dataSource", vo);
+ Common.ctx.getEventManager().raiseEvent(dset, new Date().getTime(), true, dset.getAlarmLevel(), message, context);
+ }
+
protected void raiseEvent(int eventId, long time, boolean rtn, LocalizableMessage message) {
message = new LocalizableMessage("event.ds", vo.getName(), message);
DataSourceEventType type = getEventType(eventId);
diff --git a/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java b/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java
index dac60d3166..c018c29582 100644
--- a/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java
+++ b/src/com/serotonin/mango/rt/dataSource/http/HttpRetrieverDataSourceRT.java
@@ -35,9 +35,12 @@
import com.serotonin.web.http.HttpUtils;
import com.serotonin.web.i18n.LocalizableException;
import com.serotonin.web.i18n.LocalizableMessage;
-import org.scada_lts.ds.StopDsRT;
-
-import java.util.Date;
+import org.scada_lts.ds.StartStopDsRT;
+import org.scada_lts.ds.model.ReactivationDs;
+import org.scada_lts.ds.reactivation.MenagerReactivation;
+import org.scada_lts.ds.reactivation.ReactivationConnectHttpRetriever;
+import org.scada_lts.ds.state.SleepStateDs;
+import org.scada_lts.ds.state.StopChangeEnableStateDs;
/**
* @author Matthew Lohbihler
@@ -71,7 +74,7 @@ public void setPointValue(DataPointRT dataPoint, PointValueTime valueTime, SetPo
protected void doPoll(long time) {
String data;
try {
- data = getData(vo.getUrl(), vo.getTimeoutSeconds(), vo.getRetries(), vo.isStop());
+ data = getData(vo.getUrl(), vo.getTimeoutSeconds(), vo.getRetries(), vo.isStop(), vo.getReactivation());
} catch (Exception e) {
LocalizableMessage lm;
if (e instanceof LocalizableException)
@@ -119,7 +122,31 @@ protected void doPoll(long time) {
returnToNormal(PARSE_EXCEPTION_EVENT, time);
}
- public String getData(String url, int timeoutSeconds, int retries, boolean stop) throws LocalizableException {
+ public static boolean testConnection(String url, int timeoutSeconds, int retries) {
+ String data = "";
+ for (int i = 0; i <= retries; i++) {
+ HttpClient client = Common.getHttpClient(timeoutSeconds * 1000);
+ GetMethod method = null;
+ LocalizableMessage message;
+ try {
+ method = new GetMethod(url);
+ int responseCode = client.executeMethod(method);
+ if (responseCode == HttpStatus.SC_OK) {
+ data = HttpUtils.readResponseBody(method, READ_LIMIT);
+ return true;
+ }
+ message = new LocalizableMessage("event.http.response", url, responseCode);
+ } catch (Exception e) {
+ message = DataSourceRT.getExceptionMessage(e);
+ } finally {
+ if (method != null)
+ method.releaseConnection();
+ }
+ }
+ return false;
+ }
+
+ public String getData(String url, int timeoutSeconds, int retries, boolean stop, ReactivationDs r) throws LocalizableException {
String data = "";
for (int i = 0; i <= retries; i++) {
HttpClient client = Common.getHttpClient(timeoutSeconds * 1000);
@@ -141,11 +168,15 @@ public String getData(String url, int timeoutSeconds, int retries, boolean stop)
}
if (retries == i && stop) {
- LocalizableMessage lm = new LocalizableMessage("event.httpRetriever.retrievalError", vo.getUrl(), "Data source has been stopped/interrupted after several attempted connections had failed");
- raiseEvent(DATA_RETRIEVAL_FAILURE_EVENT, new Date().getTime(), true, lm);
- StopDsRT stopDsRT = new StopDsRT(vo.getId());
+ StartStopDsRT stopDsRT = new StartStopDsRT(vo.getId(), false, new StopChangeEnableStateDs());
+ new Thread(stopDsRT).start();
+ } else if (retries == i && r.isSleep()) {
+ ReactivationConnectHttpRetriever rhr = new ReactivationConnectHttpRetriever();
+ MenagerReactivation.getInstance().addProcess(rhr, r, vo);
+ StartStopDsRT stopDsRT = new StartStopDsRT(vo.getId(),false, new SleepStateDs());
new Thread(stopDsRT).start();
- } else if (retries == i) {
+ }
+ else if (retries == i) {
throw new LocalizableException(message);
}
}
diff --git a/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java b/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java
index 311296687e..be1b1f2907 100644
--- a/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java
+++ b/src/com/serotonin/mango/vo/dataSource/DataSourceVO.java
@@ -69,6 +69,7 @@
import com.serotonin.web.i18n.LocalizableMessage;
import org.scada_lts.ds.state.MigrationOrErrorSerializeChangeEnableState;
import org.scada_lts.ds.state.IStateDs;
+import org.scada_lts.ds.state.change.ChangeStatus;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -76,7 +77,7 @@
import java.io.Serializable;
import java.util.*;
-abstract public class DataSourceVO> implements
+abstract public class DataSourceVO> extends ChangeStatus implements
Serializable, Cloneable, JsonSerializable, ChangeComparable {
public enum Type {
EBI25(16, "dsEdit.ebi25", false) {
@@ -397,11 +398,15 @@ public void setEnabled(boolean enabled) {
}
public IStateDs getState() {
+
return state;
}
public void setState(IStateDs state) {
- this.state = state;
+ notifyListeners(
+ this,
+ this.state,
+ this.state = state);
}
public int getId() {
diff --git a/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java b/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java
index b9897b2b0c..999309b03f 100644
--- a/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java
+++ b/src/com/serotonin/mango/vo/dataSource/http/HttpRetrieverDataSourceVO.java
@@ -40,12 +40,13 @@
import com.serotonin.util.StringUtils;
import com.serotonin.web.dwr.DwrResponseI18n;
import com.serotonin.web.i18n.LocalizableMessage;
+import org.scada_lts.ds.model.ReactivationDs;
/**
* @author Matthew Lohbihler
*/
@JsonRemoteEntity
-public class HttpRetrieverDataSourceVO extends DataSourceVO {
+public class HttpRetrieverDataSourceVO extends DataSourceVO implements ICheckReactivation{
public static final Type TYPE = Type.HTTP_RETRIEVER;
@Override
@@ -100,6 +101,9 @@ public HttpRetrieverPointLocatorVO createPointLocator() {
@JsonRemoteProperty
private boolean stop = false;
+ @JsonRemoteProperty
+ private ReactivationDs reactivation = new ReactivationDs();
+
public String getUrl() {
return url;
}
@@ -148,7 +152,13 @@ public void setStop(boolean stop) {
this.stop = stop;
}
+ public ReactivationDs getReactivation() {
+ return reactivation;
+ }
+ public void setReactivation(ReactivationDs reactivation) {
+ this.reactivation = reactivation;
+ }
@Override
public void validate(DwrResponseI18n response) {
@@ -171,7 +181,8 @@ protected void addPropertiesImpl(List list) {
AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.url", url);
AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.timeout", timeoutSeconds);
AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.retries", retries);
- AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.retries", stop );
+ AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.stop", stop );
+ AuditEventType.addPropertyMessage(list, "dsEdit.httpRetriever.reactivation", reactivation );
}
@Override
@@ -182,7 +193,8 @@ protected void addPropertyChangesImpl(List list, HttpRetriev
AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.timeout", from.timeoutSeconds,
timeoutSeconds);
AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.retries", from.retries, retries);
- AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.retries", from.stop, stop);
+ AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.stop", from.stop, stop);
+ AuditEventType.maybeAddPropertyChangeMessage(list, "dsEdit.httpRetriever.reactivation", from.stop, stop);
}
//
@@ -201,6 +213,7 @@ private void writeObject(ObjectOutputStream out) throws IOException {
out.writeInt(timeoutSeconds);
out.writeInt(retries);
out.writeBoolean(stop);
+ out.writeObject(reactivation);
}
private void readObject(ObjectInputStream in) throws IOException {
@@ -219,6 +232,11 @@ private void readObject(ObjectInputStream in) throws IOException {
} catch (Exception e) {
stop = false;
}
+ try {
+ reactivation = (ReactivationDs) in.readObject();
+ } catch (Exception e) {
+ reactivation = new ReactivationDs(false, (short) 1,(short) 1);
+ }
}
}
@@ -235,4 +253,9 @@ public void jsonSerialize(Map map) {
super.jsonSerialize(map);
serializeUpdatePeriodType(map, updatePeriodType);
}
+
+ @Override
+ public boolean checkToTrayEnable() {
+ return isEnabled() || isStop() || reactivation.isSleep();
+ }
}
diff --git a/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java b/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java
new file mode 100644
index 0000000000..df026fe383
--- /dev/null
+++ b/src/com/serotonin/mango/vo/dataSource/http/ICheckReactivation.java
@@ -0,0 +1,9 @@
+package com.serotonin.mango.vo.dataSource.http;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 31.10.18
+ */
+public interface ICheckReactivation {
+
+ boolean checkToTrayEnable();
+}
diff --git a/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java b/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java
index 279be9a532..990d0ce3c4 100644
--- a/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java
+++ b/src/com/serotonin/mango/web/dwr/DataSourceEditDwr.java
@@ -88,6 +88,7 @@
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.db.IntValuePair;
import com.serotonin.io.StreamUtils;
+import org.scada_lts.ds.model.ReactivationDs;
import org.scada_lts.modbus.SerialParameters;
import com.serotonin.mango.Common;
import com.serotonin.mango.DataTypes;
@@ -1280,6 +1281,28 @@ public DwrResponseI18n saveHttpRetrieverDataSource(String name, String xid,
return tryDataSourceSave(ds);
}
+ @MethodFilter
+ public DwrResponseI18n saveHttpRetrieverDataSourceWithReactivationOptions(String name, String xid,
+ int updatePeriods, int updatePeriodType, String url,
+ int timeoutSeconds, int retries, boolean stop, boolean sleep, short typeReactivation, short valueReactivation) {
+ HttpRetrieverDataSourceVO ds = (HttpRetrieverDataSourceVO) Common
+ .getUser().getEditDataSource();
+
+ ds.setXid(xid);
+ ds.setName(name);
+ ds.setUpdatePeriods(updatePeriods);
+ ds.setUpdatePeriodType(updatePeriodType);
+ ds.setUrl(url);
+ ds.setTimeoutSeconds(timeoutSeconds);
+ ds.setRetries(retries);
+ ds.setStop(stop);
+ ReactivationDs rDs = new ReactivationDs(sleep, typeReactivation, valueReactivation);
+ ds.setReactivation(rDs);
+
+ return tryDataSourceSave(ds);
+ }
+
+
@MethodFilter
public DwrResponseI18n saveHttpRetrieverPointLocator(int id, String xid,
String name, HttpRetrieverPointLocatorVO locator) {
diff --git a/src/org/scada_lts/dao/SerializationData.java b/src/org/scada_lts/dao/SerializationData.java
index 703fdca15c..dd44cff302 100644
--- a/src/org/scada_lts/dao/SerializationData.java
+++ b/src/org/scada_lts/dao/SerializationData.java
@@ -40,12 +40,14 @@ public class SerializationData {
public Object readObject(final InputStream is) {
if (is != null) {
- try {
- return new ObjectInputStream(is).readObject();
- } catch (ClassNotFoundException | IOException e) {
- LOG.error(e);
- throw new StreamDaoException(e);
- }
+ synchronized (is) {
+ try {
+ return new ObjectInputStream(is).readObject();
+ } catch (ClassNotFoundException | IOException e) {
+ LOG.error(e);
+ throw new StreamDaoException(e);
+ }
+ }
}
return null;
}
diff --git a/src/org/scada_lts/ds/StartStopDsRT.java b/src/org/scada_lts/ds/StartStopDsRT.java
new file mode 100644
index 0000000000..dcc27caba9
--- /dev/null
+++ b/src/org/scada_lts/ds/StartStopDsRT.java
@@ -0,0 +1,44 @@
+package org.scada_lts.ds;
+
+import com.serotonin.mango.Common;
+import com.serotonin.mango.rt.RuntimeManager;
+import com.serotonin.mango.vo.dataSource.DataSourceVO;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.scada_lts.ds.state.IStateDs;
+import org.scada_lts.ds.state.change.AlertObserver;
+
+/**
+ * @project Scada-LTS
+ * @autor grzegorz.bylica@gmail.com on 05.10.18
+ */
+public class StartStopDsRT implements Runnable {
+
+ private static final Log LOG = LogFactory.getLog(StartStopDsRT.class);
+
+ private int idDs;
+ private boolean enable;
+ private IStateDs state;
+
+ public StartStopDsRT(int idDs, boolean enable, IStateDs state) {
+ this.idDs = idDs;
+ this.enable = enable;
+ this.state = state;
+ }
+
+ @Override
+ public void run() {
+ try {
+ RuntimeManager runtimeManager = Common.ctx.getRuntimeManager();
+ DataSourceVO> dataSource = runtimeManager.getDataSource(idDs);
+ new AlertObserver(dataSource);
+ dataSource.setEnabled(enable);
+ dataSource.setState(state);
+ runtimeManager.saveDataSource(dataSource);
+
+ } catch (Exception e) {
+ LOG.error(e);
+ }
+
+ }
+}
diff --git a/src/org/scada_lts/ds/StopDsRT.java b/src/org/scada_lts/ds/StopDsRT.java
deleted file mode 100644
index bac6e662d5..0000000000
--- a/src/org/scada_lts/ds/StopDsRT.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.scada_lts.ds;
-
-import com.serotonin.mango.Common;
-import com.serotonin.mango.rt.RuntimeManager;
-import com.serotonin.mango.vo.dataSource.DataSourceVO;
-import org.scada_lts.ds.state.StopChangeEnableStateDs;
-
-/**
- * @project Scada-LTS
- * @autor grzegorz.bylica@gmail.com on 05.10.18
- */
-public class StopDsRT implements Runnable {
-
- private int idDs;
-
- public StopDsRT(int idDs) {
- this.idDs = idDs;
- }
-
- @Override
- public void run() {
- try {
- RuntimeManager runtimeManager = Common.ctx.getRuntimeManager();
- DataSourceVO> dataSource = runtimeManager.getDataSource(idDs);
- dataSource.setEnabled(false);
- dataSource.setState(new StopChangeEnableStateDs());
- runtimeManager.saveDataSource(dataSource);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-}
diff --git a/src/org/scada_lts/ds/model/ReactivationDs.java b/src/org/scada_lts/ds/model/ReactivationDs.java
new file mode 100644
index 0000000000..be1c61a579
--- /dev/null
+++ b/src/org/scada_lts/ds/model/ReactivationDs.java
@@ -0,0 +1,82 @@
+package org.scada_lts.ds.model;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 23.10.18
+ *
+ * Associated with class in vuejs SleepAndReactivationDS.vue
+ */
+public class ReactivationDs implements Serializable {
+
+ private static final long serialVersionUID = 8828977247133645961L;
+
+ public static final short TYPE_OF_SLEEP_MINUTE = 0;
+ public static final short TYPE_OF_SLEEP_HOUR = 1;
+ public static final short TYPE_OF_SLEEP_DAY = 2;
+
+ private boolean sleep;
+ private short type;
+ private short value;
+
+ public ReactivationDs() {
+ this.sleep = false;
+ this.type = TYPE_OF_SLEEP_MINUTE;
+ this.value = 1; // 1 minute
+ }
+
+ public ReactivationDs(boolean sleep, short type, short value) {
+ this.sleep = sleep;
+ this.type = type;
+ this.value = value;
+ }
+
+ public boolean isSleep() {
+ return sleep;
+ }
+
+ public void setSleep(boolean sleep) {
+ this.sleep = sleep;
+ }
+
+ public short getType() {
+ return type;
+ }
+
+ public void setType(short type) {
+ this.type = type;
+ }
+
+ public short getValue() {
+ return value;
+ }
+
+ public void setValue(short value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ReactivationDs that = (ReactivationDs) o;
+ return sleep == that.sleep &&
+ type == that.type &&
+ value == that.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sleep, type, value);
+ }
+
+ @Override
+ public String toString() {
+ return "ReactivationDs{" +
+ "sleep=" + sleep +
+ ", type=" + type +
+ ", value=" + value +
+ '}';
+ }
+}
diff --git a/src/org/scada_lts/ds/reactivation/MenagerReactivation.java b/src/org/scada_lts/ds/reactivation/MenagerReactivation.java
new file mode 100644
index 0000000000..d0a2b9b24e
--- /dev/null
+++ b/src/org/scada_lts/ds/reactivation/MenagerReactivation.java
@@ -0,0 +1,114 @@
+package org.scada_lts.ds.reactivation;
+
+import com.serotonin.mango.vo.dataSource.DataSourceVO;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+import org.quartz.utils.Key;
+import org.scada_lts.ds.model.ReactivationDs;
+
+import java.util.AbstractMap;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 24.10.18
+ */
+public class MenagerReactivation {
+
+ private static final Log LOG = LogFactory.getLog(MenagerReactivation.class);
+
+ private static final long MINUTE_IN_MILISECONDS = 60_000;
+ private static final long HOUR_IN_MILISECONDS = 3_600_000;
+ private static final long DAY_IN_MILISECONDS = 24 * HOUR_IN_MILISECONDS;
+
+ private static final String EVENT_MESSAGE_OF_REACTIVATION = "";
+
+ private ConcurrentHashMap> sleepDsIndexJobName = new ConcurrentHashMap>();
+ private ConcurrentHashMap sleepDsIndexIdDs = new ConcurrentHashMap<>();
+
+ private static final MenagerReactivation instance = new MenagerReactivation();
+ private Scheduler scheduler;
+
+ public MenagerReactivation() {
+ try {
+ this.scheduler = new StdSchedulerFactory().getScheduler();
+ this.scheduler.start();
+ } catch (SchedulerException e) {
+ LOG.error(e);
+ }
+ }
+
+ public static MenagerReactivation getInstance() {
+ return instance;
+ }
+
+ public void addProcess(StatefulJob sj, ReactivationDs rd, DataSourceVO> vo) {
+ LOG.info("addProcess");
+
+ JobDetail job = new JobDetail();
+ job.setName(sj.toString());
+ job.setJobClass(sj.getClass());
+
+ AbstractMap.SimpleImmutableEntry dsInfo = new AbstractMap.SimpleImmutableEntry<>(vo.getName(), vo.getId());
+ sleepDsIndexJobName.put(job.getKey().getName(), dsInfo);
+ sleepDsIndexIdDs.put(vo.getId(), job.getKey());
+
+ SimpleTrigger trigger = new SimpleTrigger();
+
+ Long interval = getAdditionalMilliseconds(rd);
+ Date startTime = new Date(System.currentTimeMillis() + interval );
+ LOG.info("process will be start:" + startTime);
+ trigger.setStartTime(startTime);
+ trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
+
+ LOG.trace("Quartz - "+sj.getClass()+ " interval: " + interval);
+ trigger.setRepeatInterval(interval);
+
+ trigger.setName("Quartz - trigger-"+sj.getClass()+"");
+
+ try {
+ scheduler.scheduleJob(job, trigger);
+ } catch (SchedulerException e) {
+ LOG.error(e);
+ }
+
+ }
+
+ public Map.Entry getId(String keyNameJob) {
+ return sleepDsIndexJobName.get(keyNameJob);
+ }
+
+ public void removeInfoAboutJob(String keyNameJob) {
+
+ Map.Entry dsInfo = sleepDsIndexJobName.get(keyNameJob);
+ sleepDsIndexIdDs.remove(dsInfo.getValue());
+ sleepDsIndexJobName.remove(keyNameJob);
+ }
+
+ public long getTimeToNextFire(int idDs) {
+
+ int ERROR = -1;
+ try {
+ Key key = sleepDsIndexIdDs.get(idDs);
+ return scheduler.getTriggersOfJob(key.getName(), key.getGroup())[0].getNextFireTime().getTime() - new Date().getTime();
+ } catch (SchedulerException e) {
+ LOG.error(e);
+ }
+ return ERROR;
+
+ }
+
+ private long getAdditionalMilliseconds(ReactivationDs r) {
+ if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_MINUTE) {
+ return r.getValue() * MINUTE_IN_MILISECONDS;
+ } else if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_HOUR) {
+ return r.getValue() * HOUR_IN_MILISECONDS;
+ } else if (r.getType() == ReactivationDs.TYPE_OF_SLEEP_DAY){
+ return r.getValue() * DAY_IN_MILISECONDS;
+ }
+ return 0;
+ }
+}
diff --git a/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java b/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java
new file mode 100644
index 0000000000..c63207bc8b
--- /dev/null
+++ b/src/org/scada_lts/ds/reactivation/ReactivationConnectHttpRetriever.java
@@ -0,0 +1,56 @@
+package org.scada_lts.ds.reactivation;
+
+import com.serotonin.mango.rt.dataSource.http.HttpRetrieverDataSourceRT;
+import com.serotonin.mango.vo.dataSource.DataSourceVO;
+import com.serotonin.mango.vo.dataSource.http.HttpRetrieverDataSourceVO;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.SchedulerException;
+import org.quartz.StatefulJob;
+import org.quartz.utils.Key;
+import org.scada_lts.dao.DataSourceDAO;
+import org.scada_lts.ds.StartStopDsRT;
+import org.scada_lts.ds.state.StartSleepStateDs;
+
+import java.util.Map;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 24.10.18
+ */
+public class ReactivationConnectHttpRetriever implements StatefulJob {
+
+ private static final Log LOG = LogFactory.getLog(ReactivationConnectHttpRetriever.class);
+
+ @Override
+ public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+
+ Key keyJob = jobExecutionContext.getJobDetail().getKey();
+
+ Map.Entry entry = MenagerReactivation.getInstance().getId(keyJob.getName());
+ int id = (int) entry.getValue();
+ String name = (String) entry.getKey();
+
+ DataSourceDAO dao = new DataSourceDAO();
+ DataSourceVO> ds = dao.getDataSource(id);
+
+ HttpRetrieverDataSourceVO hrds = (HttpRetrieverDataSourceVO) ds;
+
+ if (HttpRetrieverDataSourceRT.testConnection(hrds.getUrl(), hrds.getTimeoutSeconds(), hrds.getRetries())) {
+
+ try {
+ jobExecutionContext.getScheduler().deleteJob(keyJob.getName(), keyJob.getGroup());
+ } catch (SchedulerException e) {
+ LOG.error(e);
+ } finally {
+ StartStopDsRT stopDsRT = new StartStopDsRT(id,true, new StartSleepStateDs());
+ new Thread(stopDsRT).start();
+ MenagerReactivation.getInstance().removeInfoAboutJob(keyJob.getName());
+ }
+ } else {
+ // nothing to do
+ }
+
+ }
+}
diff --git a/src/org/scada_lts/ds/state/SleepStateDs.java b/src/org/scada_lts/ds/state/SleepStateDs.java
new file mode 100644
index 0000000000..d0044ea4f8
--- /dev/null
+++ b/src/org/scada_lts/ds/state/SleepStateDs.java
@@ -0,0 +1,19 @@
+package org.scada_lts.ds.state;
+
+import org.scada_lts.localization.ConfigLocalization;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 02.11.18
+ */
+public class SleepStateDs implements IStateDs, Serializable {
+
+ private static final String STOP_SLEEP = "ds.state.sleep";
+
+ @Override
+ public String getDescribe() {
+ return ConfigLocalization.getInstance().messageSource().getMessage(STOP_SLEEP, new Object[]{}, Locale.getDefault());
+ }
+}
diff --git a/src/org/scada_lts/ds/state/StartSleepStateDs.java b/src/org/scada_lts/ds/state/StartSleepStateDs.java
new file mode 100644
index 0000000000..714c5fa964
--- /dev/null
+++ b/src/org/scada_lts/ds/state/StartSleepStateDs.java
@@ -0,0 +1,20 @@
+package org.scada_lts.ds.state;
+
+import org.scada_lts.localization.ConfigLocalization;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 02.11.18
+ */
+public class StartSleepStateDs implements IStateDs, Serializable {
+
+ private static final String START_SLEEP = "ds.state.startSleep";
+
+ @Override
+ public String getDescribe() {
+ return ConfigLocalization.getInstance().messageSource().getMessage(START_SLEEP, new Object[]{}, Locale.getDefault());
+ }
+
+}
diff --git a/src/org/scada_lts/ds/state/change/AlertObserver.java b/src/org/scada_lts/ds/state/change/AlertObserver.java
new file mode 100644
index 0000000000..caf5512e5f
--- /dev/null
+++ b/src/org/scada_lts/ds/state/change/AlertObserver.java
@@ -0,0 +1,28 @@
+package org.scada_lts.ds.state.change;
+
+import com.serotonin.mango.rt.dataSource.http.HttpRetrieverDataSourceRT;
+import com.serotonin.mango.vo.dataSource.DataSourceVO;
+import org.scada_lts.ds.state.IStateDs;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 02.11.18
+ */
+public class AlertObserver implements PropertyChangeListener {
+
+ public AlertObserver(ChangeStatus changeManageStatus) {
+ changeManageStatus.addChangeListener(this);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
+
+ String describe = ((IStateDs) propertyChangeEvent.getNewValue()).getDescribe();
+ DataSourceVO> vo = (DataSourceVO>) propertyChangeEvent.getSource();
+
+ HttpRetrieverDataSourceRT.raiseEvent(describe, vo);
+
+ }
+}
diff --git a/src/org/scada_lts/ds/state/change/ChangeStatus.java b/src/org/scada_lts/ds/state/change/ChangeStatus.java
new file mode 100644
index 0000000000..085276c2c8
--- /dev/null
+++ b/src/org/scada_lts/ds/state/change/ChangeStatus.java
@@ -0,0 +1,33 @@
+package org.scada_lts.ds.state.change;
+
+import org.scada_lts.ds.state.IStateDs;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 02.11.18
+ */
+public class ChangeStatus {
+
+ private static final String STATE_PROPERTY = "state_property";
+
+ List listener;
+
+ protected ChangeStatus() {
+ listener = new ArrayList<>();
+ }
+
+ protected void notifyListeners(Object object, IStateDs oldValue, IStateDs newValue) {
+ for (PropertyChangeListener state : listener) {
+ state.propertyChange(new PropertyChangeEvent(object, STATE_PROPERTY, oldValue, newValue));
+ }
+ }
+
+ public void addChangeListener(PropertyChangeListener newListener) {
+ listener.add(newListener);
+ }
+
+}
diff --git a/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java b/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java
new file mode 100644
index 0000000000..b20e73d715
--- /dev/null
+++ b/src/org/scada_lts/web/mvc/api/ReactivationDsAPI.java
@@ -0,0 +1,41 @@
+package org.scada_lts.web.mvc.api;
+
+import com.serotonin.mango.Common;
+import com.serotonin.mango.vo.User;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.scada_lts.ds.reactivation.MenagerReactivation;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @autor grzegorz.bylica@gmail.com on 08.11.18
+ */
+@Controller
+public class ReactivationDsAPI {
+
+ private static final Log LOG = LogFactory.getLog(ReactivationDsAPI.class);
+
+ @RequestMapping(value = "/api/check-reactivation/{idDs}", method = RequestMethod.GET)
+ public ResponseEntity checkReactivation(@PathVariable(name="idDs") int idDs, HttpServletRequest request) {
+
+ LOG.info("/api/check-reactivation/{idDs} idDs:" + idDs);
+ try {
+ User user = Common.getUser(request);
+ if (user != null && user.isAdmin()) {
+ long time = MenagerReactivation.getInstance().getTimeToNextFire(idDs);
+ return new ResponseEntity(""+time, HttpStatus.OK);
+ } else {
+ return new ResponseEntity(HttpStatus.UNAUTHORIZED);
+ }
+ } catch (Exception e) {
+ return new ResponseEntity(e.toString(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+}