use of org.apache.plc4x.java.knxnetip.ets5.model.Function 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);
}
}
use of org.apache.plc4x.java.knxnetip.ets5.model.Function in project plc4x by apache.
the class KnxNetIpProtocolLogic method processCemiData.
protected void processCemiData(KnxAddress sourceAddress, byte[] destinationGroupAddress, byte firstByte, byte[] restBytes) throws ParseException {
// The first byte is actually just 6 bit long, but we'll treat it as a full one.
// So here we create a byte array containing the first and all the following bytes.
byte[] payload = new byte[1 + restBytes.length];
payload[0] = firstByte;
System.arraycopy(restBytes, 0, payload, 1, restBytes.length);
// Decode the group address depending on the project settings.
ReadBuffer addressBuffer = new ReadBufferByteBased(destinationGroupAddress);
final KnxGroupAddress knxGroupAddress = KnxGroupAddress.staticParse(addressBuffer, knxNetIpDriverContext.getGroupAddressType());
final String destinationAddress = toString(knxGroupAddress);
// If there is an ETS5 model provided, continue decoding the payload.
if (knxNetIpDriverContext.getEts5Model() != null) {
final Ets5Model ets5Model = knxNetIpDriverContext.getEts5Model();
final GroupAddress groupAddress = ets5Model.getGroupAddresses().get(destinationAddress);
final String areaName = ets5Model.getTopologyName(destinationAddress.substring(0, destinationAddress.indexOf('/')));
final String lineName = ets5Model.getTopologyName(destinationAddress.substring(0, destinationAddress.indexOf('/', destinationAddress.indexOf('/') + 1)));
if ((groupAddress != null) && (groupAddress.getType() != null)) {
LOGGER.trace(String.format("Message from: '%s' to: '%s'", toString(sourceAddress), destinationAddress));
// Parse the payload depending on the type of the group-address.
ReadBuffer rawDataReader = new ReadBufferByteBased(payload);
final PlcValue value = KnxDatapoint.staticParse(rawDataReader, groupAddress.getType());
// Assemble the plc4x return data-structure.
Map<String, PlcValue> dataPointMap = new HashMap<>();
dataPointMap.put("sourceAddress", new PlcSTRING(toString(sourceAddress)));
dataPointMap.put("targetAddress", new PlcSTRING(groupAddress.getGroupAddress()));
if (groupAddress.getFunction() != null) {
dataPointMap.put("location", new PlcSTRING(groupAddress.getFunction().getSpaceName()));
dataPointMap.put("function", new PlcSTRING(groupAddress.getFunction().getName()));
} else {
dataPointMap.put("location", null);
dataPointMap.put("function", null);
}
if (areaName != null) {
dataPointMap.put("area", new PlcSTRING(areaName));
}
if (lineName != null) {
dataPointMap.put("line", new PlcSTRING(lineName));
}
dataPointMap.put("description", new PlcSTRING(groupAddress.getName()));
dataPointMap.put("unitOfMeasurement", new PlcSTRING(groupAddress.getType().getName()));
dataPointMap.put("value", value);
final PlcStruct dataPoint = new PlcStruct(dataPointMap);
// Send the data-structure.
publishEvent(groupAddress, dataPoint);
} else {
LOGGER.warn(String.format("Message from: '%s' to unknown group address: '%s'%n payload: '%s'", toString(sourceAddress), destinationAddress, Hex.encodeHexString(payload)));
}
} else // Else just output the raw payload.
{
LOGGER.info(String.format("Raw Message: '%s' to: '%s'%n payload: '%s'", KnxNetIpProtocolLogic.toString(sourceAddress), destinationAddress, Hex.encodeHexString(payload)));
}
}
Aggregations