Search in sources :

Example 1 with GatewayDisconnectEvent

use of org.openremote.model.gateway.GatewayDisconnectEvent in project openremote by openremote.

the class GatewayClientService method onCentralManagerMessage.

protected void onCentralManagerMessage(GatewayConnection connection, String message) {
    String messageId = null;
    SharedEvent event = null;
    if (message.startsWith(EventRequestResponseWrapper.MESSAGE_PREFIX)) {
        EventRequestResponseWrapper<?> wrapper = messageFromString(message, EventRequestResponseWrapper.MESSAGE_PREFIX, EventRequestResponseWrapper.class);
        messageId = wrapper.getMessageId();
        event = wrapper.getEvent();
    }
    if (message.startsWith(SharedEvent.MESSAGE_PREFIX)) {
        event = messageFromString(message, SharedEvent.MESSAGE_PREFIX, SharedEvent.class);
    }
    if (event != null) {
        if (event instanceof GatewayDisconnectEvent) {
            if (((GatewayDisconnectEvent) event).getReason() == GatewayDisconnectEvent.Reason.PERMANENT_ERROR) {
                LOG.info("Central manager requested disconnect due to permanent error (likely this version of the edge gateway software is not compatible with that manager version)");
                destroyGatewayClient(connection, clientRealmMap.get(connection.getLocalRealm()));
                clientRealmMap.put(connection.getLocalRealm(), null);
            }
        } else if (event instanceof AttributeEvent) {
            assetProcessingService.sendAttributeEvent((AttributeEvent) event, AttributeEvent.Source.INTERNAL);
        } else if (event instanceof AssetEvent) {
            AssetEvent assetEvent = (AssetEvent) event;
            if (assetEvent.getCause() == AssetEvent.Cause.CREATE || assetEvent.getCause() == AssetEvent.Cause.UPDATE) {
                Asset asset = assetEvent.getAsset();
                asset.setRealm(connection.getLocalRealm());
                LOG.finer("Request from central manager to create/update an asset: Realm=" + connection.getLocalRealm() + ", Asset<?> ID=" + asset.getId());
                try {
                    asset = assetStorageService.merge(asset, true);
                } catch (Exception e) {
                    LOG.log(Level.INFO, "Request from central manager to create/update an asset failed: Realm=" + connection.getLocalRealm() + ", Asset<?> ID=" + asset.getId(), e);
                }
            }
        } else if (event instanceof DeleteAssetsRequestEvent) {
            DeleteAssetsRequestEvent deleteRequest = (DeleteAssetsRequestEvent) event;
            LOG.finer("Request from central manager to delete asset(s): Realm=" + connection.getLocalRealm() + ", Asset<?> IDs=" + Arrays.toString(deleteRequest.getAssetIds().toArray()));
            boolean success = false;
            try {
                success = assetStorageService.delete(deleteRequest.getAssetIds());
            } catch (Exception e) {
                LOG.log(Level.INFO, "Request from central manager to create/update an asset failed: Realm=" + connection.getLocalRealm() + ", Asset<?> IDs=" + Arrays.toString(deleteRequest.getAssetIds().toArray()), e);
            } finally {
                sendCentralManagerMessage(connection.getLocalRealm(), messageToString(EventRequestResponseWrapper.MESSAGE_PREFIX, new EventRequestResponseWrapper<>(messageId, new DeleteAssetsResponseEvent(success, deleteRequest.getAssetIds()))));
            }
        } else if (event instanceof ReadAssetsEvent) {
            ReadAssetsEvent readAssets = (ReadAssetsEvent) event;
            AssetQuery query = readAssets.getAssetQuery();
            // Force realm to be the one that this client is associated with
            query.tenant(new TenantPredicate(connection.getLocalRealm()));
            List<Asset<?>> assets = assetStorageService.findAll(readAssets.getAssetQuery());
            sendCentralManagerMessage(connection.getLocalRealm(), messageToString(EventRequestResponseWrapper.MESSAGE_PREFIX, new EventRequestResponseWrapper<>(messageId, new AssetsEvent(assets))));
        }
    }
}
Also used : GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent) AssetQuery(org.openremote.model.query.AssetQuery) TenantPredicate(org.openremote.model.query.filter.TenantPredicate) AttributeEvent(org.openremote.model.attribute.AttributeEvent) SharedEvent(org.openremote.model.event.shared.SharedEvent) EventRequestResponseWrapper(org.openremote.model.event.shared.EventRequestResponseWrapper)

Example 2 with GatewayDisconnectEvent

use of org.openremote.model.gateway.GatewayDisconnectEvent in project openremote by openremote.

the class GatewayService method processGatewayConnected.

protected void processGatewayConnected(String gatewayClientId, String sessionId) {
    if (!active) {
        return;
    }
    String gatewayId = getGatewayIdFromClientId(gatewayClientId);
    GatewayConnector connector = gatewayConnectorMap.get(gatewayId.toLowerCase(Locale.ROOT));
    if (connector == null) {
        LOG.warning("Gateway connected but not recognised which shouldn't happen: Gateway ID=" + gatewayId);
        clientEventService.sendToSession(sessionId, new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.UNRECOGNISED));
        clientEventService.closeSession(sessionId);
        return;
    }
    if (connector.isConnected()) {
        LOG.warning("Gateway already connected so requesting disconnect on new connection: Gateway ID=" + gatewayId);
        clientEventService.sendToSession(sessionId, new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.ALREADY_CONNECTED));
        clientEventService.closeSession(sessionId);
        return;
    }
    if (connector.isDisabled()) {
        LOG.warning("Gateway is currently disabled so will be ignored: Gateway ID=" + gatewayId);
        clientEventService.sendToSession(sessionId, new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.DISABLED));
        clientEventService.closeSession(sessionId);
        return;
    }
    connector.connect(createConnectorMessageConsumer(sessionId), () -> clientEventService.closeSession(sessionId));
}
Also used : GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent)

Example 3 with GatewayDisconnectEvent

use of org.openremote.model.gateway.GatewayDisconnectEvent in project openremote by openremote.

the class GatewayService method processAssetUpdate.

@Override
public boolean processAssetUpdate(EntityManager em, Asset<?> asset, Attribute<?> attribute, AttributeEvent.Source source) throws AssetProcessingException {
    // If the update was generated by a gateway then we don't want to process it here
    if (source == AttributeEvent.Source.GATEWAY) {
        return false;
    }
    GatewayConnector connector = gatewayConnectorMap.get(asset.getId().toLowerCase(Locale.ROOT));
    if (connector != null) {
        LOG.fine("Attribute event for a locally registered gateway asset (Asset ID=" + asset.getId() + "): " + attribute);
        GatewayAsset gatewayAsset = (GatewayAsset) asset;
        // This is a change to a locally registered gateway
        if (GatewayAsset.DISABLED.getName().equals(attribute.getName())) {
            boolean disabled = attribute.getValueAs(Boolean.class).orElse(false);
            boolean isAlreadyDisabled = gatewayAsset.getDisabled().orElse(false);
            // Ensure we update state
            gatewayAsset.setDisabled(disabled);
            if (disabled != isAlreadyDisabled) {
                createUpdateGatewayServiceUser(gatewayAsset);
                if (disabled) {
                    connector.sendMessageToGateway(new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.DISABLED));
                }
                connector.setDisabled(disabled);
            }
        }
        if (GatewayAsset.CLIENT_SECRET.getName().equals(attribute.getName())) {
            String newSecret = attribute.getValueAs(String.class).orElse(null);
            if (!TextUtil.isNullOrEmpty(newSecret)) {
                LOG.fine("Gateway client secret attribute updated so updating gateway service user secret to match: (Gateway ID=" + asset.getId() + ")");
                User gatewayServiceUser = identityProvider.getUserByUsername(asset.getRealm(), User.SERVICE_ACCOUNT_PREFIX + ((GatewayAsset) asset).getClientId().orElse(""));
                if (gatewayServiceUser != null) {
                    identityProvider.resetSecret(asset.getRealm(), gatewayServiceUser.getId(), newSecret);
                } else {
                    LOG.info("Couldn't retrieve gateway service user to update secret: (Gateway ID=" + asset.getId() + ")");
                }
            } else {
                // Push old secret back
                assetProcessingService.sendAttributeEvent(new AttributeEvent(asset.getId(), GatewayAsset.CLIENT_SECRET, gatewayAsset.getClientSecret().orElseThrow(() -> new IllegalStateException("Gateway client secret is null which was not expected"))));
            }
        }
    } else {
        String gatewayId = assetIdGatewayIdMap.get(asset.getId());
        if (gatewayId != null) {
            LOG.fine("Attribute event for a gateway descendant asset (Asset<?> ID=" + asset.getId() + ", Gateway ID=" + gatewayId + "): " + attribute);
            connector = gatewayConnectorMap.get(gatewayId.toLowerCase(Locale.ROOT));
            if (connector == null) {
                LOG.warning("Gateway not found for descendant asset, this should not happen!!! (Asset<?> ID=" + asset.getId() + ", Gateway ID=" + gatewayId + ")");
            } else {
                if (!connector.isConnected()) {
                    LOG.info("Gateway is not connected so attribute event for descendant asset will be dropped (Asset<?> ID=" + asset.getId() + ", Gateway ID=" + gatewayId + "): " + attribute);
                    throw new AssetProcessingException(AttributeWriteFailure.GATEWAY_DISCONNECTED, "Gateway is not connected: Gateway ID=" + connector.gatewayId);
                }
                LOG.fine("Attribute event for a gateway descendant asset being forwarded to the gateway (Asset<?> ID=" + asset.getId() + ", Gateway ID=" + gatewayId + "): " + attribute);
                connector.sendMessageToGateway(new AttributeEvent(mapAssetId(gatewayId, asset.getId(), true), attribute.getName(), attribute.getValue().orElse(null), attribute.getTimestamp().orElse(0L)).setParentId(mapAssetId(gatewayId, asset.getParentId(), true)).setRealm(asset.getRealm()));
            }
            // Consume this event as it is for a gateway descendant and we've sent it to that gateway for processing
            return true;
        }
    }
    // Don't consume event for non gateway descendant assets
    return false;
}
Also used : User(org.openremote.model.security.User) GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent) GatewayAsset(org.openremote.model.asset.impl.GatewayAsset) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AssetProcessingException(org.openremote.manager.asset.AssetProcessingException)

Example 4 with GatewayDisconnectEvent

use of org.openremote.model.gateway.GatewayDisconnectEvent in project openremote by openremote.

the class GatewayConnector method syncAborted.

protected boolean syncAborted() {
    if (syncErrors == MAX_SYNC_RETRIES) {
        LOG.warning("Gateway sync max retries reached so disconnecting the gateway: Gateway ID=" + gatewayId);
        sendMessageToGateway(new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.PERMANENT_ERROR));
        disconnect();
        return true;
    }
    return false;
}
Also used : GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent)

Example 5 with GatewayDisconnectEvent

use of org.openremote.model.gateway.GatewayDisconnectEvent in project openremote by openremote.

the class GatewayService method processGatewayChange.

protected void processGatewayChange(GatewayAsset gateway, PersistenceEvent<Asset<?>> persistenceEvent) {
    switch(persistenceEvent.getCause()) {
        case CREATE:
            createUpdateGatewayServiceUser(gateway);
            synchronized (gatewayConnectorMap) {
                GatewayConnector connector = new GatewayConnector(assetStorageService, assetProcessingService, executorService, gateway);
                gatewayConnectorMap.put(gateway.getId().toLowerCase(Locale.ROOT), connector);
            }
            break;
        case UPDATE:
            // Check if this gateway has a connector
            GatewayConnector connector = gatewayConnectorMap.get(gateway.getId().toLowerCase(Locale.ROOT));
            if (connector == null) {
                break;
            }
            connector.gateway = gateway;
            // Check if disabled
            boolean isNowDisabled = gateway.getDisabled().orElse(false);
            if (isNowDisabled) {
                connector.sendMessageToGateway(new GatewayDisconnectEvent(GatewayDisconnectEvent.Reason.DISABLED));
            }
            connector.setDisabled(isNowDisabled);
            int attributeIndex = persistenceEvent.getPropertyNames() != null ? IntStream.range(0, persistenceEvent.getPropertyNames().length).filter(i -> "attributes".equals(persistenceEvent.getPropertyNames()[i])).findFirst().orElse(-1) : -1;
            if (attributeIndex >= 0) {
                // Check if disabled attribute has changed
                AttributeMap oldAttributes = persistenceEvent.getPreviousState("attributes");
                boolean wasDisabled = oldAttributes.getValue(GatewayAsset.DISABLED).orElse(false);
                if (wasDisabled != isNowDisabled) {
                    createUpdateGatewayServiceUser(gateway);
                }
            }
            break;
        case DELETE:
            // Check if this gateway has a connector
            connector = gatewayConnectorMap.get(gateway.getId().toLowerCase(Locale.ROOT));
            if (connector == null) {
                break;
            }
            synchronized (gatewayConnectorMap) {
                connector = gatewayConnectorMap.remove(gateway.getId().toLowerCase(Locale.ROOT));
                if (connector != null) {
                    connector.disconnect();
                }
            }
            removeGatewayServiceUser(gateway);
            break;
    }
}
Also used : AssetStorageService(org.openremote.manager.asset.AssetStorageService) Tenant(org.openremote.model.security.Tenant) IntStream(java.util.stream.IntStream) ManagerKeycloakIdentityProvider(org.openremote.manager.security.ManagerKeycloakIdentityProvider) java.util(java.util) GATEWAY(org.openremote.model.syslog.SyslogCategory.GATEWAY) AssetProcessingException(org.openremote.manager.asset.AssetProcessingException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Exchange(org.apache.camel.Exchange) AssetProcessingService(org.openremote.manager.asset.AssetProcessingService) Level(java.util.logging.Level) Predicate(org.apache.camel.Predicate) RulesetStorageService(org.openremote.manager.rules.RulesetStorageService) RulesService(org.openremote.manager.rules.RulesService) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) SyslogCategory(org.openremote.model.syslog.SyslogCategory) TextUtil(org.openremote.model.util.TextUtil) PersistenceEvent(org.openremote.model.PersistenceEvent) MessageBrokerService(org.openremote.container.message.MessageBrokerService) User(org.openremote.model.security.User) Ruleset(org.openremote.model.rules.Ruleset) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) Asset(org.openremote.model.asset.Asset) GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent) AssetQuery(org.openremote.model.query.AssetQuery) GatewayAsset(org.openremote.model.asset.impl.GatewayAsset) ContainerService(org.openremote.model.ContainerService) EntityManager(javax.persistence.EntityManager) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Container(org.openremote.model.Container) Consumer(java.util.function.Consumer) ClientEventService(org.openremote.manager.event.ClientEventService) RouteBuilder(org.apache.camel.builder.RouteBuilder) PERSISTENCE_TOPIC(org.openremote.container.persistence.PersistenceService.PERSISTENCE_TOPIC) GatewayConnector.mapAssetId(org.openremote.manager.gateway.GatewayConnector.mapAssetId) org.openremote.model.attribute(org.openremote.model.attribute) AssetUpdateProcessor(org.openremote.manager.asset.AssetUpdateProcessor) PredicateBuilder.and(org.apache.camel.builder.PredicateBuilder.and) PredicateBuilder.or(org.apache.camel.builder.PredicateBuilder.or) PersistenceService.isPersistenceEventForEntityType(org.openremote.container.persistence.PersistenceService.isPersistenceEventForEntityType) ConnectionConstants(org.openremote.container.web.ConnectionConstants) SharedEvent(org.openremote.model.event.shared.SharedEvent) GatewayDisconnectEvent(org.openremote.model.gateway.GatewayDisconnectEvent)

Aggregations

GatewayDisconnectEvent (org.openremote.model.gateway.GatewayDisconnectEvent)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 AssetProcessingException (org.openremote.manager.asset.AssetProcessingException)2 GatewayAsset (org.openremote.model.asset.impl.GatewayAsset)2 SharedEvent (org.openremote.model.event.shared.SharedEvent)2 AssetQuery (org.openremote.model.query.AssetQuery)2 User (org.openremote.model.security.User)2 java.util (java.util)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 Consumer (java.util.function.Consumer)1 Level (java.util.logging.Level)1 Logger (java.util.logging.Logger)1 Collectors (java.util.stream.Collectors)1 IntStream (java.util.stream.IntStream)1 EntityManager (javax.persistence.EntityManager)1 Exchange (org.apache.camel.Exchange)1 Predicate (org.apache.camel.Predicate)1 PredicateBuilder.and (org.apache.camel.builder.PredicateBuilder.and)1 PredicateBuilder.or (org.apache.camel.builder.PredicateBuilder.or)1 RouteBuilder (org.apache.camel.builder.RouteBuilder)1