gu.dtalk.engine.BaseDispatcher Maven / Gradle / Ivy
package gu.dtalk.engine;
import static com.google.common.base.Preconditions.*;
import static gu.dtalk.CommonConstant.*;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicates;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import gu.dtalk.Ack;
import gu.dtalk.BaseItem;
import gu.dtalk.BaseOption;
import gu.dtalk.CmdItem;
import gu.dtalk.CommonConstant.ReqCmdType;
import gu.dtalk.DeviceInstruction;
import gu.simplemq.Channel;
import gu.simplemq.IMessageAdapter;
import gu.simplemq.IPublisher;
/**
* 设备命令分发器,实现{@link IMessageAdapter}接口,将消息队列操作与业务逻辑隔离
* 从设备命令频道或任务队列得到设备指令{@link DeviceInstruction},并将交给{@link ItemAdapter}执行
* 收到的设备命令将按收到命令的顺序在线程池中顺序执行
* @author guyadong
*
*/
public abstract class BaseDispatcher implements IMessageAdapter{
private static final Logger logger = LoggerFactory.getLogger(BaseDispatcher.class);
private static final Supplier NULL_SUPPLIER = Suppliers.ofInstance(null);
protected final int deviceId;
/** 命令请求类型 */
protected final ReqCmdType reqType;
private final IPublisher publisher;
/** 是否自动注销标志 */
private final AtomicBoolean autoUnregisterCmdChannel = new AtomicBoolean(false);
/** 设备命令序列号验证器 */
protected Predicate cmdSnValidator = Predicates.alwaysTrue();
private ItemAdapter itemAdapter ;
/**
* 当前设备的MAC地址(HEX字符串)
*/
private String selfMac;
private Supplier channelSupplier = NULL_SUPPLIER;
private boolean enable = true;
private volatile Channel channel;
/**
* 构造方法
* @param deviceId 当前设备ID,应用项目应确保ID是有效的
* @param reqType 设备命令请求类型
* @param publisher 消息发布实例
*/
protected BaseDispatcher(int deviceId, ReqCmdType reqType, IPublisher publisher) {
checkArgument(reqType == ReqCmdType.MULTI || reqType == ReqCmdType.TASKQUEUE,
"INVALID reqType,required %s or %s",ReqCmdType.MULTI,ReqCmdType.TASKQUEUE);
this.deviceId= deviceId;
this.reqType = reqType;
this.publisher = checkNotNull(publisher,"publisher is null");
}
/**
* @param deviceInstruction
* @return
*/
private JSONObject makeItemJSON(DeviceInstruction deviceInstruction){
String path = deviceInstruction.getCmdpath();
checkArgument(!Strings.isNullOrEmpty(path ),"path of cmd is null or empty");
JSONObject json = new JSONObject();
BaseItem item = getItemAdapterChecked().getRoot().findChecked(path);
json.fluentPut(ITEM_FIELD_PATH,path)
.fluentPut(REQ_FIELD_CMDSN,deviceInstruction.getCmdSn())
.fluentPut(REQ_FIELD_ACKCHANNEL, deviceInstruction.getAckChannel())
.fluentPut(REQ_FIELD_REQTYPE, reqType);
Map parameters = deviceInstruction.getParameters();
if(parameters != null){
// 填入设备命令参数根据
if(item instanceof BaseOption>){
Object value = parameters.get(OPTION_FIELD_VALUE);
if(value != null){
json.put(OPTION_FIELD_VALUE, value);
}
}else if(item instanceof CmdItem){
json.put(REQ_FIELD_PARAMETERS, parameters);
}
}
json.put(REQ_FIELD_ACKCHANNEL, deviceInstruction.getAckChannel());
return json;
}
/**
* 执行指定的设备命令并向命令响应频道返回命令结果
*/
@Override
public void onSubscribe(DeviceInstruction deviceInstruction) {
try {
if(validate(deviceInstruction)){
JSONObject itemJson = makeItemJSON(deviceInstruction);
getItemAdapterChecked().onSubscribe(itemJson);
}
} catch (Throwable e) {
// 捕获所有异常发到ack响应频道
logger.error(e.getMessage());
Ack
© 2015 - 2025 Weber Informatics LLC | Privacy Policy