Skip to content

Commit 6be634c

Browse files
author
Ravi Nadahar
committed
Modify ItemEventFactory to convert DateTimeType states
DateTimeTypes with non-authoritative timezones are converted the the configured timezone (and made authoritative) before being posted on the event bus. Signed-off-by: Ravi Nadahar <nadahar@rediffmail.com>
1 parent 6e9bdea commit 6be634c

File tree

3 files changed

+649
-131
lines changed

3 files changed

+649
-131
lines changed

bundles/org.openhab.core/src/main/java/org/openhab/core/items/events/ItemEventFactory.java

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@
2525
import org.openhab.core.events.AbstractEventFactory;
2626
import org.openhab.core.events.Event;
2727
import org.openhab.core.events.EventFactory;
28+
import org.openhab.core.i18n.TimeZoneProvider;
2829
import org.openhab.core.items.Item;
2930
import org.openhab.core.items.dto.ItemDTO;
3031
import org.openhab.core.items.dto.ItemDTOMapper;
32+
import org.openhab.core.library.types.DateTimeType;
3133
import org.openhab.core.types.Command;
3234
import org.openhab.core.types.RefreshType;
3335
import org.openhab.core.types.State;
3436
import org.openhab.core.types.TimeSeries;
3537
import org.openhab.core.types.Type;
3638
import org.openhab.core.types.UnDefType;
39+
import org.osgi.service.component.annotations.Activate;
3740
import org.osgi.service.component.annotations.Component;
41+
import org.osgi.service.component.annotations.Reference;
3842

3943
/**
4044
* An {@link ItemEventFactory} is responsible for creating item event instances, e.g. {@link ItemCommandEvent}s and
@@ -71,14 +75,20 @@ public class ItemEventFactory extends AbstractEventFactory {
7175

7276
private static final String ITEM_UPDATED_EVENT_TOPIC = "openhab/items/{itemName}/updated";
7377

78+
private static final String DATE_TIME_TYPE_TYPE = "DateTime";
79+
80+
private final TimeZoneProvider timeZoneProvider;
81+
7482
/**
7583
* Constructs a new ItemEventFactory.
7684
*/
77-
public ItemEventFactory() {
85+
@Activate
86+
public ItemEventFactory(@Reference TimeZoneProvider timeZoneProvider) {
7887
super(Set.of(ItemCommandEvent.TYPE, ItemStateEvent.TYPE, ItemStatePredictedEvent.TYPE,
7988
ItemStateUpdatedEvent.TYPE, ItemStateChangedEvent.TYPE, ItemAddedEvent.TYPE, ItemUpdatedEvent.TYPE,
8089
ItemRemovedEvent.TYPE, GroupStateUpdatedEvent.TYPE, GroupItemStateChangedEvent.TYPE,
8190
ItemTimeSeriesEvent.TYPE, ItemTimeSeriesUpdatedEvent.TYPE));
91+
this.timeZoneProvider = timeZoneProvider;
8292
}
8393

8494
@Override
@@ -115,7 +125,7 @@ protected Event createEventByType(String eventType, String topic, String payload
115125
private Event createGroupStateUpdatedEvent(String topic, String payload) {
116126
String itemName = getItemName(topic);
117127
String memberName = getMemberName(topic);
118-
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
128+
ItemStateUpdatedEventPayloadBean bean = processPayload(payload, ItemStateUpdatedEventPayloadBean.class);
119129
State state = getState(bean.getType(), bean.getValue());
120130
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
121131
return new GroupStateUpdatedEvent(topic, payload, itemName, memberName, state, lastStateUpdate, null);
@@ -124,7 +134,7 @@ private Event createGroupStateUpdatedEvent(String topic, String payload) {
124134
private Event createGroupStateChangedEvent(String topic, String payload) {
125135
String itemName = getItemName(topic);
126136
String memberName = getMemberName(topic);
127-
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
137+
ItemStateChangedEventPayloadBean bean = processPayload(payload, ItemStateChangedEventPayloadBean.class);
128138
State state = getState(bean.getType(), bean.getValue());
129139
State oldState = getState(bean.getOldType(), bean.getOldValue());
130140
ZonedDateTime lastStateChange = bean.getLastStateChange();
@@ -135,36 +145,36 @@ private Event createGroupStateChangedEvent(String topic, String payload) {
135145

136146
private Event createCommandEvent(String topic, String payload, @Nullable String source) {
137147
String itemName = getItemName(topic);
138-
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
148+
ItemEventPayloadBean bean = processPayload(payload, ItemEventPayloadBean.class);
139149
Command command = parseType(bean.getType(), bean.getValue(), Command.class);
140150
return new ItemCommandEvent(topic, payload, itemName, command, source);
141151
}
142152

143153
private Event createStateEvent(String topic, String payload, @Nullable String source) {
144154
String itemName = getItemName(topic);
145-
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
155+
ItemEventPayloadBean bean = processPayload(payload, ItemEventPayloadBean.class);
146156
State state = getState(bean.getType(), bean.getValue());
147157
return new ItemStateEvent(topic, payload, itemName, state, source);
148158
}
149159

150160
private Event createStatePredictedEvent(String topic, String payload) {
151161
String itemName = getItemName(topic);
152-
ItemStatePredictedEventPayloadBean bean = deserializePayload(payload, ItemStatePredictedEventPayloadBean.class);
162+
ItemStatePredictedEventPayloadBean bean = processPayload(payload, ItemStatePredictedEventPayloadBean.class);
153163
State state = getState(bean.getPredictedType(), bean.getPredictedValue());
154164
return new ItemStatePredictedEvent(topic, payload, itemName, state, bean.isConfirmation());
155165
}
156166

157167
private Event createStateUpdatedEvent(String topic, String payload) {
158168
String itemName = getItemName(topic);
159-
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
169+
ItemStateUpdatedEventPayloadBean bean = processPayload(payload, ItemStateUpdatedEventPayloadBean.class);
160170
State state = getState(bean.getType(), bean.getValue());
161171
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
162172
return new ItemStateUpdatedEvent(topic, payload, itemName, state, lastStateUpdate, null);
163173
}
164174

165175
private Event createStateChangedEvent(String topic, String payload, @Nullable String source) {
166176
String itemName = getItemName(topic);
167-
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
177+
ItemStateChangedEventPayloadBean bean = processPayload(payload, ItemStateChangedEventPayloadBean.class);
168178
State state = getState(bean.getType(), bean.getValue());
169179
State oldState = getState(bean.getOldType(), bean.getOldValue());
170180
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
@@ -175,14 +185,14 @@ private Event createStateChangedEvent(String topic, String payload, @Nullable St
175185

176186
private Event createTimeSeriesEvent(String topic, String payload) {
177187
String itemName = getItemName(topic);
178-
ItemTimeSeriesEventPayloadBean bean = deserializePayload(payload, ItemTimeSeriesEventPayloadBean.class);
188+
ItemTimeSeriesEventPayloadBean bean = processPayload(payload, ItemTimeSeriesEventPayloadBean.class);
179189
TimeSeries timeSeries = bean.getTimeSeries();
180190
return new ItemTimeSeriesEvent(topic, payload, itemName, timeSeries, null);
181191
}
182192

183193
private Event createTimeSeriesUpdatedEvent(String topic, String payload) {
184194
String itemName = getItemName(topic);
185-
ItemTimeSeriesEventPayloadBean bean = deserializePayload(payload, ItemTimeSeriesEventPayloadBean.class);
195+
ItemTimeSeriesEventPayloadBean bean = processPayload(payload, ItemTimeSeriesEventPayloadBean.class);
186196
TimeSeries timeSeries = bean.getTimeSeries();
187197
return new ItemTimeSeriesUpdatedEvent(topic, payload, itemName, timeSeries, null);
188198
}
@@ -265,6 +275,53 @@ private Event createUpdatedEvent(String topic, String payload) {
265275
return new ItemUpdatedEvent(topic, payload, itemDTOs[0], itemDTOs[1]);
266276
}
267277

278+
private <T> T processPayload(String payload, Class<T> classOfPayload) {
279+
T result = deserializePayload(payload, classOfPayload);
280+
switch (result) {
281+
case ItemEventPayloadBean iep:
282+
if (DATE_TIME_TYPE_TYPE.equals(iep.type) && iep.value != null && iep.value.charAt(0) == '?') {
283+
iep.value = new DateTimeType(iep.value).toZone(timeZoneProvider.getTimeZone()).toFullString();
284+
}
285+
break;
286+
case ItemStateUpdatedEventPayloadBean isuep:
287+
if (DATE_TIME_TYPE_TYPE.equals(isuep.type) && isuep.value != null && isuep.value.charAt(0) == '?') {
288+
isuep.value = new DateTimeType(isuep.value).toZone(timeZoneProvider.getTimeZone()).toFullString();
289+
}
290+
break;
291+
case ItemStateChangedEventPayloadBean iscep:
292+
if (DATE_TIME_TYPE_TYPE.equals(iscep.type) && iscep.value != null && iscep.value.charAt(0) == '?') {
293+
iscep.value = new DateTimeType(iscep.value).toZone(timeZoneProvider.getTimeZone()).toFullString();
294+
}
295+
if (DATE_TIME_TYPE_TYPE.equals(iscep.oldType) && iscep.value != null
296+
&& iscep.oldValue.charAt(0) == '?') {
297+
iscep.oldValue = new DateTimeType(iscep.oldValue).toZone(timeZoneProvider.getTimeZone())
298+
.toFullString();
299+
}
300+
break;
301+
case ItemStatePredictedEventPayloadBean ispep:
302+
if (DATE_TIME_TYPE_TYPE.equals(ispep.predictedType) && ispep.predictedValue != null
303+
&& ispep.predictedValue.charAt(0) == '?') {
304+
ispep.predictedValue = new DateTimeType(ispep.predictedValue).toZone(timeZoneProvider.getTimeZone())
305+
.toFullString();
306+
}
307+
break;
308+
case ItemTimeSeriesEventPayloadBean itsep:
309+
List<ItemTimeSeriesEventPayloadBean.TimeSeriesPayload> series = itsep.timeSeries;
310+
if (series != null) {
311+
for (ItemTimeSeriesEventPayloadBean.TimeSeriesPayload tsp : series) {
312+
if (DATE_TIME_TYPE_TYPE.equals(tsp.type) && tsp.value != null && tsp.value.charAt(0) == '?') {
313+
tsp.value = new DateTimeType(tsp.value).toZone(timeZoneProvider.getTimeZone())
314+
.toFullString();
315+
}
316+
}
317+
}
318+
break;
319+
default:
320+
break;
321+
}
322+
return result;
323+
}
324+
268325
/**
269326
* Creates an item command event.
270327
*
@@ -277,7 +334,7 @@ private Event createUpdatedEvent(String topic, String payload) {
277334
public static ItemCommandEvent createCommandEvent(String itemName, Command command, @Nullable String source) {
278335
assertValidArguments(itemName, command, "command");
279336
String topic = buildTopic(ITEM_COMAND_EVENT_TOPIC, itemName);
280-
ItemEventPayloadBean bean = new ItemEventPayloadBean(getCommandType(command), command.toString());
337+
ItemEventPayloadBean bean = new ItemEventPayloadBean(getCommandType(command), command.toFullString());
281338
String payload = serializePayload(bean);
282339
return new ItemCommandEvent(topic, payload, itemName, command, source);
283340
}

bundles/org.openhab.core/src/test/java/org/openhab/core/events/AbstractEventFactoryTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
import org.eclipse.jdt.annotation.NonNullByDefault;
1818
import org.junit.jupiter.api.Test;
19+
import org.mockito.Mock;
20+
import org.openhab.core.i18n.TimeZoneProvider;
1921
import org.openhab.core.items.events.ItemEventFactory;
2022

2123
/**
@@ -25,7 +27,8 @@
2527
*/
2628
@NonNullByDefault
2729
public class AbstractEventFactoryTest {
28-
private final ItemEventFactory factory = new ItemEventFactory();
30+
private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProvider;
31+
private final ItemEventFactory factory = new ItemEventFactory(timeZoneProvider);
2932

3033
private static final String SOURCE = "binding:type:id:channel";
3134
private static final String EVENT_TYPE = "SOME_EVENT_TYPE";

0 commit comments

Comments
 (0)