Skip to content

Instantly share code, notes, and snippets.

@earlwlkr
Created July 15, 2016 07:54
Show Gist options
  • Save earlwlkr/8af91045d7245aa85a40168df0c704f1 to your computer and use it in GitHub Desktop.
Save earlwlkr/8af91045d7245aa85a40168df0c704f1 to your computer and use it in GitHub Desktop.
package com.imt.streetlight.observer.modbus;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import com.imt.streetlight.common.userlog.UserLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.imt.streetlight.common.bizlogic.service.DpsService;
import com.imt.streetlight.common.bizlogic.service.FailureService;
import com.imt.streetlight.common.dto.DpsDto;
import com.imt.streetlight.common.enums.ConnectionProcessStatus;
import com.imt.streetlight.common.enums.FailureTypeEnum;
import com.imt.streetlight.common.enums.LightStatusEnum;
import com.imt.streetlight.common.enums.MLCStatusEnum;
import com.imt.streetlight.common.utils.CommonUtils;
import com.imt.streetlight.observer.modbus.mlc.DPSChangeStatusReportEvent;
import com.imt.streetlight.observer.modbus.mlc.DPSLossCommunicationEvent;
import com.imt.streetlight.observer.modbus.mlc.DPSPollEvent;
import com.imt.streetlight.observer.modbus.mlc.DPSRegistrationEvent;
import com.imt.streetlight.observer.modbus.mlc.GroupDimmingEvent;
import com.imt.streetlight.observer.modbus.mlc.MLCDigitalInputReportEvent;
import com.imt.streetlight.observer.modbus.mlc.MLCRegistrationReportEvent;
import com.imt.streetlight.observer.modbus.request.MLCRequest;
import com.imt.streetlight.observer.modbus.request.MLCResponse;
/**
* process income message
*
* @author khangtc
*
*/
public class HandleRequestThread implements Runnable {
/**
* Logging property.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(HandleRequestThread.class);
private static final UserLog userLog = new UserLog();
/**
* If thread stop
*/
private boolean run = true;
/**
* Modbus connection attached to
*/
private ModbusConnection connection;
/**
* Default constructor
* @param connection
* @param inFromClient
*/
public HandleRequestThread(ModbusConnection connection) {
this.connection = connection;
}
/**
*
* @param mlcRequest
*/
private void processMLCRegistrationReportEvent(MLCRequest mlcRequest){
LOGGER.debug("Process MLCRequest is MLCRegistrationReportEvent");
MLCRegistrationReportEvent registrationReportEvent = (MLCRegistrationReportEvent) mlcRequest.getMlcRequestInfo();
long mlcId = registrationReportEvent.getMlcId();
if (mlcId != 0)
{
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.setMlcRegisteredId(mlcId);
this.connection.setConnectionRegistered(true);
this.connection.getPendingMLCResponse().add(mlcResponse);
LOGGER.debug(
"Add MLCRegistrationReportEvent response success take action: {}",
this.connection.getOnSuccessfulMLCRegister());
if(this.connection.getOnSuccessfulMLCRegister() != null) {
Timestamp lastEvent = new Timestamp(registrationReportEvent.getLastEvent().getTime());
Timestamp lastReboot = new Timestamp(registrationReportEvent.getLastReboot().getTime());
this.connection.getOnSuccessfulMLCRegister().takeAction(lastReboot);
// update alarm_mlc_regitration table
this.connection.getOnCheckConnectionSuccessAction().takeAction(mlcId, lastEvent, lastReboot);
}
}
}
/**
*
*
*/
private void processDPSRegistrationEvent(MLCRequest mlcRequest)
{
LOGGER.debug("MLCRequest is DPSRegistrationEvent");
if (this.connection.isConnectionRegistered() &&
this.connection.getStatus() != ConnectionProcessStatus.INIT)
{
if (this.connection.getMlcStatus() != MLCStatusEnum.BOOTING)
{
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
DPSRegistrationEvent dpsRegistrationEvent =
(DPSRegistrationEvent) mlcRequest.getMlcRequestInfo();
long dpsDeviceId = dpsRegistrationEvent.getDpsDeviceId();
if ((dpsDeviceId != 0) &&
this.connection.isValidLimitNumberOfDPSs(dpsDeviceId))
{
DpsService dpsService =
SlaveController.getApplicationContext().
getBean(DpsService.class);
DpsDto dpsDto = dpsService.getDpsByDeviceId(dpsDeviceId);
// Move update process from serialize to process business.
mlcRequest.getMlcRequestInfo().processUpdateDatabase();
this.connection.getOnSuccessfulBootHoldingRegister().
assignModbusIdForDpsRegister(dpsDeviceId);
if (dpsDto != null)
{
dpsDto.setStatus(LightStatusEnum.UNKNOWN_STATE);
dpsService.updateDps(dpsDto);
}
// Get latest DPS dto object add to memory.
this.connection.getOnDpsRegistrationEventAction().
takeAction(dpsDeviceId);
} else
{
LOGGER.info(
"Reject Dps device {} by id and limit dps number trigger.",
dpsDeviceId);
}
MLCResponse mlcResponse =
MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
// Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if (this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else
{
LOGGER.warn("The connection did not register.");
}
}
/**Loss communication process
*
* @param mlcRequest
*/
private void processDPSLossCommunicationEvent(MLCRequest mlcRequest){
LOGGER.debug("MLCRequest is LossCommunicationEvent");
if(this.connection.isConnectionRegistered() && this.connection.getStatus() != ConnectionProcessStatus.INIT) {
if(this.connection.getMlcStatus() != MLCStatusEnum.BOOTING){
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
DPSLossCommunicationEvent dpsRegistrationEvent = (DPSLossCommunicationEvent) mlcRequest.getMlcRequestInfo();
long dpsId = dpsRegistrationEvent.getDpsId();
this.connection.getOnDpsCommunicationLossEventAction().takeAction(dpsId);
//Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if(this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else {
LOGGER.warn("The connection did not register.");
}
}
private void processMLCDigitalInputReportEvent(MLCRequest mlcRequest)
{
LOGGER.debug("MLCRequest is MLCDigitalInputReportEvent");
if(this.connection.isConnectionRegistered() && this.connection.getStatus() != ConnectionProcessStatus.INIT) {
if(this.connection.getMlcStatus() != MLCStatusEnum.BOOTING){
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
MLCDigitalInputReportEvent mlcDigitalInputReportEvent = (MLCDigitalInputReportEvent) mlcRequest.getMlcRequestInfo();
long mlcId = mlcDigitalInputReportEvent.getMlcId();
String digitalInput = mlcDigitalInputReportEvent.getDigitalInput();
this.connection.getOnMLCDigitalInputReportEventAction().takeAction(mlcId, digitalInput);
// Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if(this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else {
LOGGER.warn("The connection did not register.");
}
}
/**
* getLightStatusAndUpdateFailure
* - If DPS gets Comm loss or not registered: the status should be showed Offline.
- If DPS already registered but don’t know the status, the status should be showed Unknown State
- If status bits are a fault (Open-Loop, Short-Circuit and Start-Up Failure), the status should be showed Error and the fault, example: Error (OL) or Error (OL, SC, SF), v.v. .
- If status bits are a fault (Over Temperature, Under Temperature, Over Power, Over Voltage and Under Voltage), the status should be showed Warning and the fault, example: Warning (OT) or Warning (OT, OP), v.v.. .
- If status bits are normal:
If dimming level is 0%: the status should be showed in Off
If dimming level is from 1% to 99%: the status should be showed in Dimming - Please change this to “Dimmed”
If dimming level is 100%: the status should be showed in On
* @param dpsId
* @param dimming
* @param statusRawData
* @return
*/
private LightStatusEnum getLightStatusAndUpdateFailure(Long dpsId, int dimming, int statusRawData){
FailureService failureservice = SlaveController.getApplicationContext().getBean(FailureService.class);
LightStatusEnum status = null;
int value = 0;
List<FailureTypeEnum> errorList = new ArrayList<FailureTypeEnum>();
List<FailureTypeEnum> warningList = new ArrayList<FailureTypeEnum>();
DpsService dpsService =
SlaveController.getApplicationContext().
getBean(DpsService.class);
DpsDto dpsDto = dpsService.getDpsById(dpsId);
for (int type = 0; type < 8; type++) {
value = (1 & (statusRawData >> type));
// check dpsId => update DB
if(dpsId != null){
failureservice.updateDataBase(dpsId, 8 - type, value);
}
if (value == 1 && ((8 - type) == FailureTypeEnum.OPEN_LOOP.getValue()
|| (8 - type) == FailureTypeEnum.SHORT_CIRCUIT.getValue()
|| (8 - type) == FailureTypeEnum.START_UP_FAILURE.getValue())){
status = LightStatusEnum.ERROR;
errorList.add(FailureTypeEnum.values()[8 - type]);
}
if(value == 1 && status != LightStatusEnum.ERROR
&& ((8 - type) == FailureTypeEnum.UNDER_VOLTAGE.getValue()
|| (8 - type) == FailureTypeEnum.OVER_VOLTAGE.getValue()
|| (8 - type) == FailureTypeEnum.OVER_POWER.getValue()
|| (8 - type) == FailureTypeEnum.UNDER_TEMPERATURE.getValue()
|| (8 - type) == FailureTypeEnum.OVER_TEMPERATURE.getValue())){
status = LightStatusEnum.WARNING;
warningList.add(FailureTypeEnum.values()[8 - type]);
}
}
if (status != LightStatusEnum.ERROR && status != LightStatusEnum.WARNING){
status = CommonUtils.convertDimmingLevelToLightStatus(dimming);
} else if (status == LightStatusEnum.ERROR) {
// USERLOGGER - Error Conditions of DPS due to Open Loop, Short Circuit or Start-up Failure. (12)
StringBuilder builder = new StringBuilder();
for (FailureTypeEnum errorValue: errorList) {
builder.append(' ');
builder.append(errorValue.toString());
builder.append(',');
}
int seperatorIndex = builder.lastIndexOf(",");
if (seperatorIndex != -1) {
builder.delete(seperatorIndex, seperatorIndex + 1);
}
builder.delete(builder.lastIndexOf(","), 1);
userLog.log(userLog.getMessage(UserLog.DPS_ERROR_MESSAGE_FORMAT), dpsDto.getDpsName(), builder.toString(), dpsDto.getMlcId(), dpsId);
} else if (status == LightStatusEnum.WARNING) {
// USERLOGGER - Warning Conditions of DPS due to Over Temperature, Under Temperature, Over Power, Over Voltage or Under Voltage. (13)
StringBuilder builder = new StringBuilder();
for (FailureTypeEnum warningValue: warningList) {
builder.append(' ');
builder.append(warningValue.toString());
builder.append(',');
}
int seperatorIndex = builder.lastIndexOf(",");
if (seperatorIndex != -1) {
builder.delete(seperatorIndex, seperatorIndex + 1);
}
userLog.log(userLog.getMessage(UserLog.DPS_WARNING_MESSAGE_FORMAT), dpsDto.getDpsName(), builder.toString(), dpsDto.getMlcId(), dpsId);
}
return status;
}
/**
*
* @param mlcRequest
*/
private void processDPSChangeStatusReportEvent(MLCRequest mlcRequest)
{
LOGGER.debug("MLCRequest is DPSChangeStatusReportEvent");
if(this.connection.isConnectionRegistered() && this.connection.getStatus() != ConnectionProcessStatus.INIT) {
if(this.connection.getMlcStatus() != MLCStatusEnum.BOOTING){
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
DPSChangeStatusReportEvent dpsChangeStatusReportEvent = (DPSChangeStatusReportEvent) mlcRequest.getMlcRequestInfo();
long dpsDeviceId = dpsChangeStatusReportEvent.getDpsDeviceId();
boolean mode = dpsChangeStatusReportEvent.isManualMode();
int dimming = dpsChangeStatusReportEvent.getDimmingLevel();
int dpsStatusRawData = dpsChangeStatusReportEvent.getStatusRawData();
DpsService dpsService = SlaveController.getApplicationContext().getBean(DpsService.class);
DpsDto dpsDto = dpsService.getDpsByDeviceId(dpsDeviceId);
if(dpsDto != null){
LightStatusEnum status = getLightStatusAndUpdateFailure(dpsDto.getId(), dimming, dpsStatusRawData);
dpsDto.setStatus(status);
dpsDto.setDimmingLevel(dimming);
dpsDto.setMode(mode);
//update DB
dpsService.updateDps(dpsDto);
if(dimming == 0){
//Update Device Life Time (stop time).
dpsService.updateStopTime(dpsDeviceId);
}
else{
//Insert a new Device Life Time (start time).
dpsService.insertNewDeviceLifeTimeRecord(dpsDeviceId);
}
//update memory
this.connection.getOnDPSChangeStatusReportEventAction().takeAction(dpsDto);
}
//Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if(this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else {
LOGGER.warn("The connection did not register.");
}
}
/**
*
* @param mlcRequest
*/
private void processGroupDimmingEvent(MLCRequest mlcRequest)
{
LOGGER.debug("MLCRequest is GroupDimmingEvent");
if(this.connection.isConnectionRegistered() && this.connection.getStatus() != ConnectionProcessStatus.INIT) {
if(this.connection.getMlcStatus() != MLCStatusEnum.BOOTING){
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
GroupDimmingEvent groupDimmingEvent = (GroupDimmingEvent) mlcRequest.getMlcRequestInfo();
long mclId = groupDimmingEvent.getMlcId();
int group = groupDimmingEvent.getGroup();
int dimmingLevel = groupDimmingEvent.getDimmingLevel();
this.connection.getOnGroupDimmingEventAction().takeAction(mclId, group, dimmingLevel);
//Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if(this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else {
LOGGER.warn("The connection did not register.");
}
}
/**
*
* @param mlcRequest
*/
private void processDPSPollEvent(MLCRequest mlcRequest)
{
LOGGER.debug("MLCRequest is DPSPollEvent");
if(this.connection.isConnectionRegistered() && this.connection.getStatus() != ConnectionProcessStatus.INIT) {
if(this.connection.getMlcStatus() != MLCStatusEnum.BOOTING){
this.connection.setMlcStatus(MLCStatusEnum.PROCESS_EVENT);
}
MLCResponse mlcResponse = MLCModbusRequestFactory.compileMlcEventResponse(mlcRequest);
this.connection.getPendingMLCResponse().add(mlcResponse);
DPSPollEvent dpsPollEvent = (DPSPollEvent) mlcRequest.getMlcRequestInfo();
DpsService dpsService = SlaveController.getApplicationContext().getBean(DpsService.class);
DpsDto dpsDto = dpsService.getDpsByDeviceId(dpsPollEvent.getDpsDeviceId());
if(dpsDto != null){
// parse status of light
LightStatusEnum status = this.getLightStatusAndUpdateFailure(dpsDto.getId(), dpsPollEvent.getDimmingLevel(), dpsPollEvent.getStatusRawData());
dpsPollEvent.setStatus(status);
// Update database
mlcRequest.getMlcRequestInfo().processUpdateDatabase();
this.connection.getOnDpsPollEventAction().takeAction(dpsPollEvent.getDpsDeviceId());
}
//Or Observer had finished processing event from MLC.
// MLC has ready received new request from user.
if(this.connection.getMlcStatus() == MLCStatusEnum.PROCESS_EVENT)
{
this.connection.setMlcStatus(MLCStatusEnum.READY);
}
} else {
LOGGER.warn("The connection did not register.");
}
}
/**
* MLC is master, Observer is slave. Receive request from MLC.
*
* @param rawData
*/
private void receiveMLCRequest(byte[] rawData) {
//LOGGER.debug("receiveMLCRequest before process ");
MLCRequest mlcRequest = new MLCRequest(rawData);
if(mlcRequest.getMlcRequestInfo() != null){
LOGGER.debug("Received MLCRequest: {}", mlcRequest);
if(mlcRequest.getMlcRequestInfo() instanceof MLCRegistrationReportEvent)
{
processMLCRegistrationReportEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof DPSRegistrationEvent)
{
processDPSRegistrationEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof DPSLossCommunicationEvent)
{
processDPSLossCommunicationEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof MLCDigitalInputReportEvent)
{
processMLCDigitalInputReportEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof DPSChangeStatusReportEvent)
{
processDPSChangeStatusReportEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof GroupDimmingEvent)
{
processGroupDimmingEvent(mlcRequest);
}
else if(mlcRequest.getMlcRequestInfo() instanceof DPSPollEvent)
{
processDPSPollEvent(mlcRequest);
}
else
{
/**
* We will implement on another day.
*/
LOGGER.warn("This MLC request is not handle yet.");
}
}
}
/**
* Threading active
*/
public void setRun(boolean value){
this.run = true;
}
public void run() {
LOGGER.debug("Start receive data.");
while (run)
{
try
{
Thread.sleep(20);
//LOGGER.debug("before IF ");
// LOGGER.debug("list MLC request byte data : {}" , this.connection.getListMLCRequestByte().size());
if(this.connection.getListMLCRequestByte() !=null && !this.connection.getListMLCRequestByte().isEmpty()){
//LOGGER.debug("before get request");
byte [] rawData = this.connection.getListMLCRequestByte().poll();
receiveMLCRequest(rawData);
}
}catch(Exception ex){
LOGGER.error( "error :" + ex);
}
}
LOGGER.debug("End receive data.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment