org.bidib.jbidibc.usbstickbasis.adapter.UsbStickBasisResponseFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jbidibc-usbstickbasis Show documentation
Show all versions of jbidibc-usbstickbasis Show documentation
jBiDiB jbidibc USB Stick Basis POM
package org.bidib.jbidibc.usbstickbasis.adapter;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.bidib.jbidibc.messages.AddressData;
import org.bidib.jbidibc.messages.BidibLibrary;
import org.bidib.jbidibc.messages.SoftwareVersion;
import org.bidib.jbidibc.messages.enums.AddressTypeEnum;
import org.bidib.jbidibc.messages.enums.CommandStationState;
import org.bidib.jbidibc.messages.enums.DynNumEnum;
import org.bidib.jbidibc.messages.enums.SpeedStepsEnum;
import org.bidib.jbidibc.messages.exception.ProtocolException;
import org.bidib.jbidibc.messages.message.BidibMessage;
import org.bidib.jbidibc.messages.message.CommandStationDriveStateResponse;
import org.bidib.jbidibc.messages.message.CommandStationStateResponse;
import org.bidib.jbidibc.messages.message.FeatureResponse;
import org.bidib.jbidibc.messages.message.FeedbackCvResponse;
import org.bidib.jbidibc.messages.message.FeedbackDynStateResponse;
import org.bidib.jbidibc.messages.message.FeedbackSpeedResponse;
import org.bidib.jbidibc.messages.message.ResponseFactory;
import org.bidib.jbidibc.messages.message.SysSwVersionResponse;
import org.bidib.jbidibc.messages.message.VendorResponse;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UsbStickBasisResponseFactory implements ResponseFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(UsbStickBasisResponseFactory.class);
private static final String PREFIX_POM_REPEAT = "POM repeat:";
private static final String PREFIX_CAR_RESPONSE = "Car->:";
private static final String PREFIX_CAR_REQUEST = "->Car:";
private final UsbStickBasisResponseInterface responseInterface;
private Pattern patternCarCvResponse;
private Pattern patternCarBatteryResponse;
private Pattern patternCarSpeedResponse;
private Pattern patternBasisCv;
private Pattern patternBasisStatus;
private Pattern patternSpeed;
private Pattern patternProductline;
private Pattern patternProductname;
private Pattern patternFirmwareVersion;
private Pattern patternCarSpeedstep;
private Pattern patternCarQueryCar;
// private Pattern patternCarQuerySpeed;
private Pattern patternPomRepeat;
private SelectedCar selectedCar;
public UsbStickBasisResponseFactory(final UsbStickBasisResponseInterface responseInterface) {
this.responseInterface = responseInterface;
this.selectedCar = responseInterface.getSelectedCarModel();
patternCarCvResponse = Pattern.compile(REGEX_PATTERN_CAR_CV_RESPONSE);
patternCarBatteryResponse = Pattern.compile(REGEX_PATTERN_CAR_BATTERY_RESPONSE);
patternCarSpeedResponse = Pattern.compile(REGEX_PATTERN_CAR_SPEED_RESPONSE);
patternBasisCv = Pattern.compile(REGEX_PATTERN_BASIS_CV);
patternBasisStatus = Pattern.compile(REGEX_PATTERN_BASIS_STATUS);
patternSpeed = Pattern.compile(REGEX_PATTERN_SPEED);
patternProductline = Pattern.compile(REGEX_PATTERN_PRODUCTLINE);
patternProductname = Pattern.compile(REGEX_PATTERN_PRODUCTNAME);
patternFirmwareVersion = Pattern.compile(REGEX_PATTERN_FIRMWAREVERSION);
patternCarSpeedstep = Pattern.compile(REGEX_PATTERN_CAR_SPEEDSTEP);
patternCarQueryCar = Pattern.compile(REGEX_PATTERN_CARQUERY_CAR);
// patternCarQuerySpeed = Pattern.compile(REGEX_PATTERN_CARQUERY_SPEED);
patternPomRepeat = Pattern.compile(REGEX_PATTERN_POMREPEAT);
}
@Override
public void initialize() {
}
@Override
public BidibMessage create(byte[] message) throws ProtocolException {
String line = new String(message, Charset.forName("UTF-8"));
LOGGER.info("Process the line: {}", line);
// @formatter:off
// write Basis CV 1 = 8[CRLF]
// Basis CV 1 = 8[CRLF]
// rf channel: 8
// set rf channel: 1
// set rf channel: 8
// Status: go
// set Status: Stop
// ->Car:3 FS: 0
// actual car address: 3 with speedstep: 0
// actual speedstep: 64
// put first! <<<<<---- no actual car
//
// ->Car:3 F0,F4-F1: 10000
// ->Car:3 F0-28 off
// ->Car:3 POM write CV1 ,3
// ->Car:3 POM read CV1
//
// Car->:3 Msg_Nr:1 CV1 = 3
//
// Car->:3 Msg_Nr:2 battery=100%
// Car->:3 Msg_Nr:3 speed=25km/h
// Car->:3 Msg_Nr:4 on position: 120
// Car->:3 Msg_Nr:5 CV1 = 3
//
// Speed: 10 mm/s, mean speed: 9 mm/s
// evaluate POM repeat
// POM repeat: 1
// @formatter:on
// if (line.startsWith(PREFIX_SET_COMMAND)) {
// LOGGER.info("Ignore the set command response: {}", line);
// return null;
// }
BidibMessage bidibMessage = null;
if (line.startsWith(PREFIX_CAR_RESPONSE)) {
// evaluate response from car
bidibMessage = parseCarResponse(line);
}
else if (line.startsWith(PREFIX_CAR_REQUEST)) {
// evaluate response message after send request to car
bidibMessage = parseCarRequestResponse(line);
}
else if (line.startsWith("actual")) {
// the message and response of the actual addressed car
bidibMessage = parseCarQueryResponse(line);
}
else if (line.startsWith("Status") || line.startsWith("set Status")) {
// the answer of the basis status
bidibMessage = parseBasisResponse(line);
}
else if (line.startsWith("Basis") || line.startsWith("write Basis")) {
// the answer of the basis CV
bidibMessage = parseBasisCvResponse(line);
}
else if (line.startsWith("Speed:")) {
// the speed message from the Speedometer
bidibMessage = parseSpeedResponse(line);
}
else if (line.startsWith("OpenCarSystem")) {
// the speed message from the Speedometer
bidibMessage = parseHelpResponse(line);
}
else if (line.startsWith(PREFIX_POM_REPEAT)) {
// POM repeat
bidibMessage = parsePomRepeatResponse(line);
}
else if (line.startsWith("OK")) {
// the speed message from the Speedometer
bidibMessage = parseOkResponse(line);
}
LOGGER.info("Created bidibMessage: {}", bidibMessage);
return bidibMessage;
}
private static final String REGEX_PATTERN_CAR_CV_RESPONSE = "Car->:(\\d+) Msg_Nr\\:(\\d+) CV(\\d+) = (.+)";
private static final String REGEX_PATTERN_CAR_BATTERY_RESPONSE = "Car->:(\\d+) Msg_Nr\\:(\\d+) battery=(\\d+)\\%";
private static final String REGEX_PATTERN_CAR_SPEED_RESPONSE = "Car->:(\\d+) Msg_Nr\\:(\\d+) speed=(\\d+)km/h";
private final byte[] ROOT_ADDR = new byte[] { 0 };
protected BidibMessage parseCarResponse(String line) throws ProtocolException {
// @formatter:off
// Car->:3 Msg_Nr:1 CV1 = 3
//
// Car->:3 Msg_Nr:2 battery=100%
// Car->:3 Msg_Nr:3 speed=25km/h
// Car->:3 Msg_Nr:4 on position: 120
// Car->:3 Msg_Nr:5 CV1 = 3
// @formatter:on
LOGGER.info("parseCarResponse, line: {}", line);
BidibMessage bidibMessage = null;
Matcher m = patternCarCvResponse.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String addr = m.group(1);
String msgNum = m.group(2);
String cvNum = m.group(3);
String cvValue = m.group(4);
LOGGER.info("Current addr: {}, msgNum: {}, cvNum: {}, cvValue: {}", addr, msgNum, cvNum, cvValue);
try {
int cvNumVal = Integer.parseInt(cvNum) - 1;
bidibMessage =
new FeedbackCvResponse(ROOT_ADDR, Integer.parseInt(msgNum), Integer.parseInt(addr), cvNumVal,
Integer.parseInt(cvValue));
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackCvResponse failed, response: {}", line, ex);
throw new ProtocolException("Create FeedbackCvResponse failed, line: " + line);
}
return bidibMessage;
}
m = patternCarBatteryResponse.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String addr = m.group(1);
String msgNum = m.group(2);
String batteryPercentage = m.group(3);
LOGGER.info("Current addr: {}, msgNum: {}, batteryPercentage: {}", addr, msgNum, batteryPercentage);
try {
AddressData addressData = new AddressData(Integer.parseInt(addr), AddressTypeEnum.LOCOMOTIVE_FORWARD);
int detectorNum = 0;
bidibMessage =
new FeedbackDynStateResponse(ROOT_ADDR, Integer.parseInt(msgNum), detectorNum, addressData,
DynNumEnum.DYN_STATE_NUM_CONTAINER_1.getType(),
ByteUtils.getLowByte(Integer.parseInt(batteryPercentage)));
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackDynStateResponse failed, response: {}", line, ex);
throw new ProtocolException("Create FeedbackDynStateResponse failed, line: " + line);
}
return bidibMessage;
}
m = patternCarSpeedResponse.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String carAddress = m.group(1);
String msgNum = m.group(2);
String carSpeed = m.group(3);
LOGGER.info("Current carAddress: {}, msgNum: {}, carSpeed: {}", carAddress, msgNum, carSpeed);
LOGGER.info("Create speed response from car speed message: {}", carSpeed);
try {
bidibMessage =
new FeedbackSpeedResponse(ROOT_ADDR, 0, Integer.parseInt(carAddress), Integer.parseInt(carSpeed));
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackSpeedResponse failed, response: {}", line, ex);
throw new ProtocolException("Create FeedbackSpeedResponse failed, line: " + line);
}
return bidibMessage;
}
return bidibMessage;
}
private static final String REGEX_PATTERN_CAR_SPEEDSTEP = "^->Car:(\\d+) FS: (\\d+)";
protected BidibMessage parseCarRequestResponse(String line) throws ProtocolException {
LOGGER.info("parseCarRequestResponse, line: {}", line);
// @formatter:off
// ->Car:3 FS: 0
// ->Car:3 F0,F4-F1: 10000
// ->Car:3 F0-28 off
// ->Car:3 POM write CV1 ,3
// ->Car:3 POM read CV1
// @formatter:on
BidibMessage bidibMessage = null;
Matcher m = patternCarCvResponse.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String addr = m.group(1);
String msgNum = m.group(2);
String cvNum = m.group(3);
String cvValue = m.group(4);
LOGGER.info("Current addr: {}, msgNum: {}, cvNum: {}, cvValue: {}", addr, msgNum, cvNum, cvValue);
try {
int cvNumVal = Integer.parseInt(cvNum) - 1;
bidibMessage =
new FeedbackCvResponse(ROOT_ADDR, Integer.parseInt(msgNum), Integer.parseInt(addr), cvNumVal,
Integer.parseInt(cvValue));
return bidibMessage;
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackCvResponse failed, response: {}", line, ex);
throw new ProtocolException("Create FeedbackCvResponse failed, line: " + line);
}
}
else {
LOGGER.trace("The provided line does not match the CarCV response pattern: {}", line);
}
m = patternCarSpeedstep.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String carAddress = null;
String carSpeed = null;
try {
carAddress = m.group(1);
carSpeed = m.group(2);
LOGGER.info("Parsed car address: {}, speed: {}", carAddress, carSpeed);
LOGGER.info("Create speed response from car speed steps message: {}", carSpeed);
// we should not provide the speed message if the measurement is active
if (selectedCar.getScale() == null) {
bidibMessage =
new FeedbackSpeedResponse(ROOT_ADDR, 0, Integer.parseInt(carAddress),
Integer.parseInt(carSpeed));
return bidibMessage;
}
else {
LOGGER.info("Skip provide SPEED response from car speed message because measurement is active.");
}
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackSpeedResponse failed, CV num: {}, CV value: {}", carAddress, carSpeed, ex);
throw new ProtocolException("Create FeedbackSpeedResponse failed, line: " + line);
}
}
else {
LOGGER.trace("The provided line does not match the car speed step pattern: {}", line);
}
return bidibMessage;
}
private static final String REGEX_PATTERN_CARQUERY_CAR = "^actual car address: (\\d+) with speedstep: (\\d+)";
// private static final String REGEX_PATTERN_CARQUERY_SPEED = "^actual speedstep: (\\d+)";
protected BidibMessage parseCarQueryResponse(String line) throws ProtocolException {
LOGGER.info("parseCarQueryResponse, line: {}", line);
// @formatter:off
// actual car address: 3 with speedstep: 0
// actual speedstep: 64
// @formatter:on
BidibMessage bidibMessage = null;
Matcher m = patternCarQueryCar.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String carAddress = null;
String carSpeed = null;
try {
carAddress = m.group(1);
carSpeed = m.group(2);
LOGGER.info("Parsed car address: {}, speed: {}", carAddress, carSpeed);
org.bidib.jbidibc.messages.AddressData addressData =
new AddressData(Integer.parseInt(carAddress), AddressTypeEnum.LOCOMOTIVE_FORWARD);
byte[] functions = new byte[] { 0x00, 0x00, 0x00, 0x00 };
bidibMessage =
new CommandStationDriveStateResponse(ROOT_ADDR, 0, 0x41, addressData, SpeedStepsEnum.DCC128,
Integer.parseInt(carSpeed), functions);
}
catch (Exception ex) {
LOGGER
.warn("Create CommandStationStateResponse failed, CV num: {}, CV value: {}", carAddress, carSpeed,
ex);
throw new ProtocolException("Create CommandStationStateResponse failed, line: " + line);
}
}
return bidibMessage;
}
private static final String REGEX_PATTERN_BASIS_CV = "^(write Basis|Basis) CV(\\d+) = (\\d+)";
protected BidibMessage parseBasisCvResponse(String line) throws ProtocolException {
LOGGER.info("parseBasisCvResponse, parse line: {}", line);
// @formatter:off
// write Basis CV 1 = 8[CRLF]
// Basis CV 1 = 8[CRLF]
// @formatter:on
BidibMessage bidibMessage = null;
Matcher m = patternBasisCv.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String basisCvNum = null;
String basisCvValue = null;
try {
basisCvNum = m.group(2);
basisCvValue = m.group(3);
LOGGER.info("Parsed CV num: {}, CV value: {}", basisCvNum, basisCvValue);
bidibMessage = new VendorResponse(ROOT_ADDR, 0, basisCvNum, basisCvValue);
}
catch (Exception ex) {
LOGGER
.warn("Create CommandStationStateResponse failed, CV num: {}, CV value: {}", basisCvNum,
basisCvValue, ex);
throw new ProtocolException("Create CommandStationStateResponse failed, line: " + line);
}
}
else {
LOGGER.info("No match found: {}", line);
}
return bidibMessage;
}
public static final String REGEX_PATTERN_BASIS_STATUS = "^Status\\: (\\S+)";
public static final String REGEX_PATTERN_BASIS_SET_STATUS = "^set Status\\: (\\S+)";
protected BidibMessage parseBasisResponse(String line) throws ProtocolException {
// @formatter:off
// write Basis CV 1 = 8[CRLF]
// Basis CV 1 = 8[CRLF]
// rf channel: 8
// Status: Go
// set Status: Stop
// @formatter:on
if (line.startsWith("set ")) {
line = line.substring(4);
}
BidibMessage bidibMessage = null;
Matcher m = patternBasisStatus.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
String basisStatus = m.group(1);
try {
CommandStationState state = null;
switch (basisStatus.toLowerCase()) {
case "go":
state = CommandStationState.GO;
break;
default:
state = CommandStationState.STOP;
break;
}
bidibMessage = new CommandStationStateResponse(ROOT_ADDR, 0, state.getType());
}
catch (Exception ex) {
LOGGER.warn("Create CommandStationStateResponse failed, basisStatus: {}", basisStatus, ex);
throw new ProtocolException("Create CommandStationStateResponse failed, line: " + line);
}
}
return bidibMessage;
}
private static final String REGEX_PATTERN_SPEED = "^Speed\\: (\\d+) mm/s, mean speed: (\\d+) mm/s";
protected BidibMessage parseSpeedResponse(String line) throws ProtocolException {
// @formatter:off
// Speed: 10 mm/s, mean speed: 9 mm/s
// @formatter:on
BidibMessage bidibMessage = null;
Matcher m = patternSpeed.matcher(line);
if (m.matches()) {
LOGGER.info("A matching line was found, m: {}", m);
try {
Integer decoderAddress = selectedCar.getDecoderAddress();
if (decoderAddress != null) {
// Integer scale = selectedCar.getScale();
// if (scale == null) {
// LOGGER.warn("No scale value available, assume 1:87");
// scale = 87;
// }
String currentSpeed = m.group(1);
String meanSpeed = m.group(2);
// mean speed in mm/s
int speedValue = Integer.parseInt(/* currentSpeed */ meanSpeed);
// int speedVal = 0;
// if (scale > 1) {
// speedVal = (int) (((double) speedValue * scale) / 277.778);
// }
// else {
// speedVal = speedValue;
// }
LOGGER
.info(
"Create speed response from speed message: {} mm/s, current speed: {} mm/s, meanSpeed: {} mm/s",
speedValue, currentSpeed, meanSpeed);
bidibMessage = new FeedbackSpeedResponse(ROOT_ADDR, 0, decoderAddress, speedValue);
}
else {
LOGGER.warn("Skip return speed response because no decoder address available.");
}
}
catch (Exception ex) {
LOGGER.warn("Create FeedbackSpeedResponse failed, line: {}", line, ex);
throw new ProtocolException("Create FeedbackSpeedResponse failed, line: " + line);
}
}
return bidibMessage;
}
private static final String REGEX_PATTERN_PRODUCTLINE = "^OpenCarSystem (USB-Basis|Car-Speedometer) V(\\d+).+$";
private static final String REGEX_PATTERN_PRODUCTNAME = "^OpenCarSystem (USB-Basis|Car-Speedometer)";
private static final String REGEX_PATTERN_FIRMWAREVERSION = "V(\\d+.*)$";
private BidibMessage parseHelpResponse(String line) throws ProtocolException {
LOGGER.info("Received answer: {}", line);
BidibMessage response = null;
String productLine = null;
Matcher m = patternProductline.matcher(line);
if (m.matches()) {
productLine = line;
LOGGER.info("Found matching result: {}", productLine);
}
if (StringUtils.isNotBlank(productLine)) {
// publish the product name
if (responseInterface != null) {
Matcher matcher = patternProductname.matcher(productLine);
if (matcher.find()) {
String productName = matcher.group();
LOGGER.info("Found productName: {}", productName);
responseInterface.publishProductName(productName);
}
}
// "V((?:(?:\d{1,2}\.){1,2})(?:\d{1,2}))"
Matcher matcher = patternFirmwareVersion.matcher(productLine);
if (matcher.find()) {
String firmwareVersion = matcher.group(1);
SoftwareVersion version = SoftwareVersion.parse(firmwareVersion);
response = new SysSwVersionResponse(ROOT_ADDR, 0, version.asByteArray());
}
}
else {
LOGGER.warn("Get the productName of the attached stick failed.");
}
return response;
}
private static final String REGEX_PATTERN_POMREPEAT = "^POM repeat: (\\d+)$";
protected BidibMessage parsePomRepeatResponse(String line) {
// POM repeat: 1
LOGGER.info("Parse POM repeat response: {}", line);
BidibMessage response = null;
if (StringUtils.isNotBlank(line)) {
// publish the feature POM repeat
if (responseInterface != null) {
Matcher matcher = patternPomRepeat.matcher(line);
if (matcher.find()) {
String pomRepeat = matcher.group(1);
LOGGER.info("Found pomRepeat: {}", pomRepeat);
try {
int featureValuePomRepeat = Integer.parseInt(pomRepeat);
responseInterface.publishPomRepeat(featureValuePomRepeat);
LOGGER.info("Set the FEATURE_GEN_POM_REPEAT: {}", featureValuePomRepeat);
response =
new FeatureResponse(ROOT_ADDR, 0, BidibLibrary.FEATURE_GEN_POM_REPEAT,
featureValuePomRepeat);
}
catch (Exception ex) {
LOGGER.warn("Set the feature POM repeat failed.", ex);
}
}
}
}
return response;
}
private BidibMessage parseOkResponse(String line) {
LOGGER.info("Parse OK response.");
return null;
}
@Override
public BidibMessage createRaw(byte[] message) throws ProtocolException {
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy