Created
July 15, 2016 07:54
-
-
Save earlwlkr/8af91045d7245aa85a40168df0c704f1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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