Search in sources :

Example 1 with HaID

use of org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID in project smarthome by eclipse.

the class HomeAssistantMQTTImplementationTests method parseHATree.

@Test
public void parseHATree() throws InterruptedException, ExecutionException, TimeoutException {
    MqttChannelTypeProvider channelTypeProvider = mock(MqttChannelTypeProvider.class);
    final Map<String, AbstractComponent> haComponents = new HashMap<String, AbstractComponent>();
    ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(4);
    DiscoverComponents discover = spy(new DiscoverComponents(ThingChannelConstants.testHomeAssistantThing, scheduler, channelStateUpdateListener, new Gson()));
    // The DiscoverComponents object calls ComponentDiscovered callbacks.
    // In the following implementation we add the found component to the `haComponents` map
    // and add the types to the channelTypeProvider, like in the real Thing handler.
    final CountDownLatch latch = new CountDownLatch(1);
    ComponentDiscovered cd = (haID, c) -> {
        haComponents.put(haID.getChannelGroupID(), c);
        c.addChannelTypes(channelTypeProvider);
        channelTypeProvider.setChannelGroupType(c.groupTypeUID(), c.type());
        latch.countDown();
    };
    // Start the discovery for 100ms. Forced timeout after 300ms.
    HaID haID = new HaID(testObjectTopic);
    CompletableFuture<Void> future = discover.startDiscovery(connection, 100, haID, cd).thenRun(() -> {
    }).exceptionally(e -> {
        failure = e;
        return null;
    });
    assertTrue(latch.await(300, TimeUnit.MILLISECONDS));
    future.get(100, TimeUnit.MILLISECONDS);
    // No failure expected and one discoverd result
    assertNull(failure);
    assertThat(haComponents.size(), is(1));
    // For the switch component we should have one channel group type and one channel type
    verify(channelTypeProvider, times(1)).setChannelGroupType(any(), any());
    verify(channelTypeProvider, times(1)).setChannelType(any(), any());
    // We expect a switch component with an OnOff channel with the initial value UNDEF:
    State value = haComponents.get(haID.getChannelGroupID()).channelTypes().get(ComponentSwitch.switchChannelID).channelState.getCache().getChannelState();
    assertThat(value, is(UnDefType.UNDEF));
    haComponents.values().stream().map(e -> e.start(connection, scheduler, 100)).reduce(CompletableFuture.completedFuture(null), (a, v) -> a.thenCompose(b -> v)).exceptionally(e -> {
        failure = e;
        return null;
    }).get();
    // We should have received the retained value, while subscribing to the channels MQTT state topic.
    verify(channelStateUpdateListener, times(1)).updateChannelState(any(), any());
    // Value should be ON now.
    value = haComponents.get(haID.getChannelGroupID()).channelTypes().get(ComponentSwitch.switchChannelID).channelState.getCache().getChannelState();
    assertThat(value, is(OnOffType.ON));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) MockitoAnnotations.initMocks(org.mockito.MockitoAnnotations.initMocks) Mock(org.mockito.Mock) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) OnOffType(org.eclipse.smarthome.core.library.types.OnOffType) UnDefType(org.eclipse.smarthome.core.types.UnDefType) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) MqttConnectionState(org.eclipse.smarthome.io.transport.mqtt.MqttConnectionState) DiscoverComponents(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents) AbstractComponent(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.AbstractComponent) ArrayList(java.util.ArrayList) MqttService(org.eclipse.smarthome.io.transport.mqtt.MqttService) ConfigurationException(org.osgi.service.cm.ConfigurationException) Nullable(org.eclipse.jdt.annotation.Nullable) Gson(com.google.gson.Gson) Map(java.util.Map) After(org.junit.After) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ChannelStateUpdateListener(org.eclipse.smarthome.binding.mqtt.generic.internal.generic.ChannelStateUpdateListener) State(org.eclipse.smarthome.core.types.State) MqttConnectionObserver(org.eclipse.smarthome.io.transport.mqtt.MqttConnectionObserver) MqttChannelTypeProvider(org.eclipse.smarthome.binding.mqtt.generic.internal.generic.MqttChannelTypeProvider) ComponentSwitch(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.ComponentSwitch) Before(org.junit.Before) JavaOSGiTest(org.eclipse.smarthome.test.java.JavaOSGiTest) ComponentDiscovered(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents.ComponentDiscovered) Logger(org.slf4j.Logger) ThingChannelConstants(org.eclipse.smarthome.binding.mqtt.generic.internal.handler.ThingChannelConstants) MqttBrokerConnection(org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection) HaID(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) Test(org.junit.Test) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Mockito(org.mockito.Mockito) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Assert(org.junit.Assert) NonNull(org.eclipse.jdt.annotation.NonNull) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) MqttChannelTypeProvider(org.eclipse.smarthome.binding.mqtt.generic.internal.generic.MqttChannelTypeProvider) HashMap(java.util.HashMap) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) Gson(com.google.gson.Gson) CountDownLatch(java.util.concurrent.CountDownLatch) DiscoverComponents(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents) AbstractComponent(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.AbstractComponent) ComponentDiscovered(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents.ComponentDiscovered) HaID(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID) MqttConnectionState(org.eclipse.smarthome.io.transport.mqtt.MqttConnectionState) State(org.eclipse.smarthome.core.types.State) JavaOSGiTest(org.eclipse.smarthome.test.java.JavaOSGiTest) Test(org.junit.Test)

Example 2 with HaID

use of org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID in project smarthome by eclipse.

the class HomeAssistantDiscovery method receivedMessage.

@Override
public void receivedMessage(ThingUID connectionBridge, MqttBrokerConnection connection, String topic, byte[] payload) {
    // We check for the last part to filter all non-config topics out.
    if (!topic.endsWith("/config")) {
        return;
    }
    // We will of course find multiple of the same unique Thing IDs, for each different component another one.
    // Therefore the components are assembled into a list and given to the DiscoveryResult label for the user to
    // easily recognise object capabilities.
    HaID topicParts = determineTopicParts(topic);
    final String thingID = topicParts.getThingID();
    final ThingUID thingUID = new ThingUID(MqttBindingConstants.HOMEASSISTANT_MQTT_THING, connectionBridge, thingID);
    // Reset the found-component timer.
    // We will collect components for the thing label description for another 2 seconds.
    final ScheduledFuture<?> future = this.future;
    if (future != null) {
        future.cancel(false);
    }
    this.future = scheduler.schedule(componentsPerThingID::clear, 2, TimeUnit.SECONDS);
    // We need to keep track of already found component topics for a specific object_id/node_id
    Set<String> components = componentsPerThingID.getOrDefault(thingID, new HashSet<>());
    if (components.contains(topicParts.component)) {
        logger.trace("Discovered an already known component {}", topicParts.component);
        // If we already know about this object component, ignore the discovered topic.
        return;
    }
    components.add(topicParts.component);
    componentsPerThingID.put(thingID, components);
    final String componentNames = components.stream().map(c -> HA_COMP_TO_NAME.getOrDefault(c, c)).collect(Collectors.joining(","));
    Config config = new Gson().fromJson(new String(payload, StandardCharsets.UTF_8), Config.class);
    Map<String, Object> properties = new HashMap<>();
    properties.put("objectid", topicParts.objectID);
    properties.put("nodeid", topicParts.nodeID);
    properties.put("basetopic", BASE_TOPIC);
    // First remove an already discovered thing with the same ID
    thingRemoved(thingUID);
    // Because we need the new properties map with the updated "components" list
    thingDiscovered(DiscoveryResultBuilder.create(thingUID).withProperties(properties).withRepresentationProperty("objectid").withBridge(connectionBridge).withLabel(config.name + " (" + componentNames + ")").build());
}
Also used : ScheduledFuture(java.util.concurrent.ScheduledFuture) NonNullByDefault(org.eclipse.jdt.annotation.NonNullByDefault) Logger(org.slf4j.Logger) MqttBrokerConnection(org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection) HaID(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID) LoggerFactory(org.slf4j.LoggerFactory) Set(java.util.Set) DiscoveryService(org.eclipse.smarthome.config.discovery.DiscoveryService) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) HashSet(java.util.HashSet) TimeUnit(java.util.concurrent.TimeUnit) MQTTTopicDiscoveryService(org.eclipse.smarthome.binding.mqtt.discovery.MQTTTopicDiscoveryService) Component(org.osgi.service.component.annotations.Component) Stream(java.util.stream.Stream) TreeMap(java.util.TreeMap) Nullable(org.eclipse.jdt.annotation.Nullable) DiscoveryResultBuilder(org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder) Gson(com.google.gson.Gson) Map(java.util.Map) MqttBindingConstants(org.eclipse.smarthome.binding.mqtt.generic.internal.MqttBindingConstants) Reference(org.osgi.service.component.annotations.Reference) ThingUID(org.eclipse.smarthome.core.thing.ThingUID) HashMap(java.util.HashMap) HaID(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID) ThingUID(org.eclipse.smarthome.core.thing.ThingUID) Gson(com.google.gson.Gson)

Example 3 with HaID

use of org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID in project smarthome by eclipse.

the class HomeAssistantThingHandler method initialize.

@SuppressWarnings({ "null", "unused" })
@Override
public void initialize() {
    config = getConfigAs(HandlerConfiguration.class);
    if (config.objectid.isEmpty()) {
        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Device ID unknown");
        return;
    }
    discoveryHomeAssistantID = new HaID(config.basetopic, config.objectid, "", "");
    for (Channel channel : thing.getChannels()) {
        final String groupID = channel.getUID().getGroupId();
        if (groupID == null) {
            logger.warn("Channel {} has no groupd ID", channel.getLabel());
            continue;
        }
        // Already restored component?
        @Nullable AbstractComponent component = haComponents.get(groupID);
        if (component != null) {
            continue;
        } else {
            component = CFactory.createComponent(config.basetopic, channel, this, gson);
        }
        if (component != null) {
            haComponents.put(component.uid().getId(), component);
            component.addChannelTypes(channelTypeProvider);
        } else {
            logger.warn("Could not restore component {}", thing);
        }
    }
    super.initialize();
}
Also used : AbstractComponent(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.AbstractComponent) HandlerConfiguration(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HandlerConfiguration) HaID(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID) Channel(org.eclipse.smarthome.core.thing.Channel) CChannel(org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.CChannel) Nullable(org.eclipse.jdt.annotation.Nullable)

Aggregations

Nullable (org.eclipse.jdt.annotation.Nullable)3 HaID (org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID)3 Gson (com.google.gson.Gson)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 TimeUnit (java.util.concurrent.TimeUnit)2 AbstractComponent (org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.AbstractComponent)2 MqttBrokerConnection (org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection)2 StandardCharsets (java.nio.charset.StandardCharsets)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Set (java.util.Set)1 TreeMap (java.util.TreeMap)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutionException (java.util.concurrent.ExecutionException)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 ScheduledFuture (java.util.concurrent.ScheduledFuture)1 ScheduledThreadPoolExecutor (java.util.concurrent.ScheduledThreadPoolExecutor)1