Skip to content

Commit

Permalink
Add M2Web polling thread
Browse files Browse the repository at this point in the history
  • Loading branch information
alexjhawk committed Jun 2, 2023
1 parent 45637b6 commit 45b59ae
Showing 1 changed file with 186 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package com.hms_networks.americas.sc.ignition.threading;

import com.hms_networks.americas.sc.ignition.comm.M2WebCommunicationManager;
import com.hms_networks.americas.sc.ignition.comm.responses.m2w.M2WebEwon;
import com.hms_networks.americas.sc.ignition.comm.responses.m2w.M2WebEwonEBDTagListResponse;
import com.hms_networks.americas.sc.ignition.comm.responses.m2w.M2WebGetEwonsResponse;
import com.hms_networks.americas.sc.ignition.config.EwonConnectorSettings;
import com.hms_networks.americas.sc.ignition.data.TagManager;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A thread that polls for M2Web data at a specified interval. The polling logic is defined in the
* {@link DMWebPollingThread#run()} method. The polling interval can be changed at runtime by
* calling the {@link DMWebPollingThread#setPollingInterval(long, TimeUnit)} method.
*
* @author HMS Networks, MU Americas Solution Center
* @since 2.0.0
* @version 1.0.0
*/
public class M2WebPollingThread extends PollingThread {

/**
* Log handler for {@link M2WebPollingThread}.
*
* @since 2.0.0
*/
private static final Logger LOGGER = LoggerFactory.getLogger(M2WebPollingThread.class);

/**
* Interval for updating the cached list of Ewon gateways in the M2Web API. This is used to ensure
* that the list of Ewon gateways is up-to-date.
*
* @since 1.0.0
*/
private static final long EWONS_LIST_UPDATE_INTERVAL_MS = TimeUnit.MINUTES.toMillis(30);

/**
* Last time (in milliseconds) the cached list of Ewon gateways was updated in the M2Web API.
*
* @since 1.0.0
*/
private long lastEwonsListUpdateTimeMs = 0;

/**
* The cached list of Ewon gateways ({@link M2WebEwon}s).
*
* @since 1.0.0
*/
private List<M2WebEwon> ewons;

/**
* Creates a new polling thread with the specified thread polling interval. The default polling
* interval start delay is used ({@link #DEFAULT_POLLING_INTERVAL_START_DELAY}).
*
* @param pollingInterval The thread polling interval.
* @param pollingIntervalTimeUnit The thread polling interval time unit.
* @param connectorSettings The Ewon connector settings.
* @since 1.0.0
*/
public M2WebPollingThread(
long pollingInterval,
TimeUnit pollingIntervalTimeUnit,
EwonConnectorSettings connectorSettings) {
super(pollingInterval, pollingIntervalTimeUnit, connectorSettings);
}

/**
* Creates a new polling thread with the specified thread polling interval and polling interval
* start delay. The start delay is the amount of time to delay before the first poll interval
* starts.
*
* @param pollingInterval The thread polling interval.
* @param pollingIntervalStartDelay The thread polling interval start delay.
* @param pollingIntervalTimeUnit The thread polling interval time unit.
* @param connectorSettings The Ewon connector settings.
* @since 1.0.0
*/
public M2WebPollingThread(
long pollingInterval,
long pollingIntervalStartDelay,
TimeUnit pollingIntervalTimeUnit,
EwonConnectorSettings connectorSettings) {
super(pollingInterval, pollingIntervalStartDelay, pollingIntervalTimeUnit, connectorSettings);
}

/**
* When an object implementing interface <code>Runnable</code> is used to create a thread,
* starting the thread causes the object's <code>run</code> method to be called in that separately
* executing thread.
*
* <p>The general contract of the method <code>run</code> is that it may take any action
* whatsoever.
*
* @see Thread#run()
* @since 1.0.0
*/
@Override
public void run() {
// Check if Ewons list needs to be updated
long timeSinceLastEwonsListUpdateMs = System.currentTimeMillis() - lastEwonsListUpdateTimeMs;
boolean ewonsListNeedsUpdate = timeSinceLastEwonsListUpdateMs >= EWONS_LIST_UPDATE_INTERVAL_MS;

// If Ewons list needs to be updated, update it
if (ewonsListNeedsUpdate) {
Future<M2WebGetEwonsResponse> ewonGatewayList =
M2WebCommunicationManager.getEwonGatewayList(connectorSettings.getAuthInfo());
try {
M2WebGetEwonsResponse getEwonsResponse = ewonGatewayList.get();
ewons = getEwonsResponse.getEwons();
lastEwonsListUpdateTimeMs = System.currentTimeMillis();
if (connectorSettings.isDebugEnabled()) {
LOGGER.debug("Updated Ewon gateway list from M2Web API.");
}
} catch (InterruptedException e) {
LOGGER.error(
"Failed to get updated Ewon gateway list from M2Web API due to an interruption.", e);
} catch (ExecutionException e) {
LOGGER.error(
"Failed to get updated Ewon gateway list from M2Web API due to an exception during"
+ " execution.",
e);
}
}

// If Ewons list updated, update tag list for each Ewon
if (ewonsListNeedsUpdate && ewons != null) {
for (M2WebEwon ewon : ewons) {
Future<M2WebEwonEBDTagListResponse> ewonTagList =
M2WebCommunicationManager.getEwonTagList(
connectorSettings.getAuthInfo(), ewon.getName());
try {
M2WebEwonEBDTagListResponse getEwonTagListResponse = ewonTagList.get();
// TODO: Handle response of tag list
if (connectorSettings.isDebugEnabled()) {
LOGGER.debug(
"Updated Ewon tag list for device [" + ewon.getName() + "] from M2Web API.");
}
} catch (InterruptedException e) {
LOGGER.error(
"Failed to get updated Ewon tag list for device ["
+ ewon.getName()
+ "] from M2Web API due to an interruption.",
e);
} catch (ExecutionException e) {
LOGGER.error(
"Failed to get updated Ewon tag list for device ["
+ ewon.getName()
+ "] from M2Web API due to an exception during execution.",
e);
}
}
}

// Update tag data via M2Web for eligible Ewons + tags
if (connectorSettings.isForceLive()) {
// TODO: Update tag data for all tags
} else {
// Update tag data for forced Ewons
for (String forcedRealtimeEwonName : TagManager.getForcedM2WebEwons()) {
// TODO: Get realtime value data for forced Ewon
// TODO: Update tag data for forced Ewon
}

// Update tag data for forced tags (if parent Ewon not already forced realtime)
for (Map.Entry<String, List<String>> forcedRealtimeEwonTags :
TagManager.getForcedM2WebEwonTags().entrySet()) {
// Get parent Ewon name
String forcedRealtimeEwonName = forcedRealtimeEwonTags.getKey();

// If parent Ewon not already forced realtime, update tag data for forced tags
if (!TagManager.getForcedM2WebEwons().contains(forcedRealtimeEwonName)) {
// TODO: Get realtime value data for parent Ewon

// TODO: Update tag data for forced tags on Ewon
for (String forcedRealtimeEwonTag : forcedRealtimeEwonTags.getValue()) {}
}
}
}
}
}

0 comments on commit 45b59ae

Please sign in to comment.