2 * Copyright (c) 2010-2024 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.smartmeter.internal;
16 import java.util.Collection;
17 import java.util.Locale;
19 import java.util.concurrent.ConcurrentHashMap;
21 import javax.measure.Quantity;
22 import javax.measure.Unit;
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.smartmeter.SmartMeterBindingConstants;
27 import org.openhab.core.library.CoreItemFactory;
28 import org.openhab.core.thing.type.ChannelType;
29 import org.openhab.core.thing.type.ChannelTypeBuilder;
30 import org.openhab.core.thing.type.ChannelTypeProvider;
31 import org.openhab.core.thing.type.ChannelTypeUID;
32 import org.openhab.core.thing.type.StateChannelTypeBuilder;
33 import org.openhab.core.types.StateDescriptionFragmentBuilder;
34 import org.openhab.core.types.util.UnitUtils;
35 import org.osgi.service.component.annotations.Component;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * A {@link ChannelTypeProvider} that listens for changes to the {@link MeterDevice} and updates the
41 * {@link ChannelType}s according to all available OBIS values.
42 * It creates one {@link ChannelType} per available OBIS value.
44 * @author Matthias Steigenberger - Initial contribution
47 @Component(service = { ChannelTypeProvider.class, SmartMeterChannelTypeProvider.class })
48 public class SmartMeterChannelTypeProvider implements ChannelTypeProvider, MeterValueListener {
50 private final Logger logger = LoggerFactory.getLogger(SmartMeterChannelTypeProvider.class);
52 private final Map<String, ChannelType> obisChannelMap = new ConcurrentHashMap<>();
55 public Collection<ChannelType> getChannelTypes(@Nullable Locale locale) {
56 return obisChannelMap.values();
60 public @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID, @Nullable Locale locale) {
61 return obisChannelMap.values().stream().filter(channelType -> channelType.getUID().equals(channelTypeUID))
62 .findFirst().orElse(null);
66 public void errorOccurred(Throwable e) {
67 // Nothing to do if there is a reading error...
71 public <Q extends @NonNull Quantity<Q>> void valueChanged(MeterValue<Q> value) {
72 if (!obisChannelMap.containsKey(value.getObisCode())) {
73 logger.debug("Creating ChannelType for OBIS {}", value.getObisCode());
74 obisChannelMap.put(value.getObisCode(), getChannelType(value.getUnit(), value.getObisCode()));
78 private ChannelType getChannelType(Unit<?> unit, String obis) {
79 String obisChannelId = SmartMeterBindingConstants.getObisChannelId(obis);
80 StateChannelTypeBuilder stateDescriptionBuilder;
82 String dimension = UnitUtils.getDimensionName(unit);
83 stateDescriptionBuilder = ChannelTypeBuilder
84 .state(new ChannelTypeUID(SmartMeterBindingConstants.BINDING_ID, obisChannelId), obis,
85 CoreItemFactory.NUMBER + ":" + dimension)
86 .withStateDescriptionFragment(StateDescriptionFragmentBuilder.create().withReadOnly(true)
87 .withPattern("%.2f %unit%").build())
88 .withConfigDescriptionURI(URI.create(SmartMeterBindingConstants.CHANNEL_TYPE_METERREADER_OBIS));
90 stateDescriptionBuilder = ChannelTypeBuilder
91 .state(new ChannelTypeUID(SmartMeterBindingConstants.BINDING_ID, obisChannelId), obis,
92 CoreItemFactory.STRING)
93 .withStateDescriptionFragment(StateDescriptionFragmentBuilder.create().withReadOnly(true).build());
95 return stateDescriptionBuilder.build();
99 public <Q extends @NonNull Quantity<Q>> void valueRemoved(MeterValue<Q> value) {
100 obisChannelMap.remove(value.getObisCode());
104 * Gets the {@link ChannelTypeUID} for the given OBIS code.
106 * @param obis The obis code.
107 * @return The {@link ChannelTypeUID} or null.
109 public ChannelTypeUID getChannelTypeIdForObis(String obis) {
110 ChannelType channeltype = obisChannelMap.get(obis);
111 return channeltype != null ? channeltype.getUID() : null;