Package tcg.scada.da.modbus

Source Code of tcg.scada.da.modbus.ModbusSubsystem$PollingThread

package tcg.scada.da.modbus;

import java.util.ArrayList;
import java.util.Calendar;

import org.apache.log4j.NDC;

import tcg.common.LoggerManager;
import tcg.common.util.BufferParser;
import tcg.common.util.DetachedThread;
import tcg.scada.cos.CosDpQualityEnum;
import tcg.scada.cos.CosDpValueStruct;
import tcg.scada.cos.CosDpValueUnion;
import tcg.scada.da.DataPoint;
import tcg.scada.da.ESourceDataType;
import tcg.scada.da.ESubsystemType;
import tcg.scada.da.IDataPoint;
import tcg.scada.da.Subsystem;
import tcg.scada.da.SubsystemConfig;
import tcg.scada.modbus.EModbusFunctionCode;

/**
* Implementation of Modbus Subsystem. It contains poller to poll for data and
* status from Modbus subsystem.
*
* <p>
* Note: It expects the first words (address = 0) to be status word for the
* subystem. The first bit can be used to define which host (among a pair of
* host) is the preferred host (1 = preferred, 0 = normal). The subsequent bits
* can be used to pass the state/quality of a managed subsystem under this
* modbus subsystem (1 = managed subsystem is OK, 0 = managed subsystem is NOT
* OK). When the state of a managed subsystem is NOT_OK, all datapoints in the
* managed subsystem will be set to QualityBad.
* </p>
*
* <p><b>
* Note: Subsystem status word is the first word inside input registers.
* </b></p>
*
* @author Yoga
*
*/
public class ModbusSubsystem extends Subsystem
{
  // public static int OUTPUT_COIL = 1;
  // public static int INPUT_CONTACT = 2;
  // public static int HOLDING_REGISTER = 3;
  // public static int INPUT_REGISTER = 4;

  // private int primaryStatus_ = 0;
  // private int standbyStatus_ = 0;

  // private SubsystemConfig config_ = new SubsystemConfig();

  /**
   * Status polling segment
   */
  private PollingSegment statusSegment_ = new PollingSegment();

  /**
   * List of polling segment
   */
  private ArrayList<PollingSegment> segments_ = new ArrayList<PollingSegment>();

  /**
   * Primary modbus client, connected to primary host
   */
  private ModbusClient primaryHost_ = new ModbusClient();
 
  /**
   * Standby modbus client, connected to standby host
   */
  private ModbusClient standbyHost_ = new ModbusClient();
 
  /**
   * Active modbus client, ie. currently connected modbus client.
   */
  private ModbusClient activeHost_ = null;

  // control command (boolean). default: write-multiple-coils
  private int boolCommand_ = EModbusFunctionCode.FORCE_MULTIPLE_COILS;

  // control command (integer). default: write-multiple-registers
  private int intCommand_ = EModbusFunctionCode.PRESET_MULTIPLE_REGISTERS;

  // polling thread
  private PollingThread thread_ = new PollingThread(this);

  /**
   * Default ctor
   */
  public ModbusSubsystem()
  {
    // override the logger
    logger = LoggerManager.getLogger(ModbusSubsystem.class.toString());
    // default to bad quality
    quality = CosDpQualityEnum.QualityBad;
  }

  /**
   * Alternative ctor
   *
   * @param config
   *            - subsystem configuration
   */
  public ModbusSubsystem(SubsystemConfig config)
  {
    // configure the modbus client to primary host
    primaryHost_.setHost(config.primaryHost.deviceId,
        config.primaryHost.hostname, config.primaryHost.startPort,
        config.primaryHost.portRange);
    primaryHost_.setTimeOut(config.timeout.sockTimeoutMillis,
        config.timeout.connTimeoutMillis,
        config.timeout.idleTimeoutMillis);

    // configure the modbus client to standby host
    standbyHost_.setHost(config.standbyHost.deviceId,
        config.standbyHost.hostname, config.standbyHost.startPort,
        config.standbyHost.portRange);
    standbyHost_.setTimeOut(config.timeout.sockTimeoutMillis,
        config.timeout.connTimeoutMillis,
        config.timeout.idleTimeoutMillis);

    // TODO: retrieve the polling segments
    // TODO: implement properly. this might include retrieving the list of
    // polling segments

    // override the logger
    logger = LoggerManager.getLogger(ModbusSubsystem.class.toString());
    // default to bad quality
    quality = CosDpQualityEnum.QualityBad;
  }

  @Override
  public ESubsystemType getType()
  {
    return ESubsystemType.SUBSYSTEM_MODBUS;
  }

  @Override
  public void setPrimaryHost(int inDeviceId, String inHost, int inPort,
      short inPortRange)
  {
    primaryHost_.setHost((short) inDeviceId, inHost, inPort, inPortRange);
  }

  @Override
  public int getPrimaryHostDeviceId()
  {
    return primaryHost_.getDeviceId();
  }

  @Override
  public String getPrimaryHostName()
  {
    return primaryHost_.getHostName();
  }

  @Override
  public int getPrimaryHostPort()
  {
    return primaryHost_.getPort();
  }

  @Override
  public void setStandbyHost(int inDeviceId, String inHost, int inPort,
      short inPortRange)
  {
    standbyHost_.setHost((short) inDeviceId, inHost, inPort, inPortRange);
  }

  @Override
  public int getStandbyHostDeviceId()
  {
    return standbyHost_.getDeviceId();
  }

  @Override
  public String getStandbyHostName()
  {
    return standbyHost_.getHostName();
  }

  @Override
  public int getStandbyHostPort()
  {
    return standbyHost_.getPort();
  }

  @Override
  public void setTimeOut(int inSocketTimeOutMillis,
      int inConnectTimeOutMillis, int inIdleTimeOutMillis)
  {
    // set the modbus client's timeout setting
    primaryHost_.setTimeOut(inSocketTimeOutMillis, inConnectTimeOutMillis,
        inIdleTimeOutMillis);
    standbyHost_.setTimeOut(inSocketTimeOutMillis, inConnectTimeOutMillis,
        inIdleTimeOutMillis);
  }

  @Override
  public int getSocketTimeOut()
  {
    return primaryHost_.getSocketTimeOut();
  }

  @Override
  public int getConnectTimeOut()
  {
    return primaryHost_.getConnectTimeOut();
  }

  @Override
  public int getIdleTimeOut()
  {
    return primaryHost_.getIdleTimeOut();
  }

  @Override
  public void setControlCommand(int inBoolCommand, int inIntCommand)
  {
    // set boolean control command
    if (inBoolCommand == EModbusFunctionCode.FORCE_SINGLE_COIL)
    {
      inBoolCommand = EModbusFunctionCode.FORCE_SINGLE_COIL;
    }
    else
    {
      inBoolCommand = EModbusFunctionCode.FORCE_MULTIPLE_COILS;
    }

    // set integer control command
    if (inIntCommand == EModbusFunctionCode.PRESET_SINGLE_REGISTER)
    {
      inIntCommand = EModbusFunctionCode.PRESET_SINGLE_REGISTER;
    }
    else
    {
      inIntCommand = EModbusFunctionCode.PRESET_MULTIPLE_REGISTERS;
    }

    return;
  }

  @Override
  public boolean setControl(IDataPoint inDataPoint, boolean inValue)
  {
    boolean status = false;
    int retval = 0;

    // validation : datapoint
    if (inDataPoint == null)
    {
      return false;
    }

    // logging context
    NDC.push(inDataPoint.getName());

    // check if we use set-multiple-coils
    boolean[] states = null;
    if (boolCommand_ != EModbusFunctionCode.FORCE_SINGLE_COIL)
    {
      states = new boolean[1];
      states[0] = inValue;
    }

    // send using active host first if it is available
    if (activeHost_ != null)
    {
      logger.info("Sending boolean control to active host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (boolCommand_ == EModbusFunctionCode.FORCE_SINGLE_COIL)
        {
          retval = activeHost_.writeOutputCoil(inDataPoint
              .getAddress(), inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = activeHost_.writeOutputCoils(inDataPoint
              .getAddress(), 1, states);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send boolean control to active host. Exception: "
                + rte.getMessage());
      }
    }

    // send to primary host if it is not the current active host
    if (primaryHost_ != null && primaryHost_.isEnabled()
        && primaryHost_ != activeHost_)
    {
      logger.info("Sending boolean control to primary host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (boolCommand_ == EModbusFunctionCode.FORCE_SINGLE_COIL)
        {
          retval = primaryHost_.writeOutputCoil(inDataPoint
              .getAddress(), inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = primaryHost_.writeOutputCoils(inDataPoint
              .getAddress(), 1, states);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send boolean control to primary host. Exception: "
                + rte.getMessage());
      }
    }

    // send to standby host if it is not the current active host
    if (standbyHost_ != null && standbyHost_.isEnabled()
        && standbyHost_ != activeHost_)
    {
      logger.info("Sending boolean control to standby host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (boolCommand_ == EModbusFunctionCode.FORCE_SINGLE_COIL)
        {
          retval = standbyHost_.writeOutputCoil(inDataPoint
              .getAddress(), inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = standbyHost_.writeOutputCoils(inDataPoint
              .getAddress(), 1, states);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send boolean control to standby host. Exception: "
                + rte.getMessage());
      }
    }

    // logging context
    NDC.pop();

    return status;
  }

  @Override
  public boolean setControl(IDataPoint inDataPoint, int inValue)
  {
    boolean status = false;
    int retval = 0;

    // validation : datapoint
    if (inDataPoint == null)
    {
      return false;
    }

    // logging context
    NDC.push(inDataPoint.getName());

    // check if we use set-multiple-registers
    short[] values = null;
    if (intCommand_ != EModbusFunctionCode.PRESET_SINGLE_REGISTER)
    {
      values = new short[1];
      values[0] = (short) inValue;
    }

    // send using active host first if it is available
    if (activeHost_ != null)
    {
      logger.info("Sending integer control to active host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (intCommand_ == EModbusFunctionCode.PRESET_SINGLE_REGISTER)
        {
          retval = activeHost_.writeHoldingRegister(inDataPoint
              .getAddress(), (short) inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = activeHost_.writeHoldingRegisters(inDataPoint
              .getAddress(), 1, values);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send integer control to active host. Exception: "
                + rte.getMessage());
      }
    }

    // send to primary host if it is not the current active host
    if (primaryHost_ != null && primaryHost_.isEnabled()
        && primaryHost_ != activeHost_)
    {
      logger.info("Sending integer control to primary host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (intCommand_ == EModbusFunctionCode.PRESET_SINGLE_REGISTER)
        {
          retval = primaryHost_.writeHoldingRegister(inDataPoint
              .getAddress(), (short) inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = primaryHost_.writeHoldingRegisters(inDataPoint
              .getAddress(), 1, values);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send integer control to primary host. Exception: "
                + rte.getMessage());
      }
    }

    // send to standby host if it is not the current active host
    if (standbyHost_ != null && standbyHost_.isEnabled()
        && standbyHost_ != activeHost_)
    {
      logger.info("Sending integer control to standby host. Address: "
          + inDataPoint.getAddress() + ". Value: " + inValue);
      try
      {
        if (intCommand_ == EModbusFunctionCode.PRESET_SINGLE_REGISTER)
        {
          retval = standbyHost_.writeHoldingRegister(inDataPoint
              .getAddress(), (short) inValue);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
        else
        {
          retval = standbyHost_.writeHoldingRegisters(inDataPoint
              .getAddress(), 1, values);
          if (retval == 1)
          {
            // successful
            status = true;
          }
        }
      }
      catch (RuntimeException rte)
      {
        logger
            .warn("Can not send integer control to standby host. Exception: "
                + rte.getMessage());
      }
    }

    // logging context
    NDC.pop();

    return status;
  }

  @Override
  public boolean startControl()
  {
    // check if it is already running
    if (thread_.isRunning())
    {
      return true;
    }

    // start the polling thread
    thread_.start();

    return true;
  }

  @Override
  public boolean startMonitor()
  {
    // nothing to do in monitor mode
    return true;
  }

  @Override
  public boolean stopControl()
  {
    // check if it is never running
    if (!thread_.isRunning())
    {
      return true;
    }

    // stop the polling thread
    thread_.stop(100);

    return true;
  }

  @Override
  public boolean stopMonitor()
  {
    // nothing to do in monitor mode. so nothing to stop
    return true;
  }

  /**
   * Perform status and data polling
   *
   * @return the number of segment successfully polled
   */
  protected int poll()
  {
    // TODO: check each polling segment if it is the time for polling it
    long curtime = Calendar.getInstance().getTimeInMillis();
    int counter = 0;
    PollingSegment segment = null;
    for (int i = 0; i < segments_.size(); i++)
    {
      segment = segments_.get(i);
      if (segment == null)
      {
        continue;
      }

      // check if it is already time for polling this segment
      if (segment.nextPollingMillis > curtime)
      {
        continue;
      }

      // try the current active host
      if (activeHost_ == null)
      {
        activeHost_ = primaryHost_;
      }

      // logging context
      NDC.push(segment.name);

      // poll the segment
      if (segment.commandType == EModbusFunctionCode.READ_COIL_STATUS)
      {
        boolean[] arr = null;

        // try the current active host
        try
        {
          arr = activeHost_.readOutputCoils(segment.start,
              segment.size);
        }
        catch (RuntimeException re)
        {
          // verbose
          if (activeHost_ == primaryHost_)
          {
            logger.warn("Can not poll the segment from primary host. "
                    +"Attempting to switch to standby host...");
          }
          else
          {
            logger.warn("Can not poll the segment from standby host. "
                +"Attempting to switch to primary host...");
          }
        }

        // if fails, switch the host and try again
        if (arr == null)
        {
          // switch the host
          if (activeHost_ == primaryHost_)
          {
            activeHost_ = standbyHost_;
          }
          else
          {
            activeHost_ = primaryHost_;
          }
          // try again
          try
          {
            arr = activeHost_.readOutputCoils(segment.start,
                segment.size);
          }
          catch (RuntimeException re)
          {
            // verbose
            if (activeHost_ == primaryHost_)
            {
              logger.warn("STILL can not poll the segment from primary host. "
                      +"Forcing immediate status polling...");
            }
            else
            {
              logger.warn("STILL can not poll the segment from standby host. "
                  +"Forcing immediate status polling...");
            }
          }  //try-catch
        //if (arr == null)

        // if both fails, set the datapoint' source quality to bad
        if (arr == null)
        {
          // set the datapoint' source quality to bad
          // TODO

          // force a status polling
          // TODO
        }
        else
        {
          // update the value
          // TODO

          // successful polling
          counter++;
        }
      }
      else if (segment.commandType == EModbusFunctionCode.READ_INPUT_STATUS)
      {
        boolean[] arr = null;

        // try the current active host
        try
        {
          arr = activeHost_.readInputContacts(segment.start,
              segment.size);
        }
        catch (RuntimeException re)
        {
          // verbose
          if (activeHost_ == primaryHost_)
          {
            logger.warn("Can not poll the segment from primary host. "
                    +"Attempting to switch to standby host...");
          }
          else
          {
            logger.warn("Can not poll the segment from standby host. "
                +"Attempting to switch to primary host...");
          }
        }

        // if fails, switch the host and try again
        if (arr == null)
        {
          // switch the host
          if (activeHost_ == primaryHost_)
          {
            activeHost_ = standbyHost_;
          }
          else
          {
            activeHost_ = primaryHost_;
          }
          // try again
          try
          {
            arr = activeHost_.readInputContacts(segment.start,
                segment.size);
          }
          catch (RuntimeException re)
          {
            // verbose
            if (activeHost_ == primaryHost_)
            {
              logger.warn("STILL can not poll the segment from primary host. "
                      +"Forcing immediate status polling...");
            }
            else
            {
              logger.warn("STILL can not poll the segment from standby host. "
                  +"Forcing immediate status polling...");
            }
          }  //try-catch
        //if (arr == null)

        // if both fails, set the datapoint' source quality to bad
        if (arr == null)
        {
          // set the datapoint' source quality to bad
          // TODO

          // force a status polling
          // TODO
        }
        else
        {
          // update the value
          // TODO

          // successful polling
          counter++;
        }
      }
      else if (segment.commandType == EModbusFunctionCode.READ_HOLDING_REGISTER)
      {
        short[] arr = null;

        // try the current active host
        try
        {
          arr = activeHost_.readHoldingRegisters(segment.start,
              segment.size);
        }
        catch (RuntimeException re)
        {
          // verbose
          if (activeHost_ == primaryHost_)
          {
            logger.warn("Can not poll the segment from primary host. "
                    +"Attempting to switch to standby host...");
          }
          else
          {
            logger.warn("Can not poll the segment from standby host. "
                +"Attempting to switch to primary host...");
          }
        }

        // if fails, switch the host and try again
        if (arr == null)
        {
          // switch the host
          if (activeHost_ == primaryHost_)
          {
            activeHost_ = standbyHost_;
          }
          else
          {
            activeHost_ = primaryHost_;
          }
          // try again
          try
          {
            arr = activeHost_.readHoldingRegisters(segment.start,
                segment.size);
          }
          catch (RuntimeException re)
          {
            // verbose
            if (activeHost_ == primaryHost_)
            {
              logger.warn("STILL can not poll the segment from primary host. "
                      +"Forcing immediate status polling...");
            }
            else
            {
              logger.warn("STILL can not poll the segment from standby host. "
                  +"Forcing immediate status polling...");
            }
          }  //try-catch
        //if (arr == null)

        // if both fails, set the datapoint' source quality to bad
        if (arr == null)
        {
          // set the datapoint' source quality to bad
          // TODO

          // force a status polling
          // TODO
        }
        else
        {
          // update the value
          // TODO

          // successful polling
          counter++;
        }
      }
      else    //default: read input registers
      {
        short[] arr = null;

        // try the current active host
        try
        {
          arr = activeHost_.readInputRegisters(segment.start,
              segment.size);
        }
        catch (RuntimeException re)
        {
          // verbose
          if (activeHost_ == primaryHost_)
          {
            logger.warn("Can not poll the segment from primary host. "
                    +"Attempting to switch to standby host...");
          }
          else
          {
            logger.warn("Can not poll the segment from standby host. "
                +"Attempting to switch to primary host...");
          }
        }

        // if fails, switch the host and try again
        if (arr == null)
        {
          // switch the host
          if (activeHost_ == primaryHost_)
          {
            activeHost_ = standbyHost_;
          }
          else
          {
            activeHost_ = primaryHost_;
          }
          // try again
          try
          {
            arr = activeHost_.readInputRegisters(segment.start,
                segment.size);
          }
          catch (RuntimeException re)
          {
            // verbose
            if (activeHost_ == primaryHost_)
            {
              logger.warn("STILL can not poll the segment from primary host. "
                      +"Forcing immediate status polling...");
            }
            else
            {
              logger.warn("STILL can not poll the segment from standby host. "
                  +"Forcing immediate status polling...");
            }
          }  //try-catch
        //if (arr == null)

        // if both fails, set the datapoint' source quality to bad
        if (arr == null)
        {
          // set the datapoint' source quality to bad
          // TODO

          // force a status polling
          // TODO
        }
        else
        {
          // update the value
          // TODO

          // successful polling
          counter++;
        }
      }

      // logging context
      NDC.pop();
    }

    return 0;
  }

  private void update_values(ArrayList<DataPoint> datapoints,
      boolean[] states, int offset)
  {
    if (datapoints == null || states == null || offset < 0)
    {
      return;
    }

    CosDpValueStruct value = new CosDpValueStruct();
    value.timestamp = 0;
    value.quality = CosDpQualityEnum.QualityGood;

    // update the value
    IDataPoint dp = null;
    boolean boolValue = false;
    for (int i = 0; i < datapoints.size(); i++)
    {
      dp = datapoints.get(i);
      if (dp == null || dp.getSourceType() != ESourceDataType.TYPE_DI)
      {
        continue;
      }

      // TODO: parse DDI and TDI as well

      boolValue = states[dp.getAddress() - offset];
      value.value.boolValue(boolValue);

      // set the dp value
      if (dp.setSourceValue(value) < 0)
      {
        logger.warn("Can not update source value of datapoint "
            + dp.getName());
      }
    }
  }

  private void update_values(ArrayList<DataPoint> datapoints, short[] values,
      int offset)
  {
    if (datapoints == null || values == null || offset < 0)
    {
      return;
    }

    CosDpValueStruct value = new CosDpValueStruct();
    value.timestamp = 0;
    value.quality = CosDpQualityEnum.QualityGood;

    // update the value
    DataPoint dp = null;
    // int dpWordAddress = 0;
    boolean boolValue = false;
    long intValue = 0;
    String strValue = "";
    double dblValue = 0;
    for (int i = 0; i < datapoints.size(); i++)
    {
      dp = datapoints.get(i);
      if (dp == null)
      {
        continue;
      }

      switch (dp.getSourceType())
      {
        case TYPE_DI:
          boolValue = BufferParser.getBooleanValue(values, dp
              .getAddress()
              - offset, dp.getBitAddress());
          value.value.boolValue(boolValue);
          break;
        case TYPE_INT16:
          intValue = BufferParser.getLongValue(values, dp
              .getAddress()
              - offset, 2, false);
          value.value.longValue((int) intValue);
          break;
        case TYPE_INT32:
          intValue = BufferParser.getLongValue(values, dp
              .getAddress()
              - offset, 4, false);
          value.value.longValue((int) intValue);
          break;
        case TYPE_UINT16:
          intValue = BufferParser.getLongValue(values, dp
              .getAddress()
              - offset, 2, true);
          value.value.unsignedValue((int) intValue);
          break;
        case TYPE_UINT32:
          intValue = BufferParser.getLongValue(values, dp
              .getAddress()
              - offset, 4, true);
          value.value.unsignedValue((int) intValue);
          break;
        case TYPE_BCD:
          intValue = BufferParser.getBcdValue(values, dp.getAddress()
              - offset, dp.getLength() / 2);
          value.value.longValue((int) intValue);
          break;
        case TYPE_IEEE16:
          dblValue = BufferParser.getDoubleValue(values, dp
              .getAddress()
              - offset, 2);
          value.value.dblValue(dblValue);
          break;
        case TYPE_IEEE32:
          dblValue = BufferParser.getDoubleValue(values, dp
              .getAddress()
              - offset, 4);
          value.value.dblValue(dblValue);
          break;
        case TYPE_STRING:
          strValue = BufferParser.getStringValue(values, dp
              .getAddress()
              - offset, dp.getLength() / 2);
          value.value.charValue(strValue);
          break;
      }

      // set the dp value
      if (dp.setSourceValue(value) < 0)
      {
        logger.warn("Can not update source value of datapoint "
            + dp.name);
      }
    }
  }

  /**
   * Worker polling thread
   *
   * @author Yoga
   */
  class PollingThread extends DetachedThread
  {
    private ModbusSubsystem subsystem = null;

    PollingThread(ModbusSubsystem inSwc)
    {
      subsystem = inSwc;
      // set the precision explicitly
      precisionMillis = DetachedThread.DEF_PRECISION_MILLIS;
    }

    @Override
    protected void _doWork()
    {
      subsystem.poll();
    }

    @Override
    protected void _initial()
    {
      NDC.push(subsystem.getName());
      logger.info("Poller thread is started.");
    }

    @Override
    protected void _final()
    {
      logger.info("Poller thread has stopped.");
      NDC.pop();
    }

    @Override
    protected void _onStart()
    {
      logger.info("Starting subsystem " + subsystem.getName()
          + " poller thread...");
    }

    @Override
    protected void _onStop()
    {
      logger.info("Stopping subsystem " + subsystem.getName()
          + " poller thread...");
    }

  }
}
TOP

Related Classes of tcg.scada.da.modbus.ModbusSubsystem$PollingThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.