Skip to content

Commit

Permalink
Merge branch 'feature/strip-crc' into 'master'
Browse files Browse the repository at this point in the history
CRC processing which works with long/short frames

See merge request openhab/wmbus!23
  • Loading branch information
Hanno - Felix Wagner committed Nov 16, 2020
2 parents ad0c901 + 383ea00 commit a92b888
Show file tree
Hide file tree
Showing 13 changed files with 421 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ build:
paths:
- org.openhab.binding.wmbus/target/*.jar
- org.openhab.binding.wmbus.tools/target/*.jar
image: maven:3.5-jdk-8
image: maven:3.6-jdk-8
26 changes: 26 additions & 0 deletions org.openhab.binding.wmbus.tools/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,32 @@
<type>pom</type>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,14 @@
*/
package org.openhab.binding.wmbus.tools;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingRegistry;
import org.eclipse.smarthome.core.util.HexUtils;
import org.openhab.binding.wmbus.WMBusBindingConstants;
import org.openhab.binding.wmbus.WMBusDevice;
import org.openhab.binding.wmbus.handler.WMBusAdapter;
import org.openhab.binding.wmbus.tools.processor.*;
import org.openmuc.jmbus.DecodingException;
import org.openmuc.jmbus.wireless.VirtualWMBusMessageHelper;
import org.openmuc.jmbus.wireless.WMBusMessage;
Expand All @@ -41,6 +28,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;

/**
* Very basic servlet which allows to send a test frame to deployed binding.
*
Expand Down Expand Up @@ -112,54 +109,32 @@ private void inject(WMBusAdapter adapter, String frames, HttpServletRequest req,
boolean stripCRC = Optional.ofNullable(req.getParameter("stripCRC")).map(value -> Boolean.TRUE).orElse(false);
boolean calculateLength = Optional.ofNullable(req.getParameter("calculateLength")).map(value -> Boolean.TRUE)
.orElse(false);
boolean recalculateLength = Optional.ofNullable(req.getParameter("recalculateLength")).map(value -> Boolean.TRUE)
.orElse(false);

List<Processor<String>> processors = new ArrayList<>();
processors.add(new RssiProcessor(rssiIndex, rssiValue));
if (skipBytes > 0) {
processors.add(new SkipProcessor(skipBytes));
}
if (stripCRC) {
processors.add(new SkipCrcProcessor());
}
if (calculateLength) {
processors.add(new CalculateLength());
}
if (recalculateLength) {
processors.add(new RecalculateLength());
}

String[] frameArray = frames.split("\n");
try {
for (String frame : frameArray) {
frame = frame.trim().replace(" ", "");

int rssi = rssiValue;
if (rssiIndex != 0) {
if (rssiIndex == 1) {
rssi = Integer.parseUnsignedInt(frame.substring(0, 2), 16);
frame = frame.substring(2);
} else if (rssiIndex == -1) {
rssi = Integer.parseUnsignedInt(frame.substring(frame.length() -2), 16);
frame = frame.substring(0, frame.length() - 2);
}
}

if (skipBytes > 0) {
// one byte is 2 characters in hex representation
frame = frame.substring(skipBytes * 2);
}

if (stripCRC) {
String strippedframe = "";
strippedframe += frame.substring(Math.min(0, frame.length()), Math.min(18, frame.length()));
strippedframe += frame.substring(Math.min(22, frame.length()), Math.min(54, frame.length()));
strippedframe += frame.substring(Math.min(58, frame.length()), Math.min(90, frame.length()));
// String strippedframe = frame.substring(0, 18) + frame.substring(22, frame.length());
/*
* TODO: general implementation
*
*
* Integer position = 2;
* while (position < frame.length()) {
* strippedframe += frame.substring(position, position+16);
* position += 16 ;
* }
*/
frame = strippedframe;
}

if (calculateLength) {
// remember of hex notation which doubles length
Integer len = frame.length() / 2;
frame = Integer.toHexString(len) + frame;
}
// logger.debug("Seen frame:");
// logger.debug(frame);
Map<String, Object> context = new HashMap<>();
frame = Processors.process(frame, context, processors);
int rssi = (int) context.getOrDefault(Processor.RSSI, rssiValue);

byte[] bytes = HexUtils.hexToBytes(frame);
WMBusMessage message = VirtualWMBusMessageHelper.decode(bytes, rssi, Collections.emptyMap());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools;

import java.util.Map;

/**
* Generic purpose frame processor.
*
* @param <T> Type of frame representation.
*/
public interface Processor<T> {

String RSSI = "rssi";

T process(T frame, Map<String, Object> context);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools.processor;

import org.openhab.binding.wmbus.tools.Processor;

import java.util.Map;

public class CalculateLength implements Processor<String> {

@Override
public String process(String frame, Map<String, Object> context) {
// remember of hex notation which doubles length
Integer len = frame.length() / 2;
return Integer.toHexString(len) + frame;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools.processor;

import org.openhab.binding.wmbus.tools.Processor;

import java.util.List;
import java.util.Map;

/**
* Helper type to orchestrate execution of several frame processors at once.
*
* @author Łukasz Dywicki - Initial contribution.
*/
public class Processors {

public static <T> T process(final T value, Map<String, Object> context, List<Processor<T>> processors) {
if (processors.isEmpty()) {
return value;
}

T result = value;
for (Processor<T> processor : processors) {
result = processor.process(result, context);
}

return result;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools.processor;

import org.openhab.binding.wmbus.tools.Processor;

import java.util.Map;

public class RecalculateLength implements Processor<String> {

@Override
public String process(String frame, Map<String, Object> context) {
int inputByteLength = frame.length() / 2;

String newFrame = "";
Integer numberOfBlocks;
int ciField = parseInt(frame, 20, 22);

if (ciField == 0x7A){
numberOfBlocks = (inputByteLength-14) / 16;
inputByteLength = 14 + numberOfBlocks*16;
newFrame += Integer.toHexString(inputByteLength);
newFrame += frame.substring(2, 26);
newFrame += Integer.toHexString(numberOfBlocks*16);
newFrame += frame.substring(28, (inputByteLength * 2) + 2);
return newFrame;
}

if (ciField == 0x72){
numberOfBlocks = (inputByteLength-22) / 16;
inputByteLength = 22 + numberOfBlocks*16;
newFrame += Integer.toHexString(inputByteLength);
newFrame += frame.substring(2, 42);
newFrame += Integer.toHexString(numberOfBlocks*16);
newFrame += frame.substring(44, (inputByteLength * 2) + 2);
return newFrame;
}

return newFrame;
}

private int parseInt(String frame, int startIndex, int endIndex) {
return Integer.parseInt(frame.substring(startIndex, endIndex), 16);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools.processor;

import org.openhab.binding.wmbus.tools.Processor;

import java.util.Map;

public class RssiProcessor implements Processor<String> {

private final int rssiIndex;
private final int rssiValue;

public RssiProcessor(int rssiIndex, int rssiValue) {
this.rssiIndex = rssiIndex;
this.rssiValue = rssiValue;
}

@Override
public String process(String frame, Map<String, Object> context) {
if (rssiIndex != 0) {
if (rssiIndex == 1) { // first byte starts from character at index 0.
context.put(RSSI, Integer.parseUnsignedInt(frame.substring(0, 2), 16));
return frame.substring(2);
} else if (rssiIndex == -1) {
context.put(RSSI, Integer.parseUnsignedInt(frame.substring(frame.length() -2), 16));
return frame.substring(0, frame.length() - 2);
}
}

context.put(RSSI, rssiValue);
return frame;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2010-2018 by the respective copyright holders.
* <p>
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.wmbus.tools.processor;

import org.openhab.binding.wmbus.tools.Processor;

import java.util.HashMap;
import java.util.Map;

public class SkipCrcProcessor implements Processor<String> {

@Override
public String process(String frame, Map<String, Object> context) {
String strippedframe = "";
int len = frame.length() / 2; // include all fields

//int lengthField = Integer.decode(frame.substring(0, 2));
int ciField = parseInt(frame, 22, 24);
boolean formatB = ciField == 0x72 || ciField == 0x7A;

if (formatB) {
strippedframe += frame.substring(0, Math.min(18, frame.length() - 4));
// block 1 + block 2 = 11 + ((16*n)+2) -- max 129 bytes
if (len <= 129) {
strippedframe += frame.substring(Math.min(22, frame.length()), frame.length() - 4);
}
// block 1 + block 2 + block 3= 11 + ((16*n)+2) + (16*n) -- bytes > 129
else {
strippedframe += frame.substring(22, 256);
strippedframe += frame.substring(Math.min(260, frame.length()), frame.length() - 4);
}
} else {
// assume that we starts counting from C-field
strippedframe += frame.substring(0, Math.min(18, frame.length()));
int position = 22;
while (position < frame.length()) {
strippedframe += frame.substring(position, Math.min(position + 32, frame.length()));
position += 36;
}
strippedframe = strippedframe.substring(0,strippedframe.length()-4);
}

return strippedframe;
}

private int parseInt(String frame, int startIndex, int endIndex) {
return Integer.parseInt(frame.substring(startIndex, endIndex), 16);
}

}
Loading

0 comments on commit a92b888

Please sign in to comment.