Search in sources :

Example 1 with KnxDatapointType

use of org.apache.plc4x.java.knxnetip.readwrite.KnxDatapointType in project plc4x by apache.

the class Ets5Parser method parse.

public Ets5Model parse(File knxprojFile, String password) {
    try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
        DocumentBuilder builder = factory.newDocumentBuilder();
        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();
        try (ZipFile zipFile = new ZipFile(knxprojFile)) {
            // //////////////////////////////////////////////////////////////////////////////
            // File containing the information on the type of encoding used for group addresses.
            // //////////////////////////////////////////////////////////////////////////////
            Document projectHeaderDoc;
            Document projectDoc;
            String projectNumber = this.getProjectNumber(zipFile);
            FileHeader projectFileHeader = zipFile.getFileHeader(projectNumber + "/project.xml");
            if (projectFileHeader == null) {
                // This is the case of a knxproj file which is password-protected
                final FileHeader encryptedProjectFileHeader = zipFile.getFileHeader(projectNumber + ".zip");
                if (encryptedProjectFileHeader == null) {
                    throw new PlcRuntimeException(String.format("Error accessing project header file. Project file '%s/project.xml' and '%s.zip' don't exist.", projectNumber, projectNumber));
                }
                // Dump the encrypted zip to a temp file.
                Path tempDir = Files.createTempDirectory(null);
                zipFile.extractFile(projectNumber + ".zip", tempDir.toFile().getAbsolutePath());
                File tempFile = new File(tempDir.toFile(), projectNumber + ".zip");
                // Unzip the archive inside the archive.
                try (ZipFile projectZipFile = new ZipFile(tempFile, password.toCharArray())) {
                    final FileHeader compressedProjectFileHeader = projectZipFile.getFileHeader("project.xml");
                    if (compressedProjectFileHeader == null) {
                        throw new PlcRuntimeException(String.format("Error accessing project header file: Project file 'project.xml' inside '%s.zip'.", projectNumber));
                    }
                    projectHeaderDoc = builder.parse(projectZipFile.getInputStream(compressedProjectFileHeader));
                    FileHeader projectFileFileHeader = projectZipFile.getFileHeader("0.xml");
                    if (projectFileFileHeader == null) {
                        throw new PlcRuntimeException("Error accessing project file.");
                    }
                    projectDoc = builder.parse(projectZipFile.getInputStream(projectFileFileHeader));
                }
            } else {
                projectHeaderDoc = builder.parse(zipFile.getInputStream(projectFileHeader));
                FileHeader projectFileFileHeader = zipFile.getFileHeader(projectNumber + "/0.xml");
                if (projectFileFileHeader == null) {
                    throw new PlcRuntimeException("Error accessing project file.");
                }
                projectDoc = builder.parse(zipFile.getInputStream(projectFileFileHeader));
            }
            final XPathExpression xpathGroupAddressStyle = xPath.compile("/KNX/Project/ProjectInformation/@GroupAddressStyle");
            Attr groupAddressStyle = (Attr) xpathGroupAddressStyle.evaluate(projectHeaderDoc, XPathConstants.NODE);
            byte groupAddressStyleCode = getGroupAddressLevel(groupAddressStyle.getTextContent());
            // //////////////////////////////////////////////////////////////////////////////
            // General information on the type of encoding and the value ranges.
            // //////////////////////////////////////////////////////////////////////////////
            FileHeader knxMasterDataFileFileHeader = zipFile.getFileHeader("knx_master.xml");
            if (knxMasterDataFileFileHeader == null) {
                throw new PlcRuntimeException("Error accessing KNX master file.");
            }
            Document knxMasterDoc = builder.parse(zipFile.getInputStream(knxMasterDataFileFileHeader));
            final XPathExpression xpathDatapointSubtype = xPath.compile("//DatapointSubtype");
            NodeList datapointSubtypeNodes = (NodeList) xpathDatapointSubtype.evaluate(knxMasterDoc, XPathConstants.NODESET);
            // Build an index of the internal data-types.
            Map<String, KnxDatapointType> knxDatapointTypeMap = new TreeMap<>();
            for (KnxDatapointType value : KnxDatapointType.values()) {
                knxDatapointTypeMap.put(value.getDatapointMainType().getNumber() + "#" + value.getNumber(), value);
            }
            Map<String, AddressType> addressTypes = new HashMap<>();
            for (int i = 0; i < datapointSubtypeNodes.getLength(); i++) {
                final Element datapointSubtypeNode = (Element) datapointSubtypeNodes.item(i);
                final String id = datapointSubtypeNode.getAttribute("Id");
                final int subType = Integer.parseInt(datapointSubtypeNode.getAttribute("Number"));
                final int mainType = Integer.parseInt(((Element) datapointSubtypeNode.getParentNode().getParentNode()).getAttribute("Number"));
                final String name = datapointSubtypeNode.getAttribute("Text");
                addressTypes.put(id, new AddressType(id, mainType, subType, name));
            }
            // //////////////////////////////////////////////////////////////////////////////
            // File containing all the information about group addresses used, their names, types etc.
            // //////////////////////////////////////////////////////////////////////////////
            final Map<String, String> topologyNames = new HashMap<>();
            final XPathExpression topology = xPath.compile("//Topology");
            final Element topologyElement = (Element) topology.evaluate(projectDoc, XPathConstants.NODE);
            final NodeList areas = topologyElement.getElementsByTagName("Area");
            for (int a = 0; a < areas.getLength(); a++) {
                final Element areaNode = (Element) areas.item(a);
                final String curAreaAddress = areaNode.getAttribute("Address");
                topologyNames.put(curAreaAddress, areaNode.getAttribute("Name"));
                final NodeList lines = areaNode.getElementsByTagName("Line");
                for (int l = 0; l < lines.getLength(); l++) {
                    final Element lineNode = (Element) lines.item(l);
                    final String curLineAddress = curAreaAddress + "/" + lineNode.getAttribute("Address");
                    topologyNames.put(curLineAddress, lineNode.getAttribute("Name"));
                }
            }
            final Map<String, Function> groupAddressRefs = new HashMap<>();
            final XPathExpression xpathGroupAddressRef = xPath.compile("//GroupAddressRef");
            NodeList groupAddressRefNodes = (NodeList) xpathGroupAddressRef.evaluate(projectDoc, XPathConstants.NODESET);
            for (int i = 0; i < groupAddressRefNodes.getLength(); i++) {
                final Element groupAddressRefNode = (Element) groupAddressRefNodes.item(i);
                final String refId = groupAddressRefNode.getAttribute("RefId");
                final Element functionNode = (Element) groupAddressRefNode.getParentNode();
                final String functionName = functionNode.getAttribute("Name");
                // Function Type information is stored in knx_master.xml (//FunctionType[@id='functionTypeId']
                final String functionTypeId = functionNode.getAttribute("Type");
                final Element spaceNode = (Element) functionNode.getParentNode();
                final String spaceName = spaceNode.getAttribute("Name");
                final Function function = new Function(refId, functionName, functionTypeId, spaceName);
                groupAddressRefs.put(refId, function);
            }
            final XPathExpression xpathGroupAddresses = xPath.compile("//GroupAddress");
            NodeList groupAddressNodes = (NodeList) xpathGroupAddresses.evaluate(projectDoc, XPathConstants.NODESET);
            Map<String, GroupAddress> groupAddresses = new HashMap<>();
            for (int i = 0; i < groupAddressNodes.getLength(); i++) {
                final Element groupAddressNode = (Element) groupAddressNodes.item(i);
                final String id = groupAddressNode.getAttribute("Id");
                final Function function = groupAddressRefs.get(id);
                final int addressInt = Integer.parseInt(groupAddressNode.getAttribute("Address"));
                final String knxGroupAddress = Ets5Model.parseGroupAddress(groupAddressStyleCode, addressInt);
                final String name = groupAddressNode.getAttribute("Name");
                final String typeString = groupAddressNode.getAttribute("DatapointType");
                final AddressType addressType = addressTypes.get(typeString);
                if (addressType != null) {
                    // Lookup the driver internal data-type.
                    final KnxDatapointType datapointType = knxDatapointTypeMap.get(addressType.getMainType() + "#" + addressType.getSubType());
                    GroupAddress groupAddress = new GroupAddress(knxGroupAddress, name, datapointType, function);
                    groupAddresses.put(knxGroupAddress, groupAddress);
                }
            }
            return new Ets5Model(groupAddressStyleCode, groupAddresses, topologyNames);
        }
    } catch (IOException | ParserConfigurationException | SAXException | XPathExpressionException e) {
        // Zip and Xml Stuff
        throw new PlcRuntimeException(e);
    }
}
Also used : DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) HashMap(java.util.HashMap) Element(org.w3c.dom.Element) Document(org.w3c.dom.Document) Attr(org.w3c.dom.Attr) SAXException(org.xml.sax.SAXException) Function(org.apache.plc4x.java.knxnetip.ets5.model.Function) GroupAddress(org.apache.plc4x.java.knxnetip.ets5.model.GroupAddress) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) FileHeader(net.lingala.zip4j.model.FileHeader) Path(java.nio.file.Path) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) KnxDatapointType(org.apache.plc4x.java.knxnetip.readwrite.KnxDatapointType) NodeList(org.w3c.dom.NodeList) IOException(java.io.IOException) TreeMap(java.util.TreeMap) Ets5Model(org.apache.plc4x.java.knxnetip.ets5.model.Ets5Model) ZipFile(net.lingala.zip4j.ZipFile) DocumentBuilder(javax.xml.parsers.DocumentBuilder) AddressType(org.apache.plc4x.java.knxnetip.ets5.model.AddressType) File(java.io.File) ZipFile(net.lingala.zip4j.ZipFile)

Aggregations

File (java.io.File)1 IOException (java.io.IOException)1 Path (java.nio.file.Path)1 HashMap (java.util.HashMap)1 TreeMap (java.util.TreeMap)1 DocumentBuilder (javax.xml.parsers.DocumentBuilder)1 DocumentBuilderFactory (javax.xml.parsers.DocumentBuilderFactory)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 ZipFile (net.lingala.zip4j.ZipFile)1 FileHeader (net.lingala.zip4j.model.FileHeader)1 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)1 AddressType (org.apache.plc4x.java.knxnetip.ets5.model.AddressType)1 Ets5Model (org.apache.plc4x.java.knxnetip.ets5.model.Ets5Model)1 Function (org.apache.plc4x.java.knxnetip.ets5.model.Function)1 GroupAddress (org.apache.plc4x.java.knxnetip.ets5.model.GroupAddress)1 KnxDatapointType (org.apache.plc4x.java.knxnetip.readwrite.KnxDatapointType)1 Attr (org.w3c.dom.Attr)1 Document (org.w3c.dom.Document)1 Element (org.w3c.dom.Element)1 NodeList (org.w3c.dom.NodeList)1