Compare commits

..

4 Commits

Author SHA1 Message Date
lsiepel
4e88f48a71
[tacmi] Fix SAT errors (#18046)
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
2025-01-09 12:07:50 +01:00
Jacob Laursen
e69c44b85e
Disable another unstable test (#18069)
Related to #12474

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
2025-01-09 12:07:01 +01:00
Jacob Laursen
46d27b6fb5
Disable another unstable test (#18068)
Related to #12667

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
2025-01-09 12:06:30 +01:00
mlobstein
f6efa87fb2
[roku] Add End Time and Media Progress channels (#18059)
Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
2025-01-09 08:12:57 +01:00
11 changed files with 122 additions and 47 deletions

View File

@ -46,6 +46,8 @@ The following channels are available:
| playMode | String | The current playback mode ie: stop, play, pause (ReadOnly). | | playMode | String | The current playback mode ie: stop, play, pause (ReadOnly). |
| timeElapsed | Number:Time | The total number of seconds of playback time elapsed for the current playing title (ReadOnly). | | timeElapsed | Number:Time | The total number of seconds of playback time elapsed for the current playing title (ReadOnly). |
| timeTotal | Number:Time | The total length of the current playing title in seconds (ReadOnly). This data is not provided by all streaming apps. | | timeTotal | Number:Time | The total length of the current playing title in seconds (ReadOnly). This data is not provided by all streaming apps. |
| endTime | DateTime | The date/time when the currently playing media will end (ReadOnly). N/A if timeTotal is not provided by the current streaming app. |
| progress | Dimmer | The current progress [0-100%] of playing media (ReadOnly). N/A if timeTotal is not provided by the current streaming app. |
| activeChannel | String | A dropdown containing a list of available TV channels on the Roku TV. The channel currently tuned is automatically selected. The list updates every 10 minutes. | | activeChannel | String | A dropdown containing a list of available TV channels on the Roku TV. The channel currently tuned is automatically selected. The list updates every 10 minutes. |
| signalMode | String | The signal type of the current TV channel, ie: 1080i (ReadOnly). | | signalMode | String | The signal type of the current TV channel, ie: 1080i (ReadOnly). |
| signalQuality | Number:Dimensionless | The signal quality of the current TV channel, 0-100% (ReadOnly). | | signalQuality | Number:Dimensionless | The signal quality of the current TV channel, 0-100% (ReadOnly). |
@ -59,6 +61,7 @@ The following channels are available:
Some Notes: Some Notes:
- The values for `activeApp`, `activeAppName`, `playMode`, `timeElapsed`, `timeTotal`, `activeChannel`, `signalMode`, `signalQuality`, `channelName`, `programTitle`, `programDescription`, `programRating`, `power` & `powerState` refresh automatically per the configured `refresh` interval. - The values for `activeApp`, `activeAppName`, `playMode`, `timeElapsed`, `timeTotal`, `activeChannel`, `signalMode`, `signalQuality`, `channelName`, `programTitle`, `programDescription`, `programRating`, `power` & `powerState` refresh automatically per the configured `refresh` interval.
- The `endTime` and `progress` channels may not be accurate for some streaming apps especially 'live' streams where the `timeTotal` value constantly increases.
**List of available button commands for Roku streaming devices:** **List of available button commands for Roku streaming devices:**
@ -120,6 +123,8 @@ Player Player_Control "Control" { channel="roku:roku_
String Player_PlayMode "Status: [%s]" { channel="roku:roku_player:myplayer1:playMode" } String Player_PlayMode "Status: [%s]" { channel="roku:roku_player:myplayer1:playMode" }
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeElapsed" } Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeElapsed" }
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeTotal" } Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_player:myplayer1:timeTotal" }
DateTime Player_EndTime "End Time: [%1$tl:%1$tM %1$tp]" { channel="roku:roku_player:myplayer1:endTime" }
Dimmer Player_Progress "Progress [%.0f%%]" { channel="roku:roku_player:myplayer1:progress" }
// Roku TV items: // Roku TV items:
@ -132,6 +137,8 @@ Player Player_Control "Control" { channel="roku:rok
String Player_PlayMode "Status: [%s]" { channel="roku:roku_tv:mytv1:playMode" } String Player_PlayMode "Status: [%s]" { channel="roku:roku_tv:mytv1:playMode" }
Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeElapsed" } Number:Time Player_TimeElapsed "Elapsed Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeElapsed" }
Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeTotal" } Number:Time Player_TimeTotal "Total Time: [%d %unit%]" { channel="roku:roku_tv:mytv1:timeTotal" }
DateTime Player_EndTime "End Time: [%1$tl:%1$tM %1$tp]" { channel="roku:roku_tv:mytv1:endTime" }
Dimmer Player_Progress "Progress [%.0f%%]" { channel="roku:roku_tv:mytv1:progress" }
String Player_ActiveChannel "Current Channel: [%s]" { channel="roku:roku_tv:mytv1:activeChannel" } String Player_ActiveChannel "Current Channel: [%s]" { channel="roku:roku_tv:mytv1:activeChannel" }
String Player_SignalMode "Signal Mode: [%s]" { channel="roku:roku_tv:mytv1:signalMode" } String Player_SignalMode "Signal Mode: [%s]" { channel="roku:roku_tv:mytv1:signalMode" }
Number Player_SignalQuality "Signal Quality: [%d %%]" { channel="roku:roku_tv:mytv1:signalQuality" } Number Player_SignalQuality "Signal Quality: [%d %%]" { channel="roku:roku_tv:mytv1:signalQuality" }
@ -154,6 +161,8 @@ sitemap roku label="Roku" {
Text item=Player_PlayMode Text item=Player_PlayMode
Text item=Player_TimeElapsed icon="time" Text item=Player_TimeElapsed icon="time"
Text item=Player_TimeTotal icon="time" Text item=Player_TimeTotal icon="time"
Text item=Player_EndTime icon="time"
Slider item=Player_Progress icon="time"
// The following items apply to Roku TVs only // The following items apply to Roku TVs only
Switch item=Player_Power Switch item=Player_Power
Text item=Player_PowerState Text item=Player_PowerState

View File

@ -55,6 +55,8 @@ public class RokuBindingConstants {
public static final String PLAY_MODE = "playMode"; public static final String PLAY_MODE = "playMode";
public static final String TIME_ELAPSED = "timeElapsed"; public static final String TIME_ELAPSED = "timeElapsed";
public static final String TIME_TOTAL = "timeTotal"; public static final String TIME_TOTAL = "timeTotal";
public static final String END_TIME = "endTime";
public static final String PROGRESS = "progress";
public static final String ACTIVE_CHANNEL = "activeChannel"; public static final String ACTIVE_CHANNEL = "activeChannel";
public static final String SIGNAL_MODE = "signalMode"; public static final String SIGNAL_MODE = "signalMode";
public static final String SIGNAL_QUALITY = "signalQuality"; public static final String SIGNAL_QUALITY = "signalQuality";

View File

@ -14,6 +14,8 @@ package org.openhab.binding.roku.internal.handler;
import static org.openhab.binding.roku.internal.RokuBindingConstants.*; import static org.openhab.binding.roku.internal.RokuBindingConstants.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -34,8 +36,10 @@ import org.openhab.binding.roku.internal.dto.DeviceInfo;
import org.openhab.binding.roku.internal.dto.Player; import org.openhab.binding.roku.internal.dto.Player;
import org.openhab.binding.roku.internal.dto.TvChannel; import org.openhab.binding.roku.internal.dto.TvChannel;
import org.openhab.binding.roku.internal.dto.TvChannels.Channel; import org.openhab.binding.roku.internal.dto.TvChannels.Channel;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.NextPreviousType; import org.openhab.core.library.types.NextPreviousType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.PlayPauseType; import org.openhab.core.library.types.PlayPauseType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
@ -195,21 +199,32 @@ public class RokuHandler extends BaseThingHandler {
PLAY.equalsIgnoreCase(playerInfo.getState()) ? PlayPauseType.PLAY : PlayPauseType.PAUSE); PLAY.equalsIgnoreCase(playerInfo.getState()) ? PlayPauseType.PLAY : PlayPauseType.PAUSE);
// Remove non-numeric from string, ie: ' ms' // Remove non-numeric from string, ie: ' ms'
String position = playerInfo.getPosition().replaceAll(NON_DIGIT_PATTERN, EMPTY); final String positionStr = playerInfo.getPosition().replaceAll(NON_DIGIT_PATTERN, EMPTY);
if (!EMPTY.equals(position)) { int position = -1;
updateState(TIME_ELAPSED, if (!EMPTY.equals(positionStr)) {
new QuantityType<>(Integer.parseInt(position) / 1000, API_SECONDS_UNIT)); position = Integer.parseInt(positionStr) / 1000;
updateState(TIME_ELAPSED, new QuantityType<>(position, API_SECONDS_UNIT));
} else { } else {
updateState(TIME_ELAPSED, UnDefType.UNDEF); updateState(TIME_ELAPSED, UnDefType.UNDEF);
} }
String duration = playerInfo.getDuration().replaceAll(NON_DIGIT_PATTERN, EMPTY); final String durationStr = playerInfo.getDuration().replaceAll(NON_DIGIT_PATTERN, EMPTY);
if (!EMPTY.equals(duration)) { int duration = -1;
updateState(TIME_TOTAL, if (!EMPTY.equals(durationStr)) {
new QuantityType<>(Integer.parseInt(duration) / 1000, API_SECONDS_UNIT)); duration = Integer.parseInt(durationStr) / 1000;
updateState(TIME_TOTAL, new QuantityType<>(duration, API_SECONDS_UNIT));
} else { } else {
updateState(TIME_TOTAL, UnDefType.UNDEF); updateState(TIME_TOTAL, UnDefType.UNDEF);
} }
if (position >= 0 && duration > 0) {
updateState(END_TIME, new DateTimeType(Instant.now().plusSeconds(duration - position)));
updateState(PROGRESS,
new PercentType(BigDecimal.valueOf(Math.round(position / (double) duration * 100.0))));
} else {
updateState(END_TIME, UnDefType.UNDEF);
updateState(PROGRESS, UnDefType.UNDEF);
}
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
logger.debug("Unable to parse playerInfo integer value. Exception: {}", e.getMessage()); logger.debug("Unable to parse playerInfo integer value. Exception: {}", e.getMessage());
} catch (RokuLimitedModeException e) { } catch (RokuLimitedModeException e) {
@ -224,6 +239,8 @@ public class RokuHandler extends BaseThingHandler {
updateState(PLAY_MODE, UnDefType.UNDEF); updateState(PLAY_MODE, UnDefType.UNDEF);
updateState(TIME_ELAPSED, UnDefType.UNDEF); updateState(TIME_ELAPSED, UnDefType.UNDEF);
updateState(TIME_TOTAL, UnDefType.UNDEF); updateState(TIME_TOTAL, UnDefType.UNDEF);
updateState(END_TIME, UnDefType.UNDEF);
updateState(PROGRESS, UnDefType.UNDEF);
} }
if (thingTypeUID.equals(THING_TYPE_ROKU_TV) && tvActive) { if (thingTypeUID.equals(THING_TYPE_ROKU_TV) && tvActive) {

View File

@ -80,6 +80,8 @@ channel-type.roku.channelName.label = Channel Name
channel-type.roku.channelName.description = The Name of the Channel Currently Selected channel-type.roku.channelName.description = The Name of the Channel Currently Selected
channel-type.roku.control.label = Control channel-type.roku.control.label = Control
channel-type.roku.control.description = Control playback e.g. Play/Pause/Next/Previous channel-type.roku.control.description = Control playback e.g. Play/Pause/Next/Previous
channel-type.roku.endTime.label = End Time
channel-type.roku.endTime.description = The date/time when the currently playing media will end
channel-type.roku.playMode.label = Play Mode channel-type.roku.playMode.label = Play Mode
channel-type.roku.playMode.description = The Current Playback Mode channel-type.roku.playMode.description = The Current Playback Mode
channel-type.roku.powerState.label = Power State channel-type.roku.powerState.label = Power State
@ -93,6 +95,8 @@ channel-type.roku.programRating.label = Program Rating
channel-type.roku.programRating.description = The TV Parental Guideline Rating of the Current TV Program channel-type.roku.programRating.description = The TV Parental Guideline Rating of the Current TV Program
channel-type.roku.programTitle.label = Program Title channel-type.roku.programTitle.label = Program Title
channel-type.roku.programTitle.description = The Name of the Current TV Program channel-type.roku.programTitle.description = The Name of the Current TV Program
channel-type.roku.progress.label = Media Progress
channel-type.roku.progress.description = The current progress of playing media
channel-type.roku.signalMode.label = Signal Mode channel-type.roku.signalMode.label = Signal Mode
channel-type.roku.signalMode.description = The Signal Type of the Current TV Channel, ie: 1080i channel-type.roku.signalMode.description = The Signal Type of the Current TV Channel, ie: 1080i
channel-type.roku.signalQuality.label = Signal Quality channel-type.roku.signalQuality.label = Signal Quality

View File

@ -19,6 +19,8 @@
<channel id="playMode" typeId="playMode"/> <channel id="playMode" typeId="playMode"/>
<channel id="timeElapsed" typeId="timeElapsed"/> <channel id="timeElapsed" typeId="timeElapsed"/>
<channel id="timeTotal" typeId="timeTotal"/> <channel id="timeTotal" typeId="timeTotal"/>
<channel id="endTime" typeId="endTime"/>
<channel id="progress" typeId="progress"/>
</channels> </channels>
<properties> <properties>
@ -28,7 +30,7 @@
<property name="Serial Number">unknown</property> <property name="Serial Number">unknown</property>
<property name="Device Id">unknown</property> <property name="Device Id">unknown</property>
<property name="Software Version">unknown</property> <property name="Software Version">unknown</property>
<property name="thingTypeVersion">1</property> <property name="thingTypeVersion">2</property>
</properties> </properties>
<representation-property>uuid</representation-property> <representation-property>uuid</representation-property>
@ -52,6 +54,8 @@
<channel id="playMode" typeId="playMode"/> <channel id="playMode" typeId="playMode"/>
<channel id="timeElapsed" typeId="timeElapsed"/> <channel id="timeElapsed" typeId="timeElapsed"/>
<channel id="timeTotal" typeId="timeTotal"/> <channel id="timeTotal" typeId="timeTotal"/>
<channel id="endTime" typeId="endTime"/>
<channel id="progress" typeId="progress"/>
<channel id="activeChannel" typeId="activeChannel"/> <channel id="activeChannel" typeId="activeChannel"/>
<channel id="signalMode" typeId="signalMode"/> <channel id="signalMode" typeId="signalMode"/>
<channel id="signalQuality" typeId="signalQuality"/> <channel id="signalQuality" typeId="signalQuality"/>
@ -69,7 +73,7 @@
<property name="Serial Number">unknown</property> <property name="Serial Number">unknown</property>
<property name="Device Id">unknown</property> <property name="Device Id">unknown</property>
<property name="Software Version">unknown</property> <property name="Software Version">unknown</property>
<property name="thingTypeVersion">1</property> <property name="thingTypeVersion">2</property>
</properties> </properties>
<representation-property>uuid</representation-property> <representation-property>uuid</representation-property>
@ -185,6 +189,24 @@
<state readOnly="true" pattern="%d %unit%"/> <state readOnly="true" pattern="%d %unit%"/>
</channel-type> </channel-type>
<channel-type id="endTime">
<item-type>DateTime</item-type>
<label>End Time</label>
<description>The date/time when the currently playing media will end</description>
<category>Time</category>
<tags>
<tag>Status</tag>
<tag>Timestamp</tag>
</tags>
<state readOnly="true"/>
</channel-type>
<channel-type id="progress">
<item-type>Dimmer</item-type>
<label>Media Progress</label>
<description>The current progress of playing media</description>
</channel-type>
<channel-type id="activeChannel"> <channel-type id="activeChannel">
<item-type>String</item-type> <item-type>String</item-type>
<label>Active Channel</label> <label>Active Channel</label>

View File

@ -12,6 +12,15 @@
<type>roku:control</type> <type>roku:control</type>
</add-channel> </add-channel>
</instruction-set> </instruction-set>
<instruction-set targetVersion="2">
<add-channel id="endTime">
<type>roku:endTime</type>
</add-channel>
<add-channel id="progress">
<type>roku:progress</type>
</add-channel>
</instruction-set>
</thing-type> </thing-type>
<thing-type uid="roku:roku_tv"> <thing-type uid="roku:roku_tv">
@ -29,6 +38,15 @@
<type>roku:control</type> <type>roku:control</type>
</add-channel> </add-channel>
</instruction-set> </instruction-set>
<instruction-set targetVersion="2">
<add-channel id="endTime">
<type>roku:endTime</type>
</add-channel>
<add-channel id="progress">
<type>roku:progress</type>
</add-channel>
</instruction-set>
</thing-type> </thing-type>
</update:update-descriptions> </update:update-descriptions>

View File

@ -185,6 +185,7 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
} else if ("durchsichtig".equals(classFlag)) { // link } else if ("durchsichtig".equals(classFlag)) { // link
this.fieldType = FieldType.IGNORE; this.fieldType = FieldType.IGNORE;
} else if ("bord".equals(classFlag)) { // special button style - not of our interest... } else if ("bord".equals(classFlag)) { // special button style - not of our interest...
continue;
} else { } else {
logger.debug("Unhanndled class in {}:{}:{}: '{}' ", id, line, col, classFlag); logger.debug("Unhanndled class in {}:{}:{}: '{}' ", id, line, col, classFlag);
} }
@ -192,7 +193,7 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
} }
} else if (this.parserState == ParserState.DATA_ENTRY && this.fieldType == FieldType.BUTTON } else if (this.parserState == ParserState.DATA_ENTRY && this.fieldType == FieldType.BUTTON
&& "span".equals(elementName)) { && "span".equals(elementName)) {
// ignored... return; // ignored...
} else { } else {
logger.debug("Unexpected OpenElement in {}:{}: {} [{}]", line, col, elementName, attributes); logger.debug("Unexpected OpenElement in {}:{}: {} [{}]", line, col, elementName, attributes);
} }
@ -245,14 +246,14 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
getApiPageEntry(id, line, col, shortName, description, this.buttonValue); getApiPageEntry(id, line, col, shortName, description, this.buttonValue);
} }
} else if (this.fieldType == FieldType.IGNORE) { } else if (this.fieldType == FieldType.IGNORE) {
// ignore return; // ignore
} else { } else {
logger.debug("Unhandled setting {}:{}:{} [{}] : {}", id, line, col, this.fieldType, sb); logger.debug("Unhandled setting {}:{}:{} [{}] : {}", id, line, col, this.fieldType, sb);
} }
} }
} else if (this.parserState == ParserState.DATA_ENTRY && this.fieldType == FieldType.BUTTON } else if (this.parserState == ParserState.DATA_ENTRY && this.fieldType == FieldType.BUTTON
&& "span".equals(elementName)) { && "span".equals(elementName)) {
// ignored... return;// ignored...
} else { } else {
logger.debug("Unexpected CloseElement in {}:{}: {}", line, col, elementName); logger.debug("Unexpected CloseElement in {}:{}: {}", line, col, elementName);
} }
@ -307,7 +308,7 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
} }
} else if (this.parserState == ParserState.INIT && ((len == 1 && buffer[offset] == '\n') } else if (this.parserState == ParserState.INIT && ((len == 1 && buffer[offset] == '\n')
|| (len == 2 && buffer[offset] == '\r' && buffer[offset + 1] == '\n'))) { || (len == 2 && buffer[offset] == '\r' && buffer[offset + 1] == '\n'))) {
// single newline - ignore/drop it... return; // single newline - ignore/drop it...
} else { } else {
String msg = new String(buffer, offset, len).replace("\n", "\\n").replace("\r", "\\r"); String msg = new String(buffer, offset, len).replace("\n", "\\n").replace("\r", "\\r");
logger.debug("Unexpected Text {}:{}: ParserState: {} ({}) `{}`", line, col, parserState, len, msg); logger.debug("Unexpected Text {}:{}: ParserState: {} ({}) `{}`", line, col, parserState, len, msg);
@ -400,9 +401,9 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
// failed to get unit... // failed to get unit...
if ("Imp".equals(unitStr) || "€$".contains(unitStr)) { if ("Imp".equals(unitStr) || "€$".contains(unitStr)) {
// special case // special case
unitData = taCmiSchemaHandler.SPECIAL_MARKER; unitData = TACmiSchemaHandler.SPECIAL_MARKER;
} else { } else {
unitData = taCmiSchemaHandler.NULL_MARKER; unitData = TACmiSchemaHandler.NULL_MARKER;
logger.warn( logger.warn(
"Unhandled UoM '{}' - seen on channel {} '{}'; Message from QuantityType: {}", "Unhandled UoM '{}' - seen on channel {} '{}'; Message from QuantityType: {}",
valParts[1], shortName, description, iae.getMessage()); valParts[1], shortName, description, iae.getMessage());
@ -410,12 +411,12 @@ public class ApiPageParser extends AbstractSimpleMarkupHandler {
} }
taCmiSchemaHandler.unitsCache.put(unitStr, unitData); taCmiSchemaHandler.unitsCache.put(unitStr, unitData);
} }
if (unitData == taCmiSchemaHandler.NULL_MARKER) { if (unitData == TACmiSchemaHandler.NULL_MARKER) {
// no UoM mappable - just send value // no UoM mappable - just send value
channelType = "Number"; channelType = "Number";
unit = null; unit = null;
state = new DecimalType(bd); state = new DecimalType(bd);
} else if (unitData == taCmiSchemaHandler.SPECIAL_MARKER) { } else if (unitData == TACmiSchemaHandler.SPECIAL_MARKER) {
// special handling for unknown UoM // special handling for unknown UoM
if ("Imp".equals(unitStr)) { // Number of Pulses if ("Imp".equals(unitStr)) { // Number of Pulses
// impulses - no idea how to map this to something useful here? // impulses - no idea how to map this to something useful here?

View File

@ -102,7 +102,7 @@ public class ChangerX2Parser extends AbstractSimpleMarkupHandler {
this.optionFieldName = attributes == null ? null : attributes.get("name"); this.optionFieldName = attributes == null ? null : attributes.get("name");
} else if ((this.parserState == ParserState.INIT || this.parserState == ParserState.INPUT) } else if ((this.parserState == ParserState.INIT || this.parserState == ParserState.INPUT)
&& "br".equals(elementName)) { && "br".equals(elementName)) {
// ignored return; // ignored
} else if ((this.parserState == ParserState.INIT || this.parserState == ParserState.INPUT) } else if ((this.parserState == ParserState.INIT || this.parserState == ParserState.INPUT)
&& "input".equals(elementName) && "changeto".equals(id)) { && "input".equals(elementName) && "changeto".equals(id)) {
this.parserState = ParserState.INPUT_DATA; this.parserState = ParserState.INPUT_DATA;
@ -171,7 +171,6 @@ public class ChangerX2Parser extends AbstractSimpleMarkupHandler {
} }
this.options.put(ChangerX2Entry.TIME_PERIOD_PARTS, timeParts); this.options.put(ChangerX2Entry.TIME_PERIOD_PARTS, timeParts);
} else { } else {
logger.warn("Error parsing options for {}: Unhandled input field in {}:{}: {}", channelName, line, logger.warn("Error parsing options for {}: Unhandled input field in {}:{}: {}", channelName, line,
col, attributes); col, attributes);
} }
@ -218,7 +217,7 @@ public class ChangerX2Parser extends AbstractSimpleMarkupHandler {
} }
} }
} else if (this.parserState == ParserState.INPUT && "span".equals(elementName)) { } else if (this.parserState == ParserState.INPUT && "span".equals(elementName)) {
// span's are ignored... return; // span's are ignored...
} else { } else {
logger.debug("Error parsing options for {}: Unexpected CloseElement in {}:{}: {}", channelName, line, col, logger.debug("Error parsing options for {}: Unexpected CloseElement in {}:{}: {}", channelName, line, col,
elementName); elementName);
@ -275,10 +274,11 @@ public class ChangerX2Parser extends AbstractSimpleMarkupHandler {
sb.append(buffer, offset, len); sb.append(buffer, offset, len);
} }
} else if (this.parserState == ParserState.INIT && len == 1 && buffer[offset] == '\n') { } else if (this.parserState == ParserState.INIT && len == 1 && buffer[offset] == '\n') {
// single newline - ignore/drop it... return; // single newline - ignore/drop it...
} else if (this.parserState == ParserState.INPUT) { } else if (this.parserState == ParserState.INPUT) {
// this is a label next to the value input field - we currently have no use for it so // this is a label next to the value input field - we currently have no use for it so
// it's dropped... // it's dropped...
return;
} else { } else {
logger.debug("Error parsing options for {}: Unexpected Text {}:{}: (ctx: {} len: {}) '{}' ", logger.debug("Error parsing options for {}: Unexpected Text {}:{}: (ctx: {} len: {}) '{}' ",
this.channelName, line, col, this.parserState, len, new String(buffer, offset, len)); this.channelName, line, col, this.parserState, len, new String(buffer, offset, len));

View File

@ -90,9 +90,9 @@ public class TACmiSchemaHandler extends BaseThingHandler {
// this is the units lookup cache. // this is the units lookup cache.
protected final Map<String, UnitAndType> unitsCache = new ConcurrentHashMap<>(); protected final Map<String, UnitAndType> unitsCache = new ConcurrentHashMap<>();
// marks an entry with known un-resolveable unit // marks an entry with known un-resolveable unit
protected final UnitAndType NULL_MARKER = new UnitAndType(Units.ONE, ""); protected static final UnitAndType NULL_MARKER = new UnitAndType(Units.ONE, "");
// marks an entry with special handling - i.e. 'Imp' // marks an entry with special handling - i.e. 'Imp'
protected final UnitAndType SPECIAL_MARKER = new UnitAndType(Units.ONE, "s"); protected static final UnitAndType SPECIAL_MARKER = new UnitAndType(Units.ONE, "s");
public TACmiSchemaHandler(final Thing thing, final HttpClient httpClient, public TACmiSchemaHandler(final Thing thing, final HttpClient httpClient,
final TACmiChannelTypeProvider channelTypeProvider) { final TACmiChannelTypeProvider channelTypeProvider) {

View File

@ -165,6 +165,7 @@ public class HomieImplementationTest extends MqttOSGiTest {
"Connection " + homieConnection.getClientId() + " not retrieving all topics "); "Connection " + homieConnection.getClientId() + " not retrieving all topics ");
} }
@Disabled("https://github.com/openhab/openhab-addons/issues/12667")
@Test @Test
public void retrieveOneAttribute() throws Exception { public void retrieveOneAttribute() throws Exception {
WaitForTopicValue watcher = new WaitForTopicValue(homieConnection, DEVICE_TOPIC + "/$homie"); WaitForTopicValue watcher = new WaitForTopicValue(homieConnection, DEVICE_TOPIC + "/$homie");

View File

@ -107,6 +107,7 @@ public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
} }
@Test @Test
@Disabled("https://github.com/openhab/openhab-addons/issues/12474")
public void assertThatThingHandlesREFRESHCommand() public void assertThatThingHandlesREFRESHCommand()
throws MalformedURLException, URISyntaxException, ValidationException, IOException { throws MalformedURLException, URISyntaxException, ValidationException, IOException {
Command command = RefreshType.REFRESH; Command command = RefreshType.REFRESH;