feat(B8-B9): 屏端物模型回流 + 设备级 schema 覆盖层(消除死数据)
问题: device.schema_json 是中控屏上报物模型的唯一落点, 但全仓只写不读, 属死数据; 同时屏端本地设备(zigbee/ble/matter)无平台产品, 产品级物模型里 也查不到东西, 导致这类设备拿不到 control-schema。 新增 PanelSpecAdoptService: - 归一化: 屏端通用协议类型(BOOLEAN/INTEGER/NUMBER/ENUM/STRING) -> 产品物模型类型(bool/int/float/enum/string); access(READ/WRITE/READ_WRITE) -> (read/write/read,write) - 回流: 已存在的属性只补齐/修正屏端明确提供的字段(不做破坏性覆盖), 不存在的补建; 产品级已有而屏端未报的属性保留(产品级是超集) - 语义: 屏端已上报 semantic/channel 直接落库, 缺失时由 SpecSemanticResolver 兜底推导 - toProperties(): 供无产品设备直接以设备级 schema 作为模型来源 PanelDeviceService: register / updateSchema 均触发回流 ControlSchemaServiceImpl.getDeviceSchema 改造: - 无 product_id 的设备: 用设备级 schema 构建控制模型(不再直接返回空) - 有 product_id: 产品基线 + 设备级覆盖层 merge 同 code 以设备级为准, 设备级独有的 code 追加 - 新增 mergeItem(): 仅覆盖屏端明确提供的字段 验证: mvn -pl iot-common,iot-device -am compile 通过
This commit is contained in:
parent
a8c2d005a8
commit
fdf0e265fc
@ -9,6 +9,7 @@ import com.iot.device.entity.Device;
|
||||
import com.iot.device.entity.PanelTerminal;
|
||||
import com.iot.device.mapper.DeviceMapper;
|
||||
import com.iot.device.mapper.PanelTerminalMapper;
|
||||
import com.iot.device.service.spec.PanelSpecAdoptService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -28,6 +29,7 @@ public class PanelDeviceService {
|
||||
|
||||
private final DeviceMapper deviceMapper;
|
||||
private final PanelTerminalMapper panelTerminalMapper;
|
||||
private final PanelSpecAdoptService panelSpecAdoptService;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@ -76,6 +78,12 @@ public class PanelDeviceService {
|
||||
}
|
||||
deviceMapper.insert(device);
|
||||
|
||||
// 屏端物模型回流到产品物模型:否则 device.schema_json 只是无人读取的死数据,
|
||||
// 且屏端本地设备(zigbee/ble/matter)没有平台产品也拿不到 control-schema。
|
||||
if (registration.getProductId() != null) {
|
||||
panelSpecAdoptService.adopt(registration.getProductId(), registration.getSchema());
|
||||
}
|
||||
|
||||
log.info("本地设备登记成功: panelId={}, localDeviceId={}, deviceId={}",
|
||||
panelId, registration.getLocalDeviceId(), device.getDeviceId());
|
||||
return toResult(device, 1);
|
||||
@ -103,6 +111,11 @@ public class PanelDeviceService {
|
||||
device.setSchemaJson(toJson(request.getSchema()));
|
||||
deviceMapper.updateById(device);
|
||||
|
||||
// 物模型更新后同步回流到产品物模型
|
||||
if (device.getProductId() != null) {
|
||||
panelSpecAdoptService.adopt(device.getProductId(), request.getSchema());
|
||||
}
|
||||
|
||||
PanelDeviceDto.SchemaUpdateResult result = new PanelDeviceDto.SchemaUpdateResult();
|
||||
result.setDeviceId(device.getDeviceId());
|
||||
result.setSchemaRevision(revision);
|
||||
|
||||
@ -16,7 +16,9 @@ import com.iot.device.mapper.ProductActionMapper;
|
||||
import com.iot.device.mapper.ProductEventMapper;
|
||||
import com.iot.device.mapper.ProductMapper;
|
||||
import com.iot.device.mapper.ProductPropertyMapper;
|
||||
import com.iot.device.dto.PanelDeviceDto;
|
||||
import com.iot.device.service.ControlSchemaService;
|
||||
import com.iot.device.service.spec.PanelSpecAdoptService;
|
||||
import com.iot.device.service.spec.SpecSemanticResolver;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -24,6 +26,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -45,6 +48,7 @@ public class ControlSchemaServiceImpl implements ControlSchemaService {
|
||||
private final DeviceMapper deviceMapper;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final SpecSemanticResolver semanticResolver;
|
||||
private final PanelSpecAdoptService panelSpecAdoptService;
|
||||
|
||||
@Override
|
||||
public ControlSchema getProductSchema(Long productId) {
|
||||
@ -89,10 +93,18 @@ public class ControlSchemaServiceImpl implements ControlSchemaService {
|
||||
empty.setAvailable(false);
|
||||
Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getDeviceId, deviceId));
|
||||
if (device == null || device.getProductId() == null) {
|
||||
if (device == null) {
|
||||
return empty;
|
||||
}
|
||||
ControlSchema schema = getProductSchema(device.getProductId());
|
||||
ControlSchema schema;
|
||||
if (device.getProductId() != null) {
|
||||
schema = getProductSchema(device.getProductId());
|
||||
} else {
|
||||
// 无产品归属的设备(如中控屏本地设备)→ 用设备级 schema 兜底
|
||||
schema = buildFromDeviceSchema(device);
|
||||
}
|
||||
// 设备级覆盖层 merge:产品基线之外,本设备特有的属性由 device.schema_json 承载
|
||||
schema = mergeDeviceOverrides(schema, device);
|
||||
if (!schema.isAvailable()) {
|
||||
return schema;
|
||||
}
|
||||
@ -107,6 +119,143 @@ public class ControlSchemaServiceImpl implements ControlSchemaService {
|
||||
return schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无产品归属设备:直接以设备级 schema 构建控制模型。
|
||||
*/
|
||||
private ControlSchema buildFromDeviceSchema(Device device) {
|
||||
ControlSchema schema = new ControlSchema();
|
||||
schema.setProductId(null);
|
||||
schema.setPlatform(device.getPlatform());
|
||||
schema.setSchemaRevision(device.getSchemaRevision());
|
||||
PanelDeviceDto.DeviceSchema ds = parseDeviceSchema(device.getSchemaJson());
|
||||
if (ds == null) {
|
||||
schema.setAvailable(false);
|
||||
return schema;
|
||||
}
|
||||
List<ControlItem> writable = new ArrayList<>();
|
||||
List<ControlItem> readOnly = new ArrayList<>();
|
||||
for (ProductProperty p : panelSpecAdoptService.toProperties(ds)) {
|
||||
ControlItem item = toItem(p);
|
||||
if (item.isWritable()) {
|
||||
writable.add(item);
|
||||
} else {
|
||||
readOnly.add(item);
|
||||
}
|
||||
}
|
||||
schema.setItems(writable);
|
||||
schema.setReadOnly(readOnly);
|
||||
schema.setMainSwitchCode(pickMainSwitch(writable));
|
||||
schema.setAvailable(!writable.isEmpty() || !readOnly.isEmpty());
|
||||
return schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备级覆盖层 merge。
|
||||
*
|
||||
* <p>产品基线是权威超集;设备级 schema_json 只补充/覆盖该设备特有的属性:
|
||||
* 同 code 的属性以设备级为准(屏端更贴近该设备实际能力),设备级独有的 code 追加。</p>
|
||||
*/
|
||||
private ControlSchema mergeDeviceOverrides(ControlSchema schema, Device device) {
|
||||
if (device.getSchemaJson() == null || device.getSchemaJson().isBlank()) {
|
||||
return schema;
|
||||
}
|
||||
PanelDeviceDto.DeviceSchema ds = parseDeviceSchema(device.getSchemaJson());
|
||||
if (ds == null) {
|
||||
return schema;
|
||||
}
|
||||
List<ControlItem> writable = schema.getItems() == null ? new ArrayList<>() : new ArrayList<>(schema.getItems());
|
||||
List<ControlItem> readOnly = schema.getReadOnly() == null ? new ArrayList<>() : new ArrayList<>(schema.getReadOnly());
|
||||
Map<String, ControlItem> byCode = new HashMap<>();
|
||||
for (ControlItem i : writable) {
|
||||
byCode.put(i.getCode(), i);
|
||||
}
|
||||
for (ControlItem i : readOnly) {
|
||||
byCode.put(i.getCode(), i);
|
||||
}
|
||||
for (ProductProperty p : panelSpecAdoptService.toProperties(ds)) {
|
||||
ControlItem cur = byCode.get(p.getCode());
|
||||
if (cur == null) {
|
||||
ControlItem item = toItem(p);
|
||||
if (item.isWritable()) {
|
||||
writable.add(item);
|
||||
} else {
|
||||
readOnly.add(item);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 设备级覆盖:仅覆盖屏端明确提供的字段
|
||||
ControlItem upd = new ControlItem();
|
||||
upd.setCode(cur.getCode());
|
||||
boolean changed = false;
|
||||
if (StringUtils.hasText(p.getName()) && !p.getName().equals(cur.getName())) {
|
||||
upd.setName(p.getName());
|
||||
changed = true;
|
||||
}
|
||||
if (StringUtils.hasText(p.getSemantic()) && !p.getSemantic().equals(cur.getSemantic())) {
|
||||
upd.setSemantic(p.getSemantic());
|
||||
changed = true;
|
||||
}
|
||||
if (StringUtils.hasText(p.getGrp()) && !p.getGrp().equals(cur.getGrp())) {
|
||||
upd.setGrp(p.getGrp());
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
ControlItem merged = mergeItem(cur, upd);
|
||||
if (merged.isWritable()) {
|
||||
writable.remove(cur);
|
||||
writable.add(merged);
|
||||
} else {
|
||||
readOnly.remove(cur);
|
||||
readOnly.add(merged);
|
||||
}
|
||||
byCode.put(merged.getCode(), merged);
|
||||
}
|
||||
}
|
||||
schema.setItems(writable);
|
||||
schema.setReadOnly(readOnly);
|
||||
schema.setMainSwitchCode(pickMainSwitch(writable));
|
||||
schema.setAvailable(!writable.isEmpty() || !readOnly.isEmpty()
|
||||
|| (schema.getActions() != null && !schema.getActions().isEmpty()));
|
||||
return schema;
|
||||
}
|
||||
|
||||
/** 把覆盖字段合并到基线项上(null 表示不覆盖)。 */
|
||||
private ControlItem mergeItem(ControlItem base, ControlItem over) {
|
||||
ControlItem r = new ControlItem();
|
||||
r.setCode(base.getCode());
|
||||
r.setName(over.getName() != null ? over.getName() : base.getName());
|
||||
r.setType(base.getType());
|
||||
r.setDpId(base.getDpId());
|
||||
r.setUnit(base.getUnit());
|
||||
r.setSort(base.getSort());
|
||||
r.setDefaultValue(base.getDefaultValue());
|
||||
r.setMin(base.getMin());
|
||||
r.setMax(base.getMax());
|
||||
r.setStep(base.getStep());
|
||||
r.setEnumValues(base.getEnumValues());
|
||||
r.setWritable(base.isWritable());
|
||||
r.setValue(base.getValue());
|
||||
r.setSemantic(over.getSemantic() != null ? over.getSemantic() : base.getSemantic());
|
||||
r.setGrp(over.getGrp() != null ? over.getGrp() : base.getGrp());
|
||||
r.setIsPrimary(base.getIsPrimary());
|
||||
r.setEnumLabels(base.getEnumLabels());
|
||||
r.setWidget(base.getWidget());
|
||||
return r;
|
||||
}
|
||||
|
||||
/** 解析设备级 schema_json。 */
|
||||
private PanelDeviceDto.DeviceSchema parseDeviceSchema(String json) {
|
||||
if (json == null || json.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(json, PanelDeviceDto.DeviceSchema.class);
|
||||
} catch (Exception e) {
|
||||
log.warn("解析设备级 schema 失败: deviceSchema parse error: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ControlSchema.ControlAction> toActions(Long productId) {
|
||||
List<ProductAction> actions = productActionMapper.selectList(
|
||||
new LambdaQueryWrapper<ProductAction>().eq(ProductAction::getProductId, productId));
|
||||
|
||||
@ -0,0 +1,256 @@
|
||||
package com.iot.device.service.spec;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iot.device.dto.PanelDeviceDto;
|
||||
import com.iot.device.entity.ProductProperty;
|
||||
import com.iot.device.mapper.ProductPropertyMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 屏端物模型回流服务 —— 把中控屏上报的设备级标准控制模型回流到产品物模型。
|
||||
*
|
||||
* <p>重构背景:屏端上报的 DeviceSchema 此前只写进 device.schema_json,全仓无人读取,
|
||||
* 属典型死数据;与此同时,屏端本地设备(zigbee / ble / matter)没有平台产品,
|
||||
* 在产品级物模型里也查不到任何东西 —— 导致这类设备拿不到 control-schema。</p>
|
||||
*
|
||||
* <p>本服务的职责:</p>
|
||||
* <ol>
|
||||
* <li>归一化:屏端用 BOOLEAN/INTEGER/READ_WRITE 这类通用协议类型,
|
||||
* 产品物模型用 bool/int/read,write,需做映射;</li>
|
||||
* <li>回流:把归一化后的属性 merge 进产品物模型 —— 已存在的补齐/修正,
|
||||
* 不存在的补建;产品级已有的、屏端没报的属性保留(产品级是超集);</li>
|
||||
* <li>语义:屏端已上报 semantic 与 channel,直接落库;缺失时由
|
||||
* SpecSemanticResolver 兜底推导。</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>回流后,设备级 schema_json 仍保留,但角色降级为设备级差异覆盖层:
|
||||
* 产品基线之外的本设备特有属性由它承载,由 ControlSchemaServiceImpl merge 后下发客户端。</p>
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PanelSpecAdoptService {
|
||||
|
||||
private final ProductPropertyMapper productPropertyMapper;
|
||||
private final SpecSemanticResolver semanticResolver;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/** 屏端通用协议类型 -> 产品物模型类型 */
|
||||
private static final Map<String, String> TYPE_MAP = Map.of(
|
||||
"boolean", "bool",
|
||||
"integer", "int",
|
||||
"number", "float",
|
||||
"enum", "enum",
|
||||
"string", "string",
|
||||
"bool", "bool",
|
||||
"int", "int",
|
||||
"float", "float");
|
||||
|
||||
/**
|
||||
* 将屏端上报的 schema 回流到产品物模型。
|
||||
*
|
||||
* @param productId 目标产品ID(为空则跳过回流,仅保留设备级 schema)
|
||||
* @param schema 屏端上报的设备级控制模型
|
||||
* @return 新建的属性数量
|
||||
*/
|
||||
@Transactional
|
||||
public int adopt(Long productId, PanelDeviceDto.DeviceSchema schema) {
|
||||
if (productId == null || schema == null || schema.getProperties() == null
|
||||
|| schema.getProperties().isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
List<ProductProperty> existing = productPropertyMapper.selectList(
|
||||
new LambdaQueryWrapper<ProductProperty>().eq(ProductProperty::getProductId, productId));
|
||||
Map<String, ProductProperty> byCode = new HashMap<>();
|
||||
for (ProductProperty p : existing) {
|
||||
byCode.put(p.getCode(), p);
|
||||
}
|
||||
|
||||
int created = 0;
|
||||
int sort = existing.size();
|
||||
for (PanelDeviceDto.PropertySpec ps : schema.getProperties()) {
|
||||
if (ps == null || !StringUtils.hasText(ps.getCode())) {
|
||||
continue;
|
||||
}
|
||||
String code = ps.getCode().trim();
|
||||
String type = mapType(ps.getType());
|
||||
String access = mapAccess(ps);
|
||||
String semantic = StringUtils.hasText(ps.getSemantic())
|
||||
? ps.getSemantic().trim().toLowerCase(Locale.ROOT)
|
||||
: null;
|
||||
String grp = null;
|
||||
|
||||
// 屏端未上报 semantic 时由统一规则推导
|
||||
if (!StringUtils.hasText(semantic)) {
|
||||
SpecSemanticResolver.Semantic s = semanticResolver.resolve(code, ps.getName(), type, access);
|
||||
semantic = s.getSemantic();
|
||||
grp = s.getGrp();
|
||||
access = s.isWritable() ? "write" : "read";
|
||||
}
|
||||
|
||||
ProductProperty cur = byCode.get(code);
|
||||
if (cur == null) {
|
||||
ProductProperty np = new ProductProperty();
|
||||
np.setProductId(productId);
|
||||
np.setCode(code);
|
||||
np.setName(ps.getName());
|
||||
np.setType(type);
|
||||
np.setAccess(access);
|
||||
np.setSemantic(semantic);
|
||||
np.setGrp(grp);
|
||||
np.setChannel(ps.getChannel());
|
||||
np.setMin(numText(ps.getMin()));
|
||||
np.setMax(numText(ps.getMax()));
|
||||
np.setStep(numText(ps.getStep()));
|
||||
np.setUnit(ps.getUnit());
|
||||
np.setDefaultValue(ps.getDefaultValue() == null ? null : String.valueOf(ps.getDefaultValue()));
|
||||
np.setEnumList(enumToJson(ps.getEnumList()));
|
||||
np.setSort(++sort);
|
||||
productPropertyMapper.insert(np);
|
||||
byCode.put(code, np);
|
||||
created++;
|
||||
} else {
|
||||
// 已存在:只补齐/修正屏端明确提供的字段,不做破坏性覆盖
|
||||
ProductProperty upd = new ProductProperty();
|
||||
upd.setId(cur.getId());
|
||||
boolean changed = false;
|
||||
if (StringUtils.hasText(ps.getName()) && !ps.getName().equals(cur.getName())) {
|
||||
upd.setName(ps.getName());
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getSemantic()) && StringUtils.hasText(semantic)) {
|
||||
upd.setSemantic(semantic);
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getGrp()) && StringUtils.hasText(grp)) {
|
||||
upd.setGrp(grp);
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getChannel()) && StringUtils.hasText(ps.getChannel())) {
|
||||
upd.setChannel(ps.getChannel());
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getEnumList()) && ps.getEnumList() != null) {
|
||||
upd.setEnumList(enumToJson(ps.getEnumList()));
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getMin()) && ps.getMin() != null) {
|
||||
upd.setMin(numText(ps.getMin()));
|
||||
changed = true;
|
||||
}
|
||||
if (!StringUtils.hasText(cur.getMax()) && ps.getMax() != null) {
|
||||
upd.setMax(numText(ps.getMax()));
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
productPropertyMapper.updateById(upd);
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("屏端物模型回流完成: productId={}, 新建={}, 屏端属性数={}",
|
||||
productId, created, schema.getProperties().size());
|
||||
return created;
|
||||
}
|
||||
/**
|
||||
* 屏端 access(READ/WRITE/READ_WRITE)-> 产品物模型 access(read/write/read,write)。
|
||||
*/
|
||||
private String mapAccess(PanelDeviceDto.PropertySpec ps) {
|
||||
String acc = ps.getAccess() == null ? null : ps.getAccess().trim().toUpperCase(Locale.ROOT);
|
||||
if (acc == null || acc.isEmpty()) {
|
||||
boolean r = ps.getReadable() == null || ps.getReadable();
|
||||
boolean w = ps.getWritable() != null && ps.getWritable();
|
||||
return accessOf(r, w);
|
||||
}
|
||||
return switch (acc) {
|
||||
case "READ" -> "read";
|
||||
case "WRITE" -> "write";
|
||||
case "READ_WRITE" -> "read,write";
|
||||
default -> acc.toLowerCase(Locale.ROOT);
|
||||
};
|
||||
}
|
||||
|
||||
private String accessOf(boolean readable, boolean writable) {
|
||||
if (readable && writable) {
|
||||
return "read,write";
|
||||
}
|
||||
return writable ? "write" : "read";
|
||||
}
|
||||
|
||||
private String mapType(String t) {
|
||||
if (t == null || t.isBlank()) {
|
||||
return "bool";
|
||||
}
|
||||
return TYPE_MAP.getOrDefault(t.trim().toLowerCase(Locale.ROOT), "string");
|
||||
}
|
||||
|
||||
private String numText(BigDecimal v) {
|
||||
return v == null ? null : v.stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
private String enumToJson(List<Object> enumList) {
|
||||
if (enumList == null || enumList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.writeValueAsString(enumList);
|
||||
} catch (Exception e) {
|
||||
log.warn("枚举序列化失败: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把屏端设备级 schema 转成与产品物模型同构的属性列表。
|
||||
* 用于「设备没有产品」的场景,此时直接以设备级 schema 作为唯一模型来源。
|
||||
*/
|
||||
public List<ProductProperty> toProperties(PanelDeviceDto.DeviceSchema schema) {
|
||||
List<ProductProperty> list = new ArrayList<>();
|
||||
if (schema == null || schema.getProperties() == null) {
|
||||
return list;
|
||||
}
|
||||
int sort = 1;
|
||||
for (PanelDeviceDto.PropertySpec ps : schema.getProperties()) {
|
||||
if (ps == null || !StringUtils.hasText(ps.getCode())) {
|
||||
continue;
|
||||
}
|
||||
ProductProperty pp = new ProductProperty();
|
||||
pp.setCode(ps.getCode().trim());
|
||||
pp.setName(ps.getName());
|
||||
pp.setType(mapType(ps.getType()));
|
||||
pp.setAccess(mapAccess(ps));
|
||||
pp.setSemantic(ps.getSemantic());
|
||||
pp.setChannel(ps.getChannel());
|
||||
pp.setMin(numText(ps.getMin()));
|
||||
pp.setMax(numText(ps.getMax()));
|
||||
pp.setStep(numText(ps.getStep()));
|
||||
pp.setUnit(ps.getUnit());
|
||||
pp.setEnumList(enumToJson(ps.getEnumList()));
|
||||
pp.setSort(sort++);
|
||||
SpecSemanticResolver.Semantic s = semanticResolver.resolve(
|
||||
pp.getCode(), pp.getName(), pp.getType(), pp.getAccess());
|
||||
if (!StringUtils.hasText(pp.getSemantic())) {
|
||||
pp.setSemantic(s.getSemantic());
|
||||
}
|
||||
if (!StringUtils.hasText(pp.getGrp())) {
|
||||
pp.setGrp(s.getGrp());
|
||||
}
|
||||
if (semanticResolver.isReadOnly(pp.getSemantic(), pp.getGrp(), pp.getCode())) {
|
||||
pp.setAccess("read");
|
||||
}
|
||||
list.add(pp);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user