Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public class DigiplexBindingConstants {
public static final String BRIDGE_MESSAGES_SENT = "statistics#messages_sent";
public static final String BRIDGE_RESPONSES_RECEIVED = "statistics#responses_received";
public static final String BRIDGE_EVENTS_RECEIVED = "statistics#events_received";

public static final String BRIDGE_TLM_TROUBLE = "troubles#tlm_trouble";
public static final String BRIDGE_AC_FAILURE = "troubles#ac_failure";
public static final String BRIDGE_BATTERY_FAILURE = "troubles#battery_failure";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ default void handleArmDisarmAreaResponse(AreaArmDisarmResponse response) {
default void handleUnknownResponse(UnknownResponse response) {
}

default void handleErroneousResponse(ErroneousResponse response) {
}

// Events
default void handleZoneEvent(ZoneEvent event) {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.digiplex.internal.communication;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.digiplex.internal.communication.events.AreaEvent;
import org.openhab.binding.digiplex.internal.communication.events.AreaEventType;
import org.openhab.binding.digiplex.internal.communication.events.GenericEvent;
Expand All @@ -29,21 +30,19 @@
* Resolves serial messages to appropriate classes
*
* @author Robert Michalak - Initial contribution
*
*/
@NonNullByDefault
public class DigiplexResponseResolver {

private static final String OK = "&ok";
// TODO: handle failures
private static final String FAIL = "&fail";

public static DigiplexResponse resolveResponse(String message) {
if (message.length() < 4) { // sanity check: try to filter out malformed responses
return new UnknownResponse(message);
return new ErroneousResponse(message);
}

int zoneNo, areaNo;
Integer zoneNo, areaNo;
String commandType = message.substring(0, 2);
switch (commandType) {
case "CO": // communication status
Expand All @@ -53,24 +52,36 @@ public static DigiplexResponse resolveResponse(String message) {
return CommunicationStatus.OK;
}
case "ZL": // zone label
zoneNo = Integer.valueOf(message.substring(2, 5));
zoneNo = getZoneOrArea(message);
if (zoneNo == null) {
return new ErroneousResponse(message);
}
if (message.contains(FAIL)) {
return ZoneLabelResponse.failure(zoneNo);
} else {
return ZoneLabelResponse.success(zoneNo, message.substring(5).trim());
}
case "AL": // area label
areaNo = Integer.valueOf(message.substring(2, 5));
areaNo = getZoneOrArea(message);
if (areaNo == null) {
return new ErroneousResponse(message);
}
if (message.contains(FAIL)) {
return AreaLabelResponse.failure(areaNo);
} else {
return AreaLabelResponse.success(areaNo, message.substring(5).trim());
}
case "RZ": // zone status
zoneNo = Integer.valueOf(message.substring(2, 5));
zoneNo = getZoneOrArea(message);
if (zoneNo == null) {
return new ErroneousResponse(message);
}
if (message.contains(FAIL)) {
return ZoneStatusResponse.failure(zoneNo);
} else {
if (message.length() < 10) {
return new ErroneousResponse(message);
}
return ZoneStatusResponse.success(zoneNo, // zone number
ZoneStatus.fromMessage(message.charAt(5)), // status
toBoolean(message.charAt(6)), // alarm
Expand All @@ -79,10 +90,16 @@ public static DigiplexResponse resolveResponse(String message) {
toBoolean(message.charAt(9))); // battery low
}
case "RA": // area status
areaNo = Integer.valueOf(message.substring(2, 5));
areaNo = getZoneOrArea(message);
if (areaNo == null) {
return new ErroneousResponse(message);
}
if (message.contains(FAIL)) {
return AreaStatusResponse.failure(areaNo);
} else {
if (message.length() < 12) {
return new ErroneousResponse(message);
}
return AreaStatusResponse.success(areaNo, // zone number
AreaStatus.fromMessage(message.charAt(5)), // status
toBoolean(message.charAt(6)), // zone in memory
Expand All @@ -95,7 +112,10 @@ public static DigiplexResponse resolveResponse(String message) {
case "AA": // area arm
case "AQ": // area quick arm
case "AD": // area disarm
areaNo = Integer.valueOf(message.substring(2, 5));
areaNo = getZoneOrArea(message);
if (areaNo == null) {
return new ErroneousResponse(message);
}
if (message.contains(FAIL)) {
return AreaArmDisarmResponse.failure(areaNo, ArmDisarmType.fromMessage(commandType));
} else {
Expand All @@ -105,21 +125,41 @@ public static DigiplexResponse resolveResponse(String message) {
case "PG": // PGM events
default:
if (message.startsWith("G")) {
return resolveSystemEvent(message);
if (message.length() >= 12) {
return resolveSystemEvent(message);
} else {
return new ErroneousResponse(message);
}
} else {
return new UnknownResponse(message);
}
}
}

private static @Nullable Integer getZoneOrArea(String message) {
if (message.length() < 5) {
return null;
}
try {
return Integer.valueOf(message.substring(2, 5));
} catch (NumberFormatException e) {
return null;
}
}

private static boolean toBoolean(char value) {
return value != 'O';
}

private static DigiplexResponse resolveSystemEvent(String message) {
int eventGroup = Integer.parseInt(message.substring(1, 4));
int eventNumber = Integer.parseInt(message.substring(5, 8));
int areaNumber = Integer.parseInt(message.substring(9, 12));
int eventGroup, eventNumber, areaNumber;
try {
eventGroup = Integer.parseInt(message.substring(1, 4));
eventNumber = Integer.parseInt(message.substring(5, 8));
areaNumber = Integer.parseInt(message.substring(9, 12));
} catch (NumberFormatException e) {
return new ErroneousResponse(message);
}
switch (eventGroup) {
case 0:
return new ZoneStatusEvent(eventNumber, ZoneStatus.CLOSED, areaNumber);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2025 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.digiplex.internal.communication;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* Erroneous message from PRT3.
*
* Message that is invalid, which happens sometimes due to communication errors.
*
* @author Robert Michalak - Initial contribution
*
*/
@NonNullByDefault
public class ErroneousResponse implements DigiplexResponse {

public final String message;

public ErroneousResponse(String message) {
this.message = message;
}

@Override
public void accept(DigiplexMessageHandler visitor) {
visitor.handleErroneousResponse(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* Unknown message from PRT3
* Unknown message from PRT3.
*
* Message that is otherwise valid, but not handled in this binding.
*
* @author Robert Michalak - Initial contribution
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.openhab.binding.digiplex.internal.communication.DigiplexRequest;
import org.openhab.binding.digiplex.internal.communication.DigiplexResponse;
import org.openhab.binding.digiplex.internal.communication.DigiplexResponseResolver;
import org.openhab.binding.digiplex.internal.communication.ErroneousResponse;
import org.openhab.binding.digiplex.internal.communication.events.AbstractEvent;
import org.openhab.binding.digiplex.internal.communication.events.TroubleEvent;
import org.openhab.binding.digiplex.internal.communication.events.TroubleStatus;
Expand Down Expand Up @@ -295,6 +296,12 @@ public void handleTroubleEvent(TroubleEvent troubleEvent) {
updateState(channel, state);
}
}

@Override
public void handleErroneousResponse(ErroneousResponse response) {
logger.debug("Erroneous response: {}", response.message);
handleCommunicationError();
}
}

private class DigiplexReceiverThread extends Thread {
Expand Down
Loading