package com.xinda.zqwl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xinda.common.annotation.SysProtocol;
import com.xinda.common.constant.XinDaConstant;
import com.xinda.common.core.mq.DeviceReport;
import com.xinda.common.core.mq.MQSendMessageBo;
import com.xinda.common.core.mq.message.DeviceData;
import com.xinda.common.core.mq.message.FunctionCallBackBo;
import com.xinda.common.core.redis.RedisCache;
import com.xinda.common.core.redis.RedisKeyBuilder;
import com.xinda.common.core.thingsModel.ThingsModelSimpleItem;
import com.xinda.common.core.thingsModel.ThingsModelValuesInput;
import com.xinda.common.exception.ServiceException;
import com.xinda.common.utils.DateUtils;
import com.xinda.common.utils.gateway.mq.TopicsUtils;
import com.xinda.iot.model.ThingsModels.ThingsModelValueItem;
import com.xinda.iot.service.IDeviceService;
import com.xinda.protocol.base.protocol.IProtocol;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author gsb
* @date 2023/8/14 16:04
*/
@Slf4j
@Component
@SysProtocol(name = "8路继电器+Modbus转Json-智嵌物联",protocolCode = XinDaConstant.PROTOCOL.ModbusToJsonZQWL,description = "8路继电器+Modbus转Json-智嵌物联")
public class ModbusToJsonZQWLProtocolService implements IProtocol {
@Resource
private RedisCache redisCache;
@Resource
private TopicsUtils topicsUtils;
@Resource
private IDeviceService deviceService;
/**
* 上报数据格式:
* device1: 从机1标识
* name: 物模型标识符
* value: 上报值
* {
* "device1": [
* {
* "name": "J2",
* "value": 8.331631
* },
* {
* "name": "J1",
* "value": -130.123718
* }
* ],
* "device2": [
* {
* "name": "J4",
* "value": -16.350224
* },
* {
* "name": "J3",
* "value": 94.769806
* }
* ]
* }
*
* 下发报文格式
* device 从机编号
* name 标识符
* value 值
* serNo 流水号
* {
* "device": 1,
* "name": "template",
* "value": 111,
* "serNo": "213245489543789"
* }
*
*
* 下发指令回复格式
* serNo 平台的流水号,用于对应回复消息
* ack 下发指令状态 0是失败 1是成功
* {
* "serNo": "213245489543789",
* "ack": 1
* }
*
*
*/
@Override
public DeviceReport decode(DeviceData deviceData, String clientId) {
try {
DeviceReport reportMessage = new DeviceReport();
String data = new String(deviceData.getData(),StandardCharsets.UTF_8);
List result = new ArrayList<>();
Map values = JSON.parseObject(data, Map.class);
if (values.containsKey("addr") || (values.containsKey("cmd") && values.get("cmd").equals("ret"))){
for (Map.Entry entry : values.entrySet()) {
if (entry.getKey().equals("x")){
JSONArray value = (JSONArray) entry.getValue();
for (int i = 0; i < value.size(); i++) {
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
simpleItem.setTs(DateUtils.getNowDate());
simpleItem.setId(entry.getKey()+(i+1));
simpleItem.setValue(value.get(i)+"");
result.add(simpleItem);
}
}
if (entry.getKey().equals("y")){
JSONArray value = (JSONArray) entry.getValue();
for (int i = 0; i < value.size(); i++) {
ThingsModelSimpleItem simpleItem = new ThingsModelSimpleItem();
simpleItem.setTs(DateUtils.getNowDate());
simpleItem.setId(entry.getKey()+ (i+1));
simpleItem.setValue(value.get(i)+"");
result.add(simpleItem);
}
}
}
}else {
for (Map.Entry entry : values.entrySet()) {
String key = entry.getKey();
if (key.contains("-")) {
String slaveKey = key.split("-")[0];
Integer slaveId = Integer.parseInt(slaveKey);
ThingsModelSimpleItem item = new ThingsModelSimpleItem();
item.setTs(DateUtils.getNowDate());
item.setValue(entry.getValue() + "");
item.setId(key);
//item.setSlaveId(slaveId);
result.add(item);
}
}
}
reportMessage.setThingsModelSimpleItem(result);
reportMessage.setClientId(clientId);
reportMessage.setSerialNumber(clientId);
return reportMessage;
}catch (Exception e){
throw new ServiceException("数据解析异常"+e.getMessage());
}
}
@Override
public FunctionCallBackBo encode(MQSendMessageBo message) {
try {
FunctionCallBackBo callBack = new FunctionCallBackBo();
Long productId = message.getDp().getProductId();
String messageValue = message.getValue();
JSONObject params = new JSONObject();
params.put("addr",1);
params.put("cmd","set");
String identifier = message.getIdentifier();
int idIndex = Integer.parseInt(identifier.substring(1, 2));
int value = Integer.parseInt(messageValue);
int[] ints = new int[8];
List cacheValueList = getCacheDeviceStatus(productId, message.getSerialNumber());
if (identifier.contains("x")){
for (ThingsModelValueItem valueItem : cacheValueList) {
if (valueItem.getId().contains("x")){
int itemIndex = Integer.parseInt(valueItem.getId().substring(1, 2));
ints[itemIndex-1] = Integer.parseInt(valueItem.getValue());
}
}
ints[idIndex-1] = value;
params.put("x",ints);
}else if (identifier.contains("y")){
for (ThingsModelValueItem valueItem : cacheValueList) {
if (valueItem.getId().contains("y")){
int itemIndex = Integer.parseInt(valueItem.getId().substring(1, 2));
ints[itemIndex-1] = Integer.parseInt(valueItem.getValue());
}
}
ints[idIndex-1] = value;
params.put("y",ints);
}
String msg = JSONObject.toJSONString(params);
callBack.setSources(msg);
callBack.setMessage(msg.getBytes());
return callBack;
}catch (Exception e){
log.error("=>指令编码异常,device={}",message.getSerialNumber());
throw new ServiceException(e.getMessage());
}
}
private List getCacheDeviceStatus(Long productId, String deviceNumber) {
String key = RedisKeyBuilder.buildTSLVCacheKey(productId, deviceNumber);
Map map = redisCache.hashEntity(key);
List valueList = new ArrayList<>();
if (map != null && map.size() >0){
// 获取redis缓存的物模型值
valueList = map.values().stream().map(s -> JSONObject.parseObject(s, ThingsModelValueItem.class))
.collect(Collectors.toList());
}
return valueList;
}
}