jiazx0107@163.com
2023-08-22 5adce825013b49f0614db1746cffe43a7502de82
更新MODBUS-TCP协议 1
已修改10个文件
已添加2个文件
516 ■■■■ 文件已修改
igds-core/src/main/java/com/ld/igds/models/Device.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-core/src/main/java/com/ld/igds/view/Device.view.xml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-core/src/main/java/models/igds.model.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ModbusConfig.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ModbusUtil.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ServerUtil.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/command/AnalysisService.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/command/RemoteControlServiceImpl.java 198 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/data/ModbusTcp.java 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-verb/src/main/java/com/ld/igds/verb/controller/VerbController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-verb/src/main/java/com/ld/igds/verb/manager/VerbManager.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-web/.rules 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
igds-core/src/main/java/com/ld/igds/models/Device.java
@@ -78,6 +78,10 @@
    @PropertyDef(label = "关联设备通道", description = "针对双通道配置设备,如混流风口的风机、轴流风口的风机")
    private String link;
    @Column(name = "LINK_MODBUS_",length = 100)
    @PropertyDef(label = "关联设备Modbus")
    private String linkModbus;
    @Column(name = "EXT1_", length = 20)
    @PropertyDef(label = "扩展字段1", description = "根据业务需要自定义存储值")
    private String ext1;
igds-core/src/main/java/com/ld/igds/view/Device.view.xml
@@ -153,7 +153,6 @@
      <ClientEvent name="onHide">view.id(&quot;dsDevice&quot;).getData().cancel();</ClientEvent>
      <Property name="caption">编辑页面</Property>
      <Property name="width">800</Property>
      <Property name="height">450</Property>
      <Buttons>
        <Button>
          <Property name="caption">确定</Property>
@@ -232,6 +231,12 @@
            <Property name="property">modbus</Property>
            <Editor/>
          </AutoFormElement>
          <AutoFormElement layoutConstraint="colSpan:2">
            <Property name="name">linkModbus</Property>
            <Property name="property">linkModbus</Property>
            <Property name="label">风机Modbus</Property>
            <Editor/>
          </AutoFormElement>
          <Label layoutConstraint="colSpan:2">
            <Property name="text">modbus规则:开地址-关地址-停地址-开到位-关到位-开故障-关故障,无地址用N代替</Property>
            <Property name="style">
igds-core/src/main/java/models/igds.model.xml
@@ -314,7 +314,7 @@
      <Property name="label">备注</Property>
    </PropertyDef>
    <PropertyDef name="ggm">
      <Property/>
      <Property></Property>
      <Property name="label">国规码</Property>
    </PropertyDef>
  </DataType>
@@ -607,6 +607,10 @@
      <Property></Property>
      <Property name="label">Modbus配置</Property>
    </PropertyDef>
    <PropertyDef name="linkModbus">
      <Property/>
      <Property name="label">关联设备Modbus</Property>
    </PropertyDef>
    <PropertyDef name="ext1">
      <Property></Property>
      <Property name="label">扩展字段1</Property>
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ModbusConfig.java
@@ -40,7 +40,6 @@
        }
        return modbusMaster;
    }
    /**
@@ -53,10 +52,10 @@
        params.setPort(port);
        //设置为true,会导致TimeoutException: request=com.serotonin.modbus4j.ip.encap.EncapMessageRequest@774dfba5",
        //params.setEncapsulated(true);
        master = modbusFactory.createTcpMaster(params, true);// TCP åè®®
        master = modbusFactory.createTcpMaster(params, false);// TCP åè®®
        try {
            //设置超时时间
            master.setTimeout(3 * 1000);
            master.setTimeout(2 * 1000);
            //设置重连次数
            master.setRetries(3);
            //初始化
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ModbusUtil.java
@@ -1,8 +1,12 @@
package com.ld.igds.protocol.modbus;
import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.ReadCoilsRequest;
import com.serotonin.modbus4j.msg.ReadCoilsResponse;
import com.serotonin.modbus4j.msg.ReadDiscreteInputsRequest;
@@ -19,6 +23,7 @@
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -27,6 +32,7 @@
 * @author: Andy
 * @update-time: 2023/8/11
 */
@Slf4j
@Component
public class ModbusUtil {
@@ -37,7 +43,15 @@
    private ModbusConfig modbusConfig;
    public boolean[] readCoilStatus(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
    /**
     * è¯»çº¿åœˆ--01
     *
     * @param ip
     * @param port
     * @param offset
     * @param numberOfRegister
     */
    public boolean[] readStatus01(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
        ModbusMaster master = modbusConfig.getMaster(ip, port);
        ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfRegister);
@@ -48,32 +62,26 @@
    }
    /**
     * @Description: è¯»å–外围设备输入的开关量,相当于功能码:02H-读离散输入状态
     * @Description: 02H-读离散输入量
     * @Param: [ip, offset, numberOfRegister]
     * @return: boolean[]
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public boolean[] readInputStatus(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
    public boolean[] readStatus02(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
        ModbusMaster master = modbusConfig.getMaster(ip, port);
        ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, offset, numberOfRegister);
        ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();
        return valueRegroup(numberOfRegister, booleans);
    }
    /**
     * @Description: è¯»å–保持寄存器数据,相当于功能码:03H-读保持寄存器
     * @Description: 03H-读保持寄存器
     * @Param: [ip, offset, numberOfRegister]
     * @return: short[]
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public short[] readHoldingRegister(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
    public short[] readStatus03(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
        ModbusMaster master = modbusConfig.getMaster(ip, port);
        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfRegister);
@@ -82,19 +90,43 @@
    }
    /**
     * @Description: è¯»å–外围设备输入的数据,相当于功能码:04H-读输入寄存器
     * @Description: 04H-读输入寄存器
     * @Param: [ip, offset, numberOfRegister]
     * @return: short[]
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public short[] readInputRegisters(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
    public short[] readStatus04(String ip, int port, int offset, int numberOfRegister) throws ModbusTransportException {
        ModbusMaster master = modbusConfig.getMaster(ip, port);
        ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfRegister);
        ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);
        return response.getShortData();
    }
    public BatchResults<Integer> readBatch(String ip, int port) throws Exception {
        ModbusMaster master = modbusConfig.getMaster(ip, port);
        if (null == master) return null;
        return readBatch(master);
    }
    /**
     * æ‰¹é‡è¯»å–多个
     *
     * @param master
     * @throws ModbusTransportException
     */
    public BatchResults<Integer> readBatch(ModbusMaster master) throws Exception {
        BatchRead<Integer> batch = new BatchRead<>();
        batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.TWO_BYTE_INT_SIGNED));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));
        batch.setContiguousRequests(true);
        BatchResults<Integer> results = master.send(batch);
        log.info("batchRead:" + results.getValue(0));
        log.info("batchRead:" + results.getValue(1));
        return results;
    }
    /**
@@ -102,10 +134,8 @@
     * @Param: [ip, writeOffset, writeValue]
     * @return: boolean
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public boolean writeCoil(String ip, int port, int writeOffset, boolean writeValue) throws ModbusTransportException {
    public boolean writeValue05(String ip, int port, int writeOffset, boolean writeValue) throws ModbusTransportException {
        ModbusMaster tcpMaster = modbusConfig.getMaster(ip, port);
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
@@ -118,10 +148,8 @@
     * @Param: [ip, startOffset, data]
     * @return: boolean
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public boolean writeCoils(String ip, int port, int startOffset, boolean[] data) throws ModbusTransportException {
    public boolean writeValues15(String ip, int port, int startOffset, boolean[] data) throws ModbusTransportException {
        ModbusMaster tcpMaster = modbusConfig.getMaster(ip, port);
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, data);
@@ -135,10 +163,8 @@
     * @Param: [ip, writeOffset, writeValue]
     * @return: boolean
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public boolean writeHoldingRegister(String ip, int port,int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException {
    public boolean writeValue06(String ip, int port, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException {
        ModbusMaster tcpMaster = modbusConfig.getMaster(ip, port);
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
@@ -152,10 +178,8 @@
     * @Param: [ip, startOffset, data]
     * @return: boolean
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    public boolean writeHoldingRegisters(String ip,int port, int startOffset, short[] data) throws ModbusTransportException, ModbusInitException {
    public boolean writeValues16(String ip, int port, int startOffset, short[] data) throws ModbusTransportException, ModbusInitException {
        ModbusMaster tcpMaster = modbusConfig.getMaster(ip, port);
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, data);
@@ -168,8 +192,6 @@
     * @Param: [numberOfBits, values]
     * @return: boolean[]
     * @throws:
     * @Author: Ricardo.Liu
     * @Date: 2020/5/8
     */
    private boolean[] valueRegroup(int numberOfBits, boolean[] values) {
        boolean[] bs = new boolean[numberOfBits];
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/ServerUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.ld.igds.protocol.modbus;
import com.ld.igds.util.ContextUtil;
import java.util.HashMap;
import java.util.Map;
/**
 *
 */
public class ServerUtil {
    /**
     * ç”¨æ¥ç¼“存,TCP设备执行时间记录key = TCP唯一标志,value = å½“前执行时间
     */
    public static Map<String, Long> contextExeModbusTcp = new HashMap<>();
    /**
     * è®¾å¤‡çŠ¶æ€è¿”å›žçš„ç»“æžœ KEY= companyId + serId + deviceCode value = ç»“果状态
     */
    private static Map<String, String> contextStatusMap = new HashMap<>();
    /**
     * è®¾å¤‡è§£æžåŽçš„装法存放
     *
     * @param serId
     * @param deviceCode è®¾å¤‡é€šé“ID
     * @param status     ä¸è€ƒè™‘设备类型,只在通道上标记是OPEN或者CLOSE即可
     */
    public static void add2StatusMap(String companyId, String serId, String deviceCode, String status) {
        contextStatusMap.put(ContextUtil.buildDeviceStatusKey(companyId, serId, deviceCode), status);
    }
    public static Map<String, String> getStatusMap() {
        return contextStatusMap;
    }
}
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/command/AnalysisService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ld.igds.protocol.modbus.command;
import com.ld.igds.common.CoreDeviceService;
import com.ld.igds.io.constant.OrderRespEnum;
import com.ld.igds.io.notify.NotifyWebInvoker;
import com.ld.igds.io.request.DeviceControlRequest;
import com.ld.igds.protocol.modbus.ServerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * è§£æž
 */
@Slf4j
@Component
public class AnalysisService {
    @Resource
    private CoreDeviceService deviceService;
    @Resource
    private NotifyWebInvoker notifyInvoker;
    /**
     * å¼‚步更新设备状态,
     *
     * @param request
     * @param sleepTime å»¶è¿Ÿæ‰§è¡Œæ—¶é—´=毫秒值,如果==0 ï¼Œè¡¨ç¤ºä¸å»¶è¿Ÿ
     */
    @Async
    public void analysisDevice(DeviceControlRequest request, long sleepTime) {
        try {
            if (sleepTime > 0) {
                Thread.sleep(sleepTime);
            }
            deviceService.updateStatus(request.getCompanyId(), request.getSerId(), ServerUtil.getStatusMap());
            notifyInvoker.notifyAnalysisStatusSuccess(request.getCompanyId(), request.getSerId(), OrderRespEnum.MSG_SUCCESS, "设备状态查询成功并完成解析!");
        } catch (Exception e) {
            log.error("---MODBUS-TCP-状态解析异常{}", e);
        }
    }
}
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/command/RemoteControlServiceImpl.java
@@ -13,6 +13,7 @@
import com.ld.igds.io.response.DeviceControlResponse;
import com.ld.igds.models.Device;
import com.ld.igds.protocol.modbus.ModbusUtil;
import com.ld.igds.protocol.modbus.ServerUtil;
import com.ld.igds.protocol.modbus.data.ModbusTcp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -36,7 +37,10 @@
    @Resource
    private CoreDeviceService deviceService;
    @Resource
    private AnalysisService analysisService;
    @Resource
    private ModbusUtil modbusUtil;
    @Override
    public String getProtocol() {
@@ -51,14 +55,11 @@
            return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "没有需要执行的设备");
        }
        try {
            Device device;
            ModbusTcp modbusTcp;
            String[] addr;
            String temp;
            ModbusTcp modbusTcpLink = null;
            String temp = Constant.YN_N;
            int addrExe = 65535;
            for (ExeDevice exeDevice : deviceList) {
                device = deviceService.getCacheDeviceById(exeDevice.getCompanyId(), exeDevice.getId());
@@ -67,79 +68,200 @@
                if (null == device.getModbus()) continue;
                modbusTcp = new ModbusTcp();
                modbusTcp = new ModbusTcp(device.getModbus());
                modbusTcp.setIp(request.getIp());
                modbusTcp.setPort(request.getPort());
                modbusTcp.setDeviceId(device.getId());
                modbusTcp.setDeviceCode(device.getPassCode() + "");
                modbusTcp.setSerId(request.getSerId());
                modbusTcp.setCompanyId(request.getCompanyId());
                //modbus规则:开地址-关地址-停地址-开到位-关到位-开故障-关故障,无地址用N代替
                addr = device.getModbus().split("-");
                temp = addr[0];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrOpen(temp);
                temp = addr[1];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrClose(temp);
                temp = addr[2];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrStop(temp);
                temp = addr[3];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrOpenEnd(temp);
                temp = addr[4];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrCloseEnd(temp);
                temp = addr[5];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrOpenError(temp);
                temp = addr[6];
                if (!Constant.YN_N.equals(temp)) modbusTcp.setAddrCloseError(temp);
                if (null != device.getLinkModbus()) {
                    modbusTcpLink = new ModbusTcp(device.getLinkModbus());
                    modbusTcpLink.setIp(request.getIp());
                    modbusTcpLink.setPort(request.getPort());
                    modbusTcpLink.setDeviceCode(device.getLink());
                    modbusTcpLink.setSerId(request.getSerId());
                    modbusTcpLink.setCompanyId(request.getCompanyId());
                }
                //根据设备目标目标状态,选择需要执行的通道
                if (DeviceStatus.CLOSE.getCode().equals(device.getTargetStatus())) {
                    addrExe = Integer.valueOf(modbusTcp.getAddrClose());
                    temp = modbusTcp.getAddrClose();
                }
                if(DeviceStatus.OPEN.getCode().equals(device.getTargetStatus())){
                    addrExe = Integer.valueOf(modbusTcp.getAddrOpen());
                    temp = modbusTcp.getAddrOpen();
                }
                if (null == modbusTcpLink) {
                    //根据设备目标状态,调用MODBUS执行
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcp.setAddrExe(addrExe);
                    doExe(modbusTcp, device.getTargetStatus());
                    continue;
                }
                //TODO å…¶ä»–状态待定
                //如果是开风机
                if (DeviceStatus.F_OPEN.getCode().equals(device.getTargetStatus())) {
                //根据设备目标状态,调用MODBUS执行
                modbusUtil.writeCoil(modbusTcp.getIp(), modbusTcp.getPort(),addrExe, true);
                    //先开窗口
                    temp = modbusTcp.getAddrOpen();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcp.setAddrExe(addrExe);
                    doExe(modbusTcp, DeviceStatus.OPEN.getCode());
                    Thread.sleep(300);
                    //再开风机
                    temp = modbusTcpLink.getAddrOpen();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcpLink.setAddrExe(addrExe);
                    doExe(modbusTcpLink, DeviceStatus.OPEN.getCode());
                }
                //如果关风机
                if(DeviceStatus.F_CLOSE.equals(device.getTargetStatus())){
                    temp = modbusTcpLink.getAddrClose();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcpLink.setAddrExe(addrExe);
                    doExe(modbusTcpLink, DeviceStatus.CLOSE.getCode());
                }
                //如果开窗
                if(DeviceStatus.W_OPEN.equals(device.getTargetStatus())){
                    temp = modbusTcp.getAddrOpen();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcp.setAddrExe(addrExe);
                    doExe(modbusTcp, device.getTargetStatus());
                }
                //如果是关窗户
                if(DeviceStatus.W_CLOSE.equals(device.getTargetStatus())){
                    //先关风机
                    temp = modbusTcpLink.getAddrClose();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcpLink.setAddrExe(addrExe);
                    doExe(modbusTcpLink, DeviceStatus.CLOSE.getCode());
                    Thread.sleep(300);
                    //在关窗户
                    temp = modbusTcp.getAddrClose();
                    addrExe = Integer.valueOf(temp) - 1;
                    modbusTcp.setAddrExe(addrExe);
                    doExe(modbusTcp, DeviceStatus.CLOSE.getCode());
                }
            }
        } catch (Exception e) {
            log.error("调用MODBUS-TCP执行异常:{}", e);
            return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "后台执行异常:" + e.getMessage());
        }
        return new DeviceControlResponse(OrderRespEnum.ORDER_SUCCESS);
    }
    private void doExe(ModbusTcp modbusTcp, String targetStatus) throws Exception {
        boolean exeResult = modbusUtil.writeValue05(modbusTcp.getIp(), modbusTcp.getPort(), modbusTcp.getAddrExe(), true);
        if (exeResult) {
            ServerUtil.add2StatusMap(modbusTcp.getCompanyId(), modbusTcp.getSerId(), modbusTcp.getDeviceCode(), targetStatus);
        }
    }
    @Override
    public DeviceControlResponse closeAll(DeviceControlRequest request) {
        return null;
        return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体不支持");
    }
    @Override
    public DeviceControlResponse queryStatus(DeviceControlRequest request) {
        return null;
        try {
            List<Device> list = deviceService.getCacheDeviceBySerId(request.getCompanyId(), request.getSerId());
            if (null == list || list.isEmpty()) {
                return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "未获取到设备列表信息");
            }
            ModbusTcp modbusTcp;
            ModbusTcp modbusTcpLink;
            int addrStart;
            boolean[] result;
            for (Device device : list) {
                if (null == device.getModbus()) continue;
                modbusTcp = new ModbusTcp(device.getModbus());
                modbusTcp.setIp(request.getIp());
                modbusTcp.setPort(request.getPort());
                modbusTcp.setDeviceCode(device.getPassCode() + "");
                modbusTcp.setSerId(request.getSerId());
                addrStart = Integer.valueOf(modbusTcp.getAddrOpenEnd()) - 1;
                result = modbusUtil.readStatus02(modbusTcp.getIp(), modbusTcp.getPort(), addrStart, 2);
                log.debug("---------读取状态------{}--{}", modbusTcp.getDeviceCode(), result.toString());
                analysisResult(device.getCompanyId(), device.getSerId(), modbusTcp.getDeviceCode(), result);
                if (null != device.getLinkModbus()) {
                    Thread.sleep(300);
                    modbusTcpLink = new ModbusTcp(device.getModbus());
                    modbusTcpLink.setIp(request.getIp());
                    modbusTcpLink.setPort(request.getPort());
                    modbusTcpLink.setSerId(request.getSerId());
                    modbusTcpLink.setDeviceCode(device.getLink());
                    addrStart = Integer.valueOf(modbusTcpLink.getAddrOpenEnd()) - 1;
                    result = modbusUtil.readStatus02(modbusTcpLink.getIp(), modbusTcpLink.getPort(), addrStart, 2);
                    log.debug("---------读取状态-LINK------{}--{}", modbusTcpLink.getDeviceCode(), result.toString());
                    analysisResult(device.getCompanyId(), device.getSerId(), modbusTcpLink.getDeviceCode(), result);
                }
            }
        } catch (Exception e) {
            log.error("调用MODBUS-TCP执行异常:{}", e);
            return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "后台执行异常:" + e.getMessage());
        }
        analysisService.analysisDevice(request, 3000);
        return new DeviceControlResponse(OrderRespEnum.ORDER_SUCCESS);
    }
    /**
     * è¿”回两位,第一位是开到位,第二位是关到位,根据这两个标记确认当前设备的状态
     *
     * @param deviceCode
     * @param result
     */
    private void analysisResult(String companyId, String serId, String deviceCode, boolean[] result) {
        if (result[0]) {
            ServerUtil.add2StatusMap(companyId, serId, deviceCode, DeviceStatus.OPEN.getCode());
        }
        if (result[1]) {
            ServerUtil.add2StatusMap(companyId, serId, deviceCode, DeviceStatus.CLOSE.getCode());
        }
    }
    @Override
    public DeviceControlResponse tempControl(TempControlRequest request) {
        return null;
        return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体未接入当前控制");
    }
    @Override
    public DeviceControlResponse airAutoControl(DeviceAutoControlRequest request) {
        return null;
        return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体未接入当前控制");
    }
    @Override
    public DeviceControlResponse n2AutoControl(DeviceAutoControlRequest request) {
        return null;
        return new DeviceControlResponse(OrderRespEnum.ORDER_ERROR.getCode(), "终端柜体未接入当前控制");
    }
}
igds-protocol-modbus/src/main/java/com/ld/igds/protocol/modbus/data/ModbusTcp.java
@@ -1,5 +1,6 @@
package com.ld.igds.protocol.modbus.data;
import com.ld.igds.constant.Constant;
import lombok.Data;
/**
@@ -10,7 +11,10 @@
@Data
public class ModbusTcp {
    private String deviceId;
    private String companyId;
    private String deviceCode;
    private String serId;
@@ -21,36 +25,73 @@
    /**
     * å¼€åœ°å€
     **/
    private String addrOpen = "65535";
    private String addrOpen = Constant.YN_N;
    /**
     * å…³åœ°å€
     **/
    private String addrClose = "65535";
    private String addrClose = Constant.YN_N;
    /**
     * åœåœ°å€
     **/
    private String addrStop = "65535";
    private String addrStop = Constant.YN_N;
    /**
     * å¼€åˆ°ä½åœ°å€
     **/
    private String addrOpenEnd = "65535";
    private String addrOpenEnd = Constant.YN_N;
    /**
     * å…³åˆ°ä½åœ°å€
     **/
    private String addrCloseEnd = "65535";
    private String addrCloseEnd = Constant.YN_N;
    /**
     * å¼€æ•…障地址
     **/
    private String addrOpenError = "65535";
    private String addrOpenError = Constant.YN_N;
    /**
     * å…³æ•…障地址
     **/
    private String addrCloseError = "65535";
    private String addrCloseError = Constant.YN_N;
    private int addrExe = 65535;
    public ModbusTcp() {
        super();
    }
    public ModbusTcp(String modbusStr) {
        //modbus规则:开地址-关地址-停地址-开到位-关到位-开故障-关故障,无地址用N代替
        String[] addr = modbusStr.split("-");
        this.addrOpen = addr[0];
        this.addrClose = addr[1];
        this.addrStop = addr[2];
        this.addrOpenEnd = addr[3];
        this.addrCloseEnd = addr[4];
        this.addrOpenError = addr[5];
        this.addrCloseError = addr[6];
    }
//
//    public ModbusTcp(String modbusStr) {
//        //modbus规则:开地址-关地址-停地址-开到位-关到位-开故障-关故障,无地址用N代替
//        String[] addr = modbusStr.split("-");
//        String temp = addr[0];
//        if (!Constant.YN_N.equals(temp)) this.addrOpen = temp;
//        temp = addr[1];
//        if (!Constant.YN_N.equals(temp)) this.addrClose = temp;
//        temp = addr[2];
//        if (!Constant.YN_N.equals(temp)) this.addrStop = temp;
//        temp = addr[3];
//        if (!Constant.YN_N.equals(temp)) this.addrOpenEnd = temp;
//        temp = addr[4];
//        if (!Constant.YN_N.equals(temp)) this.addrCloseEnd = temp;
//        temp = addr[5];
//        if (!Constant.YN_N.equals(temp)) this.addrOpenError = temp;
//        temp = addr[6];
//        if (!Constant.YN_N.equals(temp)) this.addrCloseError = temp;
//    }
}
igds-verb/src/main/java/com/ld/igds/verb/controller/VerbController.java
@@ -64,10 +64,6 @@
            deptId = ContextUtil.subDeptId(user);
        }
        // èŽ·å–å½“å‰ç”¨æˆ·æ‰€åœ¨çš„åˆ†åº“åç§°
//        DefaultDept dept = commonManager.getSubDept(user, deptId);
//        view.addObject("dept", dept);
        view.addObject("deptId", deptId);
        // èŽ·å–å½“å‰éƒ¨é—¨ï¼Œæ‰€æœ‰ä»“åº“åˆ—è¡¨
igds-verb/src/main/java/com/ld/igds/verb/manager/VerbManager.java
@@ -5,7 +5,10 @@
import com.ld.igds.common.CoreSerService;
import com.ld.igds.common.DepotStatusService;
import com.ld.igds.common.dto.DepotSerData;
import com.ld.igds.constant.*;
import com.ld.igds.constant.BizType;
import com.ld.igds.constant.DepotType;
import com.ld.igds.constant.DeviceType;
import com.ld.igds.constant.RespCodeEnum;
import com.ld.igds.data.PageResponse;
import com.ld.igds.io.RemoteControlService;
import com.ld.igds.io.RemoteManager;
@@ -22,11 +25,10 @@
import com.ld.igds.util.ContextUtil;
import com.ld.igds.verb.AreationModel;
import com.ld.igds.verb.dto.VerbParam;
import com.ld.igds.verb.service.CoreAreationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -41,19 +43,17 @@
@Component
public class VerbManager {
    @Autowired
    @Resource
    private CoreCommonService coreCommonService;
    @Autowired
    @Resource
    private CoreDeviceService coreDeviceService;
    @Autowired
    @Resource
    private ExeOrderService exeOrderService;
    @Autowired
    @Resource
    private RemoteManager remoteManager;
    @Autowired
    @Resource
    private CoreSerService coreSerService;
    @Autowired
    private CoreAreationService areationService;
    @Autowired
    @Resource
    private DepotStatusService depotCheckService;
    private RemoteControlService remoteControlService;
@@ -243,11 +243,11 @@
        // èŽ·å–åˆ†æœºä¿¡æ¯
        DeviceSer deviceSer = coreSerService.getCacheSer(param.getCompanyId(), serId);
        if (Constant.YN_N.equals(deviceSer.getStatus())) {
            return new DeviceControlResponse(
                    OrderRespEnum.ORDER_ERROR.getCode(),
                    "当前设备所属控制柜[" + deviceSer.getName() + "]不在线,执行失败。");
        }
//        if (Constant.YN_N.equals(deviceSer.getStatus())) {
//            return new DeviceControlResponse(
//                    OrderRespEnum.ORDER_ERROR.getCode(),
//                    "当前设备所属控制柜[" + deviceSer.getName() + "]不在线,执行失败。");
//        }
        DeviceControlRequest request = new DeviceControlRequest();
        request.setDepotId(param.getDepotId());
igds-web/.rules
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<RuleSet version="1.1"><PackageInfos>
<PackageInfo name="dorado-core" version="7.6.0.2.190128.1750"/>
<PackageInfo name="dorado-uploader" version="1.0.20-SNAPSHOT"/>
<PackageInfo name="bdf2-orm" version="2.1.0"/>
<PackageInfo name="bdf2-core" version="2.0.9"/>
<PackageInfo name="bdf2-job" version="2.0.5-SNAPSHOT"/>
<PackageInfo name="dorado-uploader" version="1.0.20-SNAPSHOT"/>
<PackageInfo name="dorado-skin-sky" version="2.0.2"/>
<PackageInfo name="bdf2-job" version="2.0.5-SNAPSHOT"/>
<PackageInfo name="dorado-intro" version="0.2.1.140715.2255"/>
<PackageInfo name="bdf2-swfviewer" version="2.0.6-SNAPSHOT"/>
<PackageInfo name="bdf2-export" version="2.0.8"/>
@@ -283,7 +283,7 @@
<Prop name="verticalText" type="boolean"/></Props><Children><Child rule="Tab" name="Tab" aggregated="true" public="false"></Child></Children></Rule><Rule name="ToolBar" parents="com.bstek.dorado.view.widget.Control" label="ToolBar" type="com.bstek.dorado.view.widget.base.toolbar.ToolBar" sortFactor="2023" category="General" icon="/com/bstek/dorado/view/widget/base/toolbar/ToolBar.png" clientTypes="desktop"><Props>
<Prop name="fixRight" type="boolean"/>
<Prop name="height" visible="false"/>
<Prop name="showMenuOnHover" defaultValue="false" type="boolean"/></Props><Children><Child rule="Fill" name="Fill" aggregated="true"></Child><Child rule="MenuButton" name="MenuButton" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.base.toolbar.Separator" name="Separator" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.base.toolbar.Button" name="ToolBarButton" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.base.toolbar.Label" name="ToolBarLabel" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.Control" name="Items" aggregated="true"></Child></Children></Rule><Rule name="SplitPanel" parents="com.bstek.dorado.view.widget.Control" label="SplitPanel" type="com.bstek.dorado.view.widget.base.SplitPanel" sortFactor="2024" category="General" icon="/com/bstek/dorado/view/widget/base/SplitPanel.png" clientTypes="desktop"><Props>
<Prop name="showMenuOnHover" defaultValue="false" type="boolean"/></Props><Children><Child rule="com.bstek.dorado.view.widget.base.toolbar.Button" name="ToolBarButton" aggregated="true"></Child><Child rule="Separator" name="Separator" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.base.toolbar.Label" name="ToolBarLabel" aggregated="true"></Child><Child rule="MenuButton" name="MenuButton" aggregated="true"></Child><Child rule="Fill" name="Fill" aggregated="true"></Child><Child rule="com.bstek.dorado.view.widget.Control" name="Items" aggregated="true"></Child></Children></Rule><Rule name="SplitPanel" parents="com.bstek.dorado.view.widget.Control" label="SplitPanel" type="com.bstek.dorado.view.widget.base.SplitPanel" sortFactor="2024" category="General" icon="/com/bstek/dorado/view/widget/base/SplitPanel.png" clientTypes="desktop"><Props>
<Prop name="animate" type="java.lang.Boolean"/>
<Prop name="collapseBothSide" defaultValue="false" type="boolean"/>
<Prop name="collapseable" defaultValue="true" type="boolean"/>
@@ -889,7 +889,11 @@
<ClientEvent name="onTabContextMenu" parameters="self,arg"/>
<ClientEvent name="onTabChange" parameters="self,arg"/>
<ClientEvent name="onTabRemove" parameters="self,arg"/>
<ClientEvent name="beforeTabChange" parameters="self,arg"/></ClientEvents></Rule><Rule name="Fill" parents="com.bstek.dorado.view.widget.Control" label="Fill" type="com.bstek.dorado.view.widget.base.toolbar.Fill" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Fill.png" clientTypes="desktop"></Rule><Rule name="MenuButton" parents="Button" label="MenuButton" nodeName="MenuButton" type="com.bstek.dorado.view.widget.base.toolbar.MenuButton" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/MenuButton.png" clientTypes="desktop"><Props>
<ClientEvent name="beforeTabChange" parameters="self,arg"/></ClientEvents></Rule><Rule name="com.bstek.dorado.view.widget.base.toolbar.Button" parents="Button" label="ToolBarButton" nodeName="ToolBarButton" type="com.bstek.dorado.view.widget.base.toolbar.Button" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Button.png" clientTypes="desktop"><Props>
<Prop name="hideMenuOnMouseLeave" type="boolean"/>
<Prop name="hideMenuOnMouseLeaveDelay" defaultValue="300" type="int"/>
<Prop name="showMenuOnHover" defaultValue="false" type="boolean"/></Props></Rule><Rule name="Separator" parents="com.bstek.dorado.view.widget.Control" label="Separator" type="com.bstek.dorado.view.widget.base.toolbar.Separator" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Separator.png" clientTypes="desktop"></Rule><Rule name="com.bstek.dorado.view.widget.base.toolbar.Label" parents="com.bstek.dorado.view.widget.Control" label="Label" nodeName="ToolBarLabel" type="com.bstek.dorado.view.widget.base.toolbar.Label" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Label.png" clientTypes="desktop"><Props>
<Prop name="text"/></Props></Rule><Rule name="MenuButton" parents="Button" label="MenuButton" nodeName="MenuButton" type="com.bstek.dorado.view.widget.base.toolbar.MenuButton" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/MenuButton.png" clientTypes="desktop"><Props>
<Prop name="hideMenuOnMouseLeave" type="boolean"/>
<Prop name="hideMenuOnMouseLeaveDelay" defaultValue="300" type="int"/>
<Prop name="menu" deprecated="true" visible="false"/>
@@ -907,7 +911,7 @@
<Prop name="hideOnClick" defaultValue="true" type="boolean"/>
<Prop name="icon"/>
<Prop name="iconClass"/></Props><ClientEvents>
<ClientEvent name="onClick" parameters="self,arg"/></ClientEvents></Rule><Rule name="Separator" parents="BaseMenuItem" label="Separator" type="com.bstek.dorado.view.widget.base.menu.Separator" icon="/com/bstek/dorado/view/widget/base/menu/Separator.png" clientTypes="desktop,touch"></Rule><Rule name="ControlMenuItem" parents="TextMenuItem" label="ControlMenuItem" type="com.bstek.dorado.view.widget.base.menu.ControlMenuItem" icon="/com/bstek/dorado/view/widget/base/menu/ControlMenuItem.png" clientTypes="desktop"><Children><Child rule="FloatControl" name="Control"></Child></Children></Rule><Rule name="FloatControl" abstract="true" type="com.bstek.dorado.view.widget.FloatControl"><Props>
<ClientEvent name="onClick" parameters="self,arg"/></ClientEvents></Rule><Rule name="ControlMenuItem" parents="TextMenuItem" label="ControlMenuItem" type="com.bstek.dorado.view.widget.base.menu.ControlMenuItem" icon="/com/bstek/dorado/view/widget/base/menu/ControlMenuItem.png" clientTypes="desktop"><Children><Child rule="FloatControl" name="Control"></Child></Children></Rule><Rule name="FloatControl" abstract="true" type="com.bstek.dorado.view.widget.FloatControl"><Props>
<Prop name="align" enumValues="left,innerleft,center,innerright,top" visible="false"/>
<Prop name="anchorTarget" visible="false"/>
<Prop name="animateTarget" visible="false"/>
@@ -928,14 +932,10 @@
<Prop name="shadowMode" enumValues="drop,sides,frame,none"/>
<Prop name="showAnimateType" enumValues="zoom,modernZoom,flip,slide,safeSlide,modernSlide,fade,none"/>
<Prop name="top" type="int"/>
<Prop name="vAlign" enumValues="top,innertop,center,innerbottom,bottom" visible="false"/></Props></Rule><Rule name="CheckableMenuItem" parents="MenuItem" label="CheckableMenuItem" type="com.bstek.dorado.view.widget.base.menu.CheckableMenuItem" icon="/com/bstek/dorado/view/widget/base/menu/CheckableMenuItem.png" clientTypes="desktop"><Props>
<Prop name="vAlign" enumValues="top,innertop,center,innerbottom,bottom" visible="false"/></Props></Rule><Rule name="com.bstek.dorado.view.widget.base.menu.Separator" parents="BaseMenuItem" label="Separator" type="com.bstek.dorado.view.widget.base.menu.Separator" icon="/com/bstek/dorado/view/widget/base/menu/Separator.png" clientTypes="desktop,touch"></Rule><Rule name="CheckableMenuItem" parents="MenuItem" label="CheckableMenuItem" type="com.bstek.dorado.view.widget.base.menu.CheckableMenuItem" icon="/com/bstek/dorado/view/widget/base/menu/CheckableMenuItem.png" clientTypes="desktop"><Props>
<Prop name="checked" type="boolean"/>
<Prop name="group"/></Props><ClientEvents>
<ClientEvent name="onCheckedChange" parameters="self,arg"/></ClientEvents></Rule><Rule name="com.bstek.dorado.view.widget.base.toolbar.Separator" parents="com.bstek.dorado.view.widget.Control" label="Separator" type="com.bstek.dorado.view.widget.base.toolbar.Separator" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Separator.png" clientTypes="desktop"></Rule><Rule name="com.bstek.dorado.view.widget.base.toolbar.Button" parents="Button" label="ToolBarButton" nodeName="ToolBarButton" type="com.bstek.dorado.view.widget.base.toolbar.Button" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Button.png" clientTypes="desktop"><Props>
<Prop name="hideMenuOnMouseLeave" type="boolean"/>
<Prop name="hideMenuOnMouseLeaveDelay" defaultValue="300" type="int"/>
<Prop name="showMenuOnHover" defaultValue="false" type="boolean"/></Props></Rule><Rule name="com.bstek.dorado.view.widget.base.toolbar.Label" parents="com.bstek.dorado.view.widget.Control" label="Label" nodeName="ToolBarLabel" type="com.bstek.dorado.view.widget.base.toolbar.Label" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Label.png" clientTypes="desktop"><Props>
<Prop name="text"/></Props></Rule><Rule name="Section" parents="ClientEventSupportedElement" label="Section" type="com.bstek.dorado.view.widget.base.accordion.Section" icon="/com/bstek/dorado/view/widget/base/accordion/Section.png"><Props>
<ClientEvent name="onCheckedChange" parameters="self,arg"/></ClientEvents></Rule><Rule name="Fill" parents="com.bstek.dorado.view.widget.Control" label="Fill" type="com.bstek.dorado.view.widget.base.toolbar.Fill" scope="protected" category="ToolBar" icon="/com/bstek/dorado/view/widget/base/toolbar/Fill.png" clientTypes="desktop"></Rule><Rule name="Section" parents="ClientEventSupportedElement" label="Section" type="com.bstek.dorado.view.widget.base.accordion.Section" icon="/com/bstek/dorado/view/widget/base/accordion/Section.png"><Props>
<Prop name="caption"/>
<Prop name="className"/>
<Prop name="disabled" type="boolean"/>
@@ -1011,14 +1011,15 @@
<Prop name="visible" defaultValue="true" type="boolean"/></Props><ClientEvents>
<ClientEvent name="onGetCellEditor" parameters="self,arg"/>
<ClientEvent name="onHeaderClick" parameters="self,arg"/>
<ClientEvent name="onRenderHeaderCell" parameters="self,arg"/></ClientEvents></Rule><Rule name="AbstractDataColumn" parents="Column" abstract="true" type="com.bstek.dorado.view.widget.grid.AbstractDataColumn"><Props>
<ClientEvent name="onRenderHeaderCell" parameters="self,arg"/></ClientEvents></Rule><Rule name="RowNumColumn" parents="AbstractDataColumn" label="RowNumColumn" type="com.bstek.dorado.view.widget.grid.RowNumColumn" icon="/com/bstek/dorado/view/widget/grid/RowNumColumn.png"></Rule><Rule name="AbstractDataColumn" parents="Column" abstract="true" type="com.bstek.dorado.view.widget.grid.AbstractDataColumn"><Props>
<Prop name="filterBarRenderer"/>
<Prop name="footerRenderer"/>
<Prop name="renderer"/>
<Prop name="resizeable" defaultValue="true" type="boolean"/>
<Prop name="width"/></Props><ClientEvents>
<ClientEvent name="onRenderFooterCell" parameters="self,arg"/>
<ClientEvent name="onRenderCell" parameters="self,arg"/></ClientEvents></Rule><Rule name="DataColumn" parents="AbstractDataColumn" label="DataColumn" type="com.bstek.dorado.view.widget.grid.DataColumn" icon="/com/bstek/dorado/view/widget/grid/DataColumn.png" labelProperty="name,property"><Props>
<ClientEvent name="onRenderCell" parameters="self,arg"/></ClientEvents></Rule><Rule name="IndicatorColumn" parents="AbstractDataColumn" label="IndicatorColumn" type="com.bstek.dorado.view.widget.grid.IndicatorColumn" icon="/com/bstek/dorado/view/widget/grid/IndicatorColumn.png"></Rule><Rule name="ColumnGroup" parents="Column" label="ColumnGroup" type="com.bstek.dorado.view.widget.grid.ColumnGroup" icon="/com/bstek/dorado/view/widget/grid/ColumnGroup.png"><Props>
<Prop name="align" enumValues="left,center,right" visible="false"/></Props><Children><Child rule="Column" name="Columns" aggregated="true"></Child></Children></Rule><Rule name="DataColumn" parents="AbstractDataColumn" label="DataColumn" type="com.bstek.dorado.view.widget.grid.DataColumn" icon="/com/bstek/dorado/view/widget/grid/DataColumn.png" labelProperty="name,property"><Props>
<Prop name="align" enumValues="left,center,right"/>
<Prop name="dataType" type="com.bstek.dorado.data.type.DataType"/>
<Prop name="defaultFilterOperator"/>
@@ -1033,8 +1034,7 @@
<Prop name="summaryType" enumValues="sum,average,count,max,min"/>
<Prop name="trigger" enumValues="triggerClear,autoMappingDropDown1,autoMappingDropDown2,autoOpenMappingDropDown1,autoOpenMappingDropDown2,defaultDateDropDown,defaultDateTimeDropDown,defaultYearMonthDropDown,defaultYearDropDown,defaultMonthDropDown" reference="Trigger:id"/>
<Prop name="typeFormat"/>
<Prop name="wrappable" type="boolean"/></Props><Children><Child name="Editor" fixed="true"><Rule name="Wrapper.Editor" label="Editor" nodeName="Editor" icon="/com/bstek/dorado/view/widget/grid/Editor.png"><Children><Child rule="com.bstek.dorado.view.widget.Control" name="Editor"></Child></Children></Rule></Child></Children></Rule><Rule name="ColumnGroup" parents="Column" label="ColumnGroup" type="com.bstek.dorado.view.widget.grid.ColumnGroup" icon="/com/bstek/dorado/view/widget/grid/ColumnGroup.png"><Props>
<Prop name="align" enumValues="left,center,right" visible="false"/></Props><Children><Child rule="Column" name="Columns" aggregated="true"></Child></Children></Rule><Rule name="RowNumColumn" parents="AbstractDataColumn" label="RowNumColumn" type="com.bstek.dorado.view.widget.grid.RowNumColumn" icon="/com/bstek/dorado/view/widget/grid/RowNumColumn.png"></Rule><Rule name="RowSelectorColumn" parents="AbstractDataColumn" label="RowSelectorColumn" type="com.bstek.dorado.view.widget.grid.RowSelectorColumn" icon="/com/bstek/dorado/view/widget/grid/RowSelectorColumn.png"></Rule><Rule name="IndicatorColumn" parents="AbstractDataColumn" label="IndicatorColumn" type="com.bstek.dorado.view.widget.grid.IndicatorColumn" icon="/com/bstek/dorado/view/widget/grid/IndicatorColumn.png"></Rule><Rule name="AbstractList" parents="com.bstek.dorado.view.widget.Control" abstract="true" type="com.bstek.dorado.view.widget.list.AbstractList" scope="protected" clientTypes="desktop"><Props>
<Prop name="wrappable" type="boolean"/></Props><Children><Child name="Editor" fixed="true"><Rule name="Wrapper.Editor" label="Editor" nodeName="Editor" icon="/com/bstek/dorado/view/widget/grid/Editor.png"><Children><Child rule="com.bstek.dorado.view.widget.Control" name="Editor"></Child></Children></Rule></Child></Children></Rule><Rule name="RowSelectorColumn" parents="AbstractDataColumn" label="RowSelectorColumn" type="com.bstek.dorado.view.widget.grid.RowSelectorColumn" icon="/com/bstek/dorado/view/widget/grid/RowSelectorColumn.png"></Rule><Rule name="AbstractList" parents="com.bstek.dorado.view.widget.Control" abstract="true" type="com.bstek.dorado.view.widget.list.AbstractList" scope="protected" clientTypes="desktop"><Props>
<Prop name="allowNoCurrent" type="boolean"/>
<Prop name="dragMode" defaultValue="item" enumValues="item,control,itemOrControl"/>
<Prop name="dropMode" defaultValue="insertItems" enumValues="onControl,onItem,insertItems,onOrInsertItems,onAnyWhere"/>