2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.shelly.internal.util;
15 import static org.openhab.binding.shelly.internal.util.ShellyUtils.mkChannelId;
18 import java.util.concurrent.ConcurrentHashMap;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
22 import org.openhab.core.types.State;
23 import org.openhab.core.types.UnDefType;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * The {@link ShellyChannelCache} implements a caching layer for channel updates.
30 * @author Markus Michels - Initial contribution
33 public class ShellyChannelCache {
34 private final Logger logger = LoggerFactory.getLogger(ShellyChannelCache.class);
36 private final ShellyThingInterface thingHandler;
37 private final Map<String, State> channelData = new ConcurrentHashMap<>();
38 private String thingName = "";
39 private boolean enabled = false;
41 public ShellyChannelCache(ShellyThingInterface thingHandler) {
42 this.thingHandler = thingHandler;
43 setThingName(thingHandler.getThingName());
46 public void setThingName(String thingName) {
47 this.thingName = thingName;
50 public boolean isEnabled() {
54 public void enable() {
58 public synchronized void disable() {
64 * Update one channel. Use Channel Cache to avoid unnecessary updates (and avoid
65 * messing up the log with those updates)
67 * @param channelId Channel id
68 * @param newValue Value (State)
69 * @param forceUpdate true: ignore cached data, force update; false check cache of changed data
70 * @return true, if successful
72 public boolean updateChannel(String channelId, State newValue, Boolean forceUpdate) {
75 if (channelData.containsKey(channelId)) {
76 current = channelData.get(channelId);
78 if (!enabled || forceUpdate || (current == null) || !current.equals(newValue)) {
79 if ((current != null) && current.getClass().isEnum() && (current.equals(newValue))) {
80 return false; // special case for OnOffType
82 // For channels that support multiple types (like brightness) a suffix is added
83 // this gets removed to get the channelId for updateState
84 thingHandler.publishState(channelId, newValue);
85 if (current == null) {
86 channelData.put(channelId, newValue);
88 channelData.replace(channelId, newValue);
92 } catch (IllegalArgumentException e) {
93 logger.debug("{}: Unable to update channel {} with {} (type {}): {} ({})", thingName, channelId, newValue,
94 newValue.getClass(), ShellyUtils.getMessage(e), e.getClass(), e);
99 public boolean updateChannel(String group, String channel, State value) {
100 return updateChannel(mkChannelId(group, channel), value, false);
103 public boolean updateChannel(String channelId, State value) {
104 return updateChannel(channelId, value, false);
108 * Get a value from the Channel Cache
110 * @param group Channel Group
111 * @param channel Channel Name
112 * @return the data from that channel
115 public State getValue(String group, String channel) {
116 return getValue(mkChannelId(group, channel));
119 public State getValue(String channelId) {
120 State st = channelData.get(channelId);
121 return st != null ? st : UnDefType.NULL;
124 public void resetChannel(String channelId) {
125 channelData.remove(channelId);
128 public void clear() {