Search in sources :

Example 11 with Attribute

use of org.openremote.model.attribute.Attribute in project openremote by openremote.

the class EnergyOptimisationService method runOptimisation.

/**
 * Runs the optimisation routine for the specified time; it is important that this method does not throw an
 * exception as it will cancel the scheduled task thus stopping future optimisations.
 */
protected void runOptimisation(String optimisationAssetId, Instant optimisationTime) {
    OptimisationInstance optimisationInstance = assetOptimisationInstanceMap.get(optimisationAssetId);
    if (optimisationInstance == null) {
        return;
    }
    LOG.finer(getLogPrefix(optimisationAssetId) + "Running for time '" + formatter.format(optimisationTime));
    EnergyOptimiser optimiser = optimisationInstance.energyOptimiser;
    int intervalCount = optimiser.get24HourIntervalCount();
    double intervalSize = optimiser.getIntervalSize();
    LOG.finest(getLogPrefix(optimisationAssetId) + "Fetching child assets of type '" + ElectricitySupplierAsset.class.getSimpleName() + "'");
    List<ElectricitySupplierAsset> supplierAssets = assetStorageService.findAll(new AssetQuery().types(ElectricitySupplierAsset.class).recursive(true).parents(optimisationAssetId)).stream().filter(asset -> asset.hasAttribute(ElectricitySupplierAsset.TARIFF_IMPORT)).map(asset -> (ElectricitySupplierAsset) asset).collect(Collectors.toList());
    if (supplierAssets.size() != 1) {
        LOG.warning(getLogPrefix(optimisationAssetId) + "Expected exactly one " + ElectricitySupplierAsset.class.getSimpleName() + " asset with a '" + ElectricitySupplierAsset.TARIFF_IMPORT.getName() + "' attribute but found: " + supplierAssets.size());
        return;
    }
    double[] powerNets = new double[intervalCount];
    ElectricitySupplierAsset supplierAsset = supplierAssets.get(0);
    if (LOG.isLoggable(Level.FINEST)) {
        LOG.finest(getLogPrefix(optimisationAssetId) + "Found child asset of type '" + ElectricitySupplierAsset.class.getSimpleName() + "': " + supplierAsset);
    }
    // Do some basic validation
    if (supplierAsset.getTariffImport().isPresent()) {
        LOG.warning(getLogPrefix(optimisationAssetId) + ElectricitySupplierAsset.class.getSimpleName() + " asset '" + ElectricitySupplierAsset.TARIFF_IMPORT.getName() + "' attribute has no value");
    }
    LOG.finest(getLogPrefix(optimisationAssetId) + "Fetching optimisable child assets of type '" + ElectricityStorageAsset.class.getSimpleName() + "'");
    List<ElectricityStorageAsset> optimisableStorageAssets = assetStorageService.findAll(new AssetQuery().recursive(true).parents(optimisationAssetId).types(ElectricityStorageAsset.class).attributes(new LogicGroup<>(LogicGroup.Operator.AND, Collections.singletonList(new LogicGroup<>(LogicGroup.Operator.OR, new AttributePredicate(ElectricityStorageAsset.SUPPORTS_IMPORT.getName(), new BooleanPredicate(true)), new AttributePredicate(ElectricityStorageAsset.SUPPORTS_EXPORT.getName(), new BooleanPredicate(true)))), new AttributePredicate().name(new StringPredicate(ElectricityAsset.POWER_SETPOINT.getName()))))).stream().map(asset -> (ElectricityStorageAsset) asset).collect(Collectors.toList());
    List<ElectricityStorageAsset> finalOptimisableStorageAssets = optimisableStorageAssets;
    optimisableStorageAssets = optimisableStorageAssets.stream().filter(asset -> {
        // Exclude force charged assets (so we don't mess with the setpoint)
        if (forceChargeAssetIds.contains(asset.getId())) {
            LOG.finest("Optimisable asset was requested to force charge so it won't be optimised: " + asset.getId());
            @SuppressWarnings("OptionalGetWithoutIsPresent") Attribute<Double> powerAttribute = asset.getAttribute(ElectricityAsset.POWER).get();
            double[] powerLevels = get24HAttributeValues(asset.getId(), powerAttribute, optimiser.getIntervalSize(), intervalCount, optimisationTime);
            IntStream.range(0, intervalCount).forEach(i -> powerNets[i] += powerLevels[i]);
            double currentEnergyLevel = asset.getEnergyLevel().orElse(0d);
            double maxEnergyLevel = getElectricityStorageAssetEnergyLevelMax(asset);
            if (currentEnergyLevel >= maxEnergyLevel) {
                LOG.info("Force charged asset has reached maxEnergyLevelPercentage so stopping charging: " + asset.getId());
                forceChargeAssetIds.remove(asset.getId());
                assetProcessingService.sendAttributeEvent(new AttributeEvent(asset.getId(), ElectricityStorageAsset.POWER_SETPOINT, 0d));
                assetProcessingService.sendAttributeEvent(new AttributeEvent(asset.getId(), ElectricityStorageAsset.FORCE_CHARGE, AttributeExecuteStatus.COMPLETED));
            }
            return false;
        }
        if (asset instanceof ElectricityChargerAsset) {
            // Check if it has a child vehicle asset
            return finalOptimisableStorageAssets.stream().noneMatch(a -> {
                if (a instanceof ElectricVehicleAsset && a.getParentId().equals(asset.getId())) {
                    // Take the lowest power max from vehicle or charger
                    double vehiclePowerImportMax = a.getPowerImportMax().orElse(Double.MAX_VALUE);
                    double vehiclePowerExportMax = a.getPowerExportMax().orElse(Double.MAX_VALUE);
                    double chargerPowerImportMax = asset.getPowerImportMax().orElse(Double.MAX_VALUE);
                    double chargerPowerExportMax = asset.getPowerExportMax().orElse(Double.MAX_VALUE);
                    double smallestPowerImportMax = Math.min(vehiclePowerImportMax, chargerPowerImportMax);
                    double smallestPowerExportMax = Math.min(vehiclePowerExportMax, chargerPowerExportMax);
                    if (smallestPowerImportMax < vehiclePowerImportMax) {
                        LOG.fine("Reducing vehicle power import max due to connected charger limit: vehicle=" + a.getId() + ", oldPowerImportMax=" + vehiclePowerImportMax + ", newPowerImportMax=" + smallestPowerImportMax);
                        a.setPowerImportMax(smallestPowerImportMax);
                    }
                    if (smallestPowerExportMax < vehiclePowerExportMax) {
                        LOG.fine("Reducing vehicle power Export max due to connected charger limit: vehicle=" + a.getId() + ", oldPowerExportMax=" + vehiclePowerExportMax + ", newPowerExportMax=" + smallestPowerExportMax);
                        a.setPowerExportMax(smallestPowerExportMax);
                    }
                    LOG.finest("Excluding charger from optimisable assets and child vehicle will be used instead: " + asset.getId());
                    return true;
                }
                return false;
            });
        }
        return true;
    }).sorted(Comparator.comparingInt(asset -> asset.getEnergyLevelSchedule().map(schedule -> 0).orElse(1))).collect(Collectors.toList());
    if (optimisableStorageAssets.isEmpty()) {
        LOG.warning(getLogPrefix(optimisationAssetId) + "Expected at least one optimisable '" + ElectricityStorageAsset.class.getSimpleName() + " asset with a '" + ElectricityAsset.POWER_SETPOINT.getName() + "' attribute but found none");
        return;
    }
    if (LOG.isLoggable(Level.FINEST)) {
        LOG.finest(getLogPrefix(optimisationAssetId) + "Found optimisable child assets of type '" + ElectricityStorageAsset.class.getSimpleName() + "': " + optimisableStorageAssets.stream().map(Asset::getId).collect(Collectors.joining(", ")));
    }
    LOG.finest(getLogPrefix(optimisationAssetId) + "Fetching plain consumer and producer child assets of type '" + ElectricityProducerAsset.class.getSimpleName() + "', '" + ElectricityConsumerAsset.class.getSimpleName() + "', '" + ElectricityStorageAsset.class.getSimpleName() + "'");
    AtomicInteger count = new AtomicInteger(0);
    assetStorageService.findAll(new AssetQuery().recursive(true).parents(optimisationAssetId).types(ElectricityConsumerAsset.class, ElectricityProducerAsset.class).attributes(new AttributePredicate().name(new StringPredicate(ElectricityAsset.POWER.getName())))).forEach(asset -> {
        @SuppressWarnings("OptionalGetWithoutIsPresent") Attribute<Double> powerAttribute = asset.getAttribute(ElectricityAsset.POWER).get();
        double[] powerLevels = get24HAttributeValues(asset.getId(), powerAttribute, optimiser.getIntervalSize(), intervalCount, optimisationTime);
        IntStream.range(0, intervalCount).forEach(i -> powerNets[i] += powerLevels[i]);
        count.incrementAndGet();
    });
    // Get power of storage assets that don't support neither import or export (treat them as plain consumers/producers)
    List<ElectricityStorageAsset> plainStorageAssets = assetStorageService.findAll(new AssetQuery().recursive(true).parents(optimisationAssetId).types(ElectricityStorageAsset.class).attributes(new AttributePredicate().name(new StringPredicate(ElectricityAsset.POWER.getName())), new AttributePredicate(ElectricityStorageAsset.SUPPORTS_IMPORT.getName(), new BooleanPredicate(true), true, null), new AttributePredicate(ElectricityStorageAsset.SUPPORTS_EXPORT.getName(), new BooleanPredicate(true), true, null))).stream().map(asset -> (ElectricityStorageAsset) asset).collect(Collectors.toList());
    // Exclude chargers with a power value != 0 and a child vehicle with a power value != 0 (avoid double counting - vehicle takes priority)
    plainStorageAssets.stream().filter(asset -> {
        if (asset instanceof ElectricityChargerAsset) {
            // Check if it has a child vehicle asset also check optimisable assets as child vehicle could be in there
            return plainStorageAssets.stream().noneMatch(a -> {
                if (a instanceof ElectricVehicleAsset && a.getParentId().equals(asset.getId())) {
                    LOG.finest("Excluding charger from plain consumer/producer calculations to avoid double counting power: " + asset.getId());
                    return true;
                }
                return false;
            }) && finalOptimisableStorageAssets.stream().noneMatch(a -> {
                if (a instanceof ElectricVehicleAsset && a.getParentId().equals(asset.getId())) {
                    LOG.finest("Excluding charger from plain consumer/producer calculations to avoid double counting power: " + asset.getId());
                    return true;
                }
                return false;
            });
        }
        return true;
    }).forEach(asset -> {
        @SuppressWarnings("OptionalGetWithoutIsPresent") Attribute<Double> powerAttribute = asset.getAttribute(ElectricityAsset.POWER).get();
        double[] powerLevels = get24HAttributeValues(asset.getId(), powerAttribute, optimiser.getIntervalSize(), intervalCount, optimisationTime);
        IntStream.range(0, intervalCount).forEach(i -> powerNets[i] += powerLevels[i]);
        count.incrementAndGet();
    });
    if (LOG.isLoggable(Level.FINER)) {
        LOG.finer(getLogPrefix(optimisationAssetId) + "Found plain consumer and producer child assets count=" + count.get());
        LOG.finer("Calculated net power of consumers and producers: " + Arrays.toString(powerNets));
    }
    // Get supplier costs for each interval
    double financialWeightingImport = optimiser.getFinancialWeighting();
    double financialWeightingExport = optimiser.getFinancialWeighting();
    if (financialWeightingImport < 1d && !supplierAsset.getCarbonImport().isPresent()) {
        financialWeightingImport = 1d;
    }
    if (financialWeightingExport < 1d && !supplierAsset.getCarbonExport().isPresent()) {
        financialWeightingExport = 1d;
    }
    double[] costsImport = get24HAttributeValues(supplierAsset.getId(), supplierAsset.getAttribute(ElectricitySupplierAsset.TARIFF_IMPORT).orElse(null), optimiser.getIntervalSize(), intervalCount, optimisationTime);
    double[] costsExport = get24HAttributeValues(supplierAsset.getId(), supplierAsset.getAttribute(ElectricitySupplierAsset.TARIFF_EXPORT).orElse(null), optimiser.getIntervalSize(), intervalCount, optimisationTime);
    if (financialWeightingImport < 1d || financialWeightingExport < 1d) {
        double[] carbonImport = get24HAttributeValues(supplierAsset.getId(), supplierAsset.getAttribute(ElectricitySupplierAsset.CARBON_IMPORT).orElse(null), optimiser.getIntervalSize(), intervalCount, optimisationTime);
        double[] carbonExport = get24HAttributeValues(supplierAsset.getId(), supplierAsset.getAttribute(ElectricitySupplierAsset.CARBON_EXPORT).orElse(null), optimiser.getIntervalSize(), intervalCount, optimisationTime);
        LOG.finer(getLogPrefix(optimisationAssetId) + "Adjusting costs to include some carbon weighting, financialWeightingImport=" + financialWeightingImport + ", financialWeightingExport=" + financialWeightingExport);
        for (int i = 0; i < costsImport.length; i++) {
            costsImport[i] = (financialWeightingImport * costsImport[i]) + ((1 - financialWeightingImport) * carbonImport[i]);
            costsExport[i] = (financialWeightingExport * costsExport[i]) + ((1 - financialWeightingExport) * carbonExport[i]);
        }
    }
    if (LOG.isLoggable(Level.FINER)) {
        LOG.finer(getLogPrefix(optimisationAssetId) + "Import costs: " + Arrays.toString(costsImport));
        LOG.finer(getLogPrefix(optimisationAssetId) + "Export costs: " + Arrays.toString(costsExport));
    }
    // Savings variables
    List<String> obsoleteUnoptimisedAssetIds = new ArrayList<>(optimisationInstance.unoptimisedStorageAssetEnergyLevels.keySet());
    double unoptimisedPower = powerNets[0];
    double financialCost = 0d;
    double carbonCost = 0d;
    double unoptimisedFinancialCost = 0d;
    double unoptimisedCarbonCost = 0d;
    // Optimise storage assets with priority on storage assets with an energy schedule (already sorted above)
    double importPowerMax = supplierAsset.getPowerImportMax().orElse(Double.MAX_VALUE);
    double exportPowerMax = -1 * supplierAsset.getPowerExportMax().orElse(Double.MAX_VALUE);
    double[] importPowerMaxes = new double[intervalCount];
    double[] exportPowerMaxes = new double[intervalCount];
    Arrays.fill(importPowerMaxes, importPowerMax);
    Arrays.fill(exportPowerMaxes, exportPowerMax);
    long periodSeconds = (long) (optimiser.getIntervalSize() * 60 * 60);
    for (ElectricityStorageAsset storageAsset : optimisableStorageAssets) {
        boolean hasSetpoint = storageAsset.hasAttribute(ElectricityStorageAsset.POWER_SETPOINT);
        boolean supportsExport = storageAsset.isSupportsExport().orElse(false);
        boolean supportsImport = storageAsset.isSupportsImport().orElse(false);
        LOG.finer(getLogPrefix(optimisationAssetId) + "Optimising power set points for storage asset: " + storageAsset);
        if (!supportsExport && !supportsImport) {
            LOG.finest(getLogPrefix(optimisationAssetId) + "Storage asset doesn't support import or export: " + storageAsset.getId());
            continue;
        }
        if (!hasSetpoint) {
            LOG.info(getLogPrefix(optimisationAssetId) + "Storage asset has no '" + ElectricityStorageAsset.POWER_SETPOINT.getName() + "' attribute so cannot be controlled: " + storageAsset.getId());
            continue;
        }
        double energyCapacity = storageAsset.getEnergyCapacity().orElse(0d);
        double energyLevel = Math.min(energyCapacity, storageAsset.getEnergyLevel().orElse(-1d));
        if (energyCapacity <= 0d || energyLevel < 0) {
            LOG.info(getLogPrefix(optimisationAssetId) + "Storage asset has no capacity or energy level so cannot import or export energy: " + storageAsset.getId());
            continue;
        }
        double energyLevelMax = Math.min(energyCapacity, ((double) storageAsset.getEnergyLevelPercentageMax().orElse(100) / 100) * energyCapacity);
        double energyLevelMin = Math.min(energyCapacity, ((double) storageAsset.getEnergyLevelPercentageMin().orElse(0) / 100) * energyCapacity);
        double[] energyLevelMins = new double[intervalCount];
        double[] energyLevelMaxs = new double[intervalCount];
        Arrays.fill(energyLevelMins, energyLevelMin);
        Arrays.fill(energyLevelMaxs, energyLevelMax);
        // Does the storage support import and have an energy level schedule
        Optional<Integer[][]> energyLevelScheduleOptional = storageAsset.getEnergyLevelSchedule();
        boolean hasEnergyMinRequirement = energyLevelMin > 0 || energyLevelScheduleOptional.isPresent();
        double powerExportMax = storageAsset.getPowerExportMax().map(power -> -1 * power).orElse(Double.MIN_VALUE);
        double powerImportMax = storageAsset.getPowerImportMax().orElse(Double.MAX_VALUE);
        int[][] energySchedule = energyLevelScheduleOptional.map(dayArr -> Arrays.stream(dayArr).map(hourArr -> Arrays.stream(hourArr).mapToInt(i -> i != null ? i : 0).toArray()).toArray(int[][]::new)).orElse(null);
        if (energySchedule != null) {
            LOG.finer(getLogPrefix(optimisationAssetId) + "Applying energy schedule for storage asset: " + storageAsset.getId());
            optimiser.applyEnergySchedule(energyLevelMins, energyLevelMaxs, energyCapacity, energySchedule, LocalDateTime.ofInstant(Instant.ofEpochMilli(timerService.getCurrentTimeMillis()), ZoneId.systemDefault()));
        }
        double maxEnergyLevelMin = Arrays.stream(energyLevelMins).max().orElse(0);
        boolean isConnected = storageAssetConnected(storageAsset);
        // TODO: Make these a function of energy level
        Function<Integer, Double> powerImportMaxCalculator = interval -> interval == 0 && !isConnected ? 0 : powerImportMax;
        Function<Integer, Double> powerExportMaxCalculator = interval -> interval == 0 && !isConnected ? 0 : powerExportMax;
        if (hasEnergyMinRequirement) {
            LOG.finer(getLogPrefix(optimisationAssetId) + "Normalising min energy requirements for storage asset: " + storageAsset.getId());
            optimiser.normaliseEnergyMinRequirements(energyLevelMins, powerImportMaxCalculator, powerExportMaxCalculator, energyLevel);
            if (LOG.isLoggable(Level.FINEST)) {
                LOG.finest(getLogPrefix(optimisationAssetId) + "Min energy requirements for storage asset '" + storageAsset.getId() + "': " + Arrays.toString(energyLevelMins));
            }
        }
        // Calculate the power setpoints for this asset and update power net values for each interval
        double[] setpoints = getStoragePowerSetpoints(optimisationInstance, storageAsset, energyLevelMins, energyLevelMaxs, powerNets, importPowerMaxes, exportPowerMaxes, costsImport, costsExport);
        if (setpoints != null) {
            // Assume these setpoints will be applied so update the power net values with these
            for (int i = 0; i < powerNets.length; i++) {
                if (i == 0) {
                    if (!storageAssetConnected(storageAsset)) {
                        LOG.finer("Optimised storage asset not connected so interval 0 will not be counted or actioned: " + storageAsset.getId());
                        setpoints[i] = 0;
                        continue;
                    }
                    // Update savings/cost data with costs specific to this asset
                    if (setpoints[i] > 0) {
                        financialCost += storageAsset.getTariffImport().orElse(0d) * setpoints[i] * intervalSize;
                    } else {
                        financialCost += storageAsset.getTariffExport().orElse(0d) * -1 * setpoints[i] * intervalSize;
                    }
                }
                powerNets[i] += setpoints[i];
            }
            // Push the setpoints into the prediction service for the storage asset's setpoint attribute and set current setpoint
            List<Pair<?, LocalDateTime>> valuesAndTimestamps = IntStream.range(1, setpoints.length).mapToObj(i -> new Pair<>(setpoints[i], LocalDateTime.ofInstant(optimisationTime.plus(periodSeconds * i, ChronoUnit.SECONDS), ZoneId.systemDefault()))).collect(Collectors.toList());
            assetPredictedDatapointService.updateValues(storageAsset.getId(), ElectricityAsset.POWER_SETPOINT.getName(), valuesAndTimestamps);
        }
        assetProcessingService.sendAttributeEvent(new AttributeEvent(storageAsset.getId(), ElectricityAsset.POWER_SETPOINT, setpoints != null ? setpoints[0] : null));
        // Update unoptimised power for this asset
        obsoleteUnoptimisedAssetIds.remove(storageAsset.getId());
        double assetUnoptimisedPower = getStorageUnoptimisedImportPower(optimisationInstance, optimisationAssetId, storageAsset, maxEnergyLevelMin, Math.max(0, powerImportMax - unoptimisedPower));
        unoptimisedPower += assetUnoptimisedPower;
        unoptimisedFinancialCost += storageAsset.getTariffImport().orElse(0d) * assetUnoptimisedPower * intervalSize;
    }
    // Clear out un-optimised data for not found assets
    obsoleteUnoptimisedAssetIds.forEach(optimisationInstance.unoptimisedStorageAssetEnergyLevels.keySet()::remove);
    // Calculate and store savings data
    carbonCost = (powerNets[0] >= 0 ? supplierAsset.getCarbonImport().orElse(0d) : -1 * supplierAsset.getCarbonExport().orElse(0d)) * powerNets[0] * intervalSize;
    financialCost += (powerNets[0] >= 0 ? supplierAsset.getTariffImport().orElse(0d) : -1 * supplierAsset.getTariffExport().orElse(0d)) * powerNets[0] * intervalSize;
    unoptimisedCarbonCost = (unoptimisedPower >= 0 ? supplierAsset.getCarbonImport().orElse(0d) : -1 * supplierAsset.getCarbonExport().orElse(0d)) * unoptimisedPower * intervalSize;
    unoptimisedFinancialCost += (unoptimisedPower >= 0 ? supplierAsset.getTariffImport().orElse(0d) : -1 * supplierAsset.getTariffExport().orElse(0d)) * unoptimisedPower * intervalSize;
    double financialSaving = unoptimisedFinancialCost - financialCost;
    double carbonSaving = unoptimisedCarbonCost - carbonCost;
    LOG.info(getLogPrefix(optimisationAssetId) + "Current interval financial saving = " + financialSaving);
    LOG.info(getLogPrefix(optimisationAssetId) + "Current interval carbon saving = " + carbonSaving);
    financialSaving += optimisationInstance.optimisationAsset.getFinancialSaving().orElse(0d);
    carbonSaving += optimisationInstance.optimisationAsset.getCarbonSaving().orElse(0d);
    // Update in memory asset
    optimisationInstance.optimisationAsset.setFinancialSaving(financialSaving);
    optimisationInstance.optimisationAsset.setCarbonSaving(carbonSaving);
    // Push new values into the DB
    assetProcessingService.sendAttributeEvent(new AttributeEvent(optimisationAssetId, EnergyOptimisationAsset.FINANCIAL_SAVING, financialSaving));
    assetProcessingService.sendAttributeEvent(new AttributeEvent(optimisationAssetId, EnergyOptimisationAsset.CARBON_SAVING, carbonSaving));
}
Also used : AssetStorageService(org.openremote.manager.asset.AssetStorageService) IntStream(java.util.stream.IntStream) GatewayService.isNotForGateway(org.openremote.manager.gateway.GatewayService.isNotForGateway) java.util(java.util) DatapointInterval(org.openremote.model.datapoint.DatapointInterval) ScheduledFuture(java.util.concurrent.ScheduledFuture) AssetDescriptor(org.openremote.model.asset.AssetDescriptor) BiFunction(java.util.function.BiFunction) AttributeRef(org.openremote.model.attribute.AttributeRef) AssetProcessingService(org.openremote.manager.asset.AssetProcessingService) ValueUtil(org.openremote.model.util.ValueUtil) Function(java.util.function.Function) Level(java.util.logging.Level) java.time(java.time) BooleanPredicate(org.openremote.model.query.filter.BooleanPredicate) Attribute(org.openremote.model.attribute.Attribute) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AttributeEvent(org.openremote.model.attribute.AttributeEvent) org.openremote.model.asset.impl(org.openremote.model.asset.impl) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) PersistenceEvent(org.openremote.model.PersistenceEvent) LogicGroup(org.openremote.model.query.LogicGroup) MessageBrokerService(org.openremote.container.message.MessageBrokerService) AssetPredictedDatapointService(org.openremote.manager.datapoint.AssetPredictedDatapointService) Asset(org.openremote.model.asset.Asset) MetaItemType(org.openremote.model.value.MetaItemType) HOURS(java.time.temporal.ChronoUnit.HOURS) AssetQuery(org.openremote.model.query.AssetQuery) Pair(org.openremote.model.util.Pair) ContainerService(org.openremote.model.ContainerService) AttributePredicate(org.openremote.model.query.filter.AttributePredicate) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Container(org.openremote.model.Container) ValueDatapoint(org.openremote.model.datapoint.ValueDatapoint) TimeUnit(java.util.concurrent.TimeUnit) ClientEventService(org.openremote.manager.event.ClientEventService) ChronoUnit(java.time.temporal.ChronoUnit) StringPredicate(org.openremote.model.query.filter.StringPredicate) RouteBuilder(org.apache.camel.builder.RouteBuilder) TimerService(org.openremote.container.timer.TimerService) PERSISTENCE_TOPIC(org.openremote.container.persistence.PersistenceService.PERSISTENCE_TOPIC) DateTimeFormatter(java.time.format.DateTimeFormatter) PersistenceService.isPersistenceEventForEntityType(org.openremote.container.persistence.PersistenceService.isPersistenceEventForEntityType) GatewayService(org.openremote.manager.gateway.GatewayService) AttributeExecuteStatus(org.openremote.model.attribute.AttributeExecuteStatus) StringPredicate(org.openremote.model.query.filter.StringPredicate) Attribute(org.openremote.model.attribute.Attribute) AttributePredicate(org.openremote.model.query.filter.AttributePredicate) AttributeEvent(org.openremote.model.attribute.AttributeEvent) BooleanPredicate(org.openremote.model.query.filter.BooleanPredicate) Pair(org.openremote.model.util.Pair) AssetQuery(org.openremote.model.query.AssetQuery) ValueDatapoint(org.openremote.model.datapoint.ValueDatapoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 12 with Attribute

use of org.openremote.model.attribute.Attribute in project openremote by openremote.

the class RulesService method start.

@Override
public void start(Container container) throws Exception {
    if (!geofenceAssetAdapters.isEmpty()) {
        LOG.info("GeoefenceAssetAdapters found: " + geofenceAssetAdapters.size());
        locationPredicateRulesConsumer = this::onEngineLocationRulesChanged;
        for (GeofenceAssetAdapter geofenceAssetAdapter : geofenceAssetAdapters) {
            geofenceAssetAdapter.start(container);
        }
    }
    LOG.info("Deploying global rulesets");
    rulesetStorageService.findAll(GlobalRuleset.class, new RulesetQuery().setEnabledOnly(true).setFullyPopulate(true)).forEach(this::deployGlobalRuleset);
    LOG.info("Deploying tenant rulesets");
    tenants = Arrays.stream(identityService.getIdentityProvider().getTenants()).filter(Tenant::getEnabled).toArray(Tenant[]::new);
    rulesetStorageService.findAll(TenantRuleset.class, new RulesetQuery().setEnabledOnly(true).setFullyPopulate(true)).stream().filter(rd -> Arrays.stream(tenants).anyMatch(tenant -> rd.getRealm().equals(tenant.getRealm()))).forEach(this::deployTenantRuleset);
    LOG.info("Deploying asset rulesets");
    // Group by asset ID then tenant and check tenant is enabled
    // noinspection ResultOfMethodCallIgnored
    deployAssetRulesets(rulesetStorageService.findAll(AssetRuleset.class, new RulesetQuery().setEnabledOnly(true).setFullyPopulate(true))).count();
    LOG.info("Loading all assets with fact attributes to initialize state of rules engines");
    Stream<Pair<Asset<?>, Stream<Attribute<?>>>> stateAttributes = findRuleStateAttributes();
    // Push each attribute as an asset update through the rule engine chain
    // that will ensure the insert only happens to the engines in scope
    stateAttributes.forEach(pair -> {
        Asset<?> asset = pair.key;
        pair.value.forEach(ruleAttribute -> {
            AssetState<?> assetState = new AssetState<>(asset, ruleAttribute, Source.INTERNAL);
            updateAssetState(assetState);
        });
    });
    // Start the engines
    if (globalEngine != null) {
        globalEngine.start();
    }
    tenantEngines.values().forEach(RulesEngine::start);
    assetEngines.values().forEach(RulesEngine::start);
    startDone = true;
    preInitassetStates.forEach(this::doProcessAssetUpdate);
    preInitassetStates.clear();
}
Also used : ClientRole(org.openremote.model.security.ClientRole) BiFunction(java.util.function.BiFunction) AssetProcessingException(org.openremote.manager.asset.AssetProcessingException) AssetProcessingService(org.openremote.manager.asset.AssetProcessingService) ValueUtil(org.openremote.model.util.ValueUtil) MapAccess.getString(org.openremote.container.util.MapAccess.getString) GeofenceAssetAdapter(org.openremote.manager.rules.geofence.GeofenceAssetAdapter) Attribute.getAddedOrModifiedAttributes(org.openremote.model.attribute.Attribute.getAddedOrModifiedAttributes) org.openremote.model.rules(org.openremote.model.rules) AssetPredictedDatapointService(org.openremote.manager.datapoint.AssetPredictedDatapointService) GeofenceDefinition(org.openremote.model.rules.geofence.GeofenceDefinition) ContainerService(org.openremote.model.ContainerService) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Container(org.openremote.model.Container) Stream(java.util.stream.Stream) RouteBuilder(org.apache.camel.builder.RouteBuilder) PERSISTENCE_TOPIC(org.openremote.container.persistence.PersistenceService.PERSISTENCE_TOPIC) RulesetQuery(org.openremote.model.query.RulesetQuery) GatewayService(org.openremote.manager.gateway.GatewayService) GlobalLock.withLock(org.openremote.container.concurrent.GlobalLock.withLock) AssetStorageService(org.openremote.manager.asset.AssetStorageService) Tenant(org.openremote.model.security.Tenant) AttributeMap(org.openremote.model.attribute.AttributeMap) GatewayService.isNotForGateway(org.openremote.manager.gateway.GatewayService.isNotForGateway) java.util(java.util) AssetDatapointService(org.openremote.manager.datapoint.AssetDatapointService) NotificationService(org.openremote.manager.notification.NotificationService) SEVERE(java.util.logging.Level.SEVERE) GlobalLock.withLockReturning(org.openremote.container.concurrent.GlobalLock.withLockReturning) LocationAttributePredicate(org.openremote.model.query.filter.LocationAttributePredicate) Attribute(org.openremote.model.attribute.Attribute) PersistenceService(org.openremote.container.persistence.PersistenceService) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ManagerWebService(org.openremote.manager.web.ManagerWebService) PersistenceEvent(org.openremote.model.PersistenceEvent) MessageBrokerService(org.openremote.container.message.MessageBrokerService) FlowResourceImpl(org.openremote.manager.rules.flow.FlowResourceImpl) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) Asset(org.openremote.model.asset.Asset) MetaItemType(org.openremote.model.value.MetaItemType) AssetQuery(org.openremote.model.query.AssetQuery) Pair(org.openremote.model.util.Pair) EntityManager(javax.persistence.EntityManager) ClientEventService(org.openremote.manager.event.ClientEventService) Collectors.toList(java.util.stream.Collectors.toList) TimerService(org.openremote.container.timer.TimerService) AssetUpdateProcessor(org.openremote.manager.asset.AssetUpdateProcessor) PersistenceService.isPersistenceEventForEntityType(org.openremote.container.persistence.PersistenceService.isPersistenceEventForEntityType) Source(org.openremote.model.attribute.AttributeEvent.Source) FINEST(java.util.logging.Level.FINEST) RulesetQuery(org.openremote.model.query.RulesetQuery) Attribute(org.openremote.model.attribute.Attribute) GeofenceAssetAdapter(org.openremote.manager.rules.geofence.GeofenceAssetAdapter) Tenant(org.openremote.model.security.Tenant) Pair(org.openremote.model.util.Pair)

Example 13 with Attribute

use of org.openremote.model.attribute.Attribute in project openremote by openremote.

the class ManagerDemoSetup method onStart.

@Override
public void onStart() throws Exception {
    super.onStart();
    KeycloakDemoSetup keycloakDemoSetup = setupService.getTaskOfType(KeycloakDemoSetup.class);
    Tenant masterTenant = keycloakDemoSetup.masterTenant;
    Tenant tenantCity = keycloakDemoSetup.tenantCity;
    masterRealm = masterTenant.getRealm();
    this.realmCityTenant = tenantCity.getRealm();
    // ################################ Demo assets for 'master' realm ###################################
    // ################################ Link demo users and assets ###################################
    // ################################ Make users restricted ###################################
    // ################################ Realm smartcity ###################################
    SimulatorAgent smartcitySimulatorAgent = new SimulatorAgent("Simulator agent");
    smartcitySimulatorAgent.setRealm(this.realmCityTenant);
    smartcitySimulatorAgent = assetStorageService.merge(smartcitySimulatorAgent);
    smartcitySimulatorAgentId = smartcitySimulatorAgent.getId();
    LocalTime midnight = LocalTime.of(0, 0);
    // ################################ Realm smartcity - Energy Management ###################################
    ThingAsset energyManagement = new ThingAsset("Energy management");
    energyManagement.setRealm(this.realmCityTenant);
    energyManagement.getAttributes().addOrReplace(new Attribute<>("powerTotalProducers", ValueType.NUMBER).addOrReplaceMeta(new MetaItem<>(MetaItemType.UNITS, Constants.units(Constants.UNITS_KILO, Constants.UNITS_WATT)), new MetaItem<>(MetaItemType.READ_ONLY, true), new MetaItem<>(MetaItemType.STORE_DATA_POINTS, true), new MetaItem<>(MetaItemType.RULE_STATE, true)), new Attribute<>("powerTotalConsumers", ValueType.NUMBER).addOrReplaceMeta(new MetaItem<>(MetaItemType.UNITS, Constants.units(Constants.UNITS_KILO, Constants.UNITS_WATT)), new MetaItem<>(MetaItemType.READ_ONLY, true), new MetaItem<>(MetaItemType.STORE_DATA_POINTS, true), new MetaItem<>(MetaItemType.RULE_STATE, true)));
    energyManagement.setId(UniqueIdentifierGenerator.generateId(energyManagement.getName()));
    energyManagement = assetStorageService.merge(energyManagement);
    energyManagementId = energyManagement.getId();
    // ### De Rotterdam ###
    BuildingAsset building1Asset = new BuildingAsset("De Rotterdam");
    building1Asset.setParent(energyManagement);
    building1Asset.getAttributes().addOrReplace(new Attribute<>(BuildingAsset.STREET, "Wilhelminakade 139"), new Attribute<>(BuildingAsset.POSTAL_CODE, "3072 AP"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"), new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.488324, 51.906577)), new Attribute<>("powerBalance", ValueType.NUMBER).addMeta(new MetaItem<>(MetaItemType.UNITS, Constants.units(Constants.UNITS_KILO, Constants.UNITS_WATT)), new MetaItem<>(MetaItemType.READ_ONLY), new MetaItem<>(MetaItemType.RULE_STATE), new MetaItem<>(MetaItemType.STORE_DATA_POINTS)));
    building1Asset.setId(UniqueIdentifierGenerator.generateId(building1Asset.getName() + "building"));
    building1Asset = assetStorageService.merge(building1Asset);
    ElectricityStorageAsset storage1Asset = createDemoElectricityStorageAsset("Battery De Rotterdam", building1Asset, new GeoJSONPoint(4.488324, 51.906577));
    storage1Asset.setManufacturer("Super-B");
    storage1Asset.setModel("Nomia");
    storage1Asset.setId(UniqueIdentifierGenerator.generateId(storage1Asset.getName()));
    storage1Asset = assetStorageService.merge(storage1Asset);
    ElectricityConsumerAsset consumption1Asset = createDemoElectricityConsumerAsset("Consumption De Rotterdam", building1Asset, new GeoJSONPoint(4.487519, 51.906544));
    consumption1Asset.getAttribute(ElectricityConsumerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 23), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 21), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 20), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 22), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 21), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 22), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 41), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 54), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 63), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 76), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 80), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 79), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 84), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 76), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 82), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 83), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 77), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 71), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 63), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 41), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 27), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 22), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 24), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 20) })));
    });
    consumption1Asset.setId(UniqueIdentifierGenerator.generateId(consumption1Asset.getName()));
    consumption1Asset = assetStorageService.merge(consumption1Asset);
    ElectricityProducerSolarAsset production1Asset = createDemoElectricitySolarProducerAsset("Solar De Rotterdam", building1Asset, new GeoJSONPoint(4.488592, 51.907047));
    production1Asset.setManufacturer("AEG");
    production1Asset.setModel("AS-P60");
    production1Asset.getAttribute(ElectricityProducerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), -10), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), -15), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), -39), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), -52), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), -50), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), -48), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), -36), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), -23), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), -24), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), -18), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), -10), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), -8), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), -3), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    });
    production1Asset.setEnergyExportTotal(152689d);
    production1Asset.setPowerExportMax(89.6);
    production1Asset.setEfficiencyExport(93);
    production1Asset.setPanelOrientation(ElectricityProducerSolarAsset.PanelOrientation.EAST_WEST);
    production1Asset.setPanelAzimuth(30);
    production1Asset.setPanelPitch(20);
    production1Asset.setId(UniqueIdentifierGenerator.generateId(production1Asset.getName()));
    production1Asset = assetStorageService.merge(production1Asset);
    // ### Stadhuis ###
    BuildingAsset building2Asset = new BuildingAsset("Stadhuis");
    building2Asset.setParent(energyManagement);
    building2Asset.getAttributes().addOrReplace(new Attribute<>(BuildingAsset.STREET, "Coolsingel 40"), new Attribute<>(BuildingAsset.POSTAL_CODE, "3011 AD"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"), new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.47985, 51.92274)));
    building2Asset.setId(UniqueIdentifierGenerator.generateId(building2Asset.getName() + "building"));
    building2Asset = assetStorageService.merge(building2Asset);
    ElectricityStorageAsset storage2Asset = createDemoElectricityStorageAsset("Battery Stadhuis", building2Asset, new GeoJSONPoint(4.47985, 51.92274));
    storage2Asset.setManufacturer("LG Chem");
    storage2Asset.setModel("ESS Industrial");
    storage2Asset.setId(UniqueIdentifierGenerator.generateId(storage2Asset.getName()));
    storage2Asset = assetStorageService.merge(storage2Asset);
    ElectricityConsumerAsset consumption2Asset = createDemoElectricityConsumerAsset("Consumption Stadhuis", building2Asset, new GeoJSONPoint(4.47933, 51.92259));
    consumption2Asset.getAttribute(ElectricityConsumerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 8), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 8), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 12), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 22), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 30), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 39), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 44), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 47), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 44), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 33), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 23), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 13), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 8) })));
    });
    consumption2Asset.setId(UniqueIdentifierGenerator.generateId(consumption2Asset.getName()));
    consumption2Asset = assetStorageService.merge(consumption2Asset);
    ElectricityProducerSolarAsset production2Asset = createDemoElectricitySolarProducerAsset("Solar Stadhuis", building2Asset, new GeoJSONPoint(4.47945, 51.92301));
    production2Asset.getAttribute(ElectricityProducerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), -2), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), -3), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), -8), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), -14), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), -12), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), -10), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), -7), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), -5), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), -7), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), -5), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), -3), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), -2), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    });
    production2Asset.setEnergyExportTotal(88961d);
    production2Asset.setPowerExportMax(19.2);
    production2Asset.setEfficiencyExport(79);
    production2Asset.setPanelOrientation(ElectricityProducerSolarAsset.PanelOrientation.SOUTH);
    production2Asset.setPanelAzimuth(10);
    production2Asset.setPanelPitch(40);
    production2Asset.setManufacturer("Solarwatt");
    production2Asset.setModel("EasyIn 60M");
    production2Asset.setId(UniqueIdentifierGenerator.generateId(production2Asset.getName()));
    production2Asset = assetStorageService.merge(production2Asset);
    // ### Markthal ###
    BuildingAsset building3Asset = new BuildingAsset("Markthal");
    building3Asset.setParent(energyManagement);
    building3Asset.getAttributes().addOrReplace(new Attribute<>(BuildingAsset.STREET, "Dominee Jan Scharpstraat 298"), new Attribute<>(BuildingAsset.POSTAL_CODE, "3011 GZ"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"), new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.47945, 51.92301)), new Attribute<>("allChargersInUse", ValueType.BOOLEAN).addMeta(new MetaItem<>(MetaItemType.READ_ONLY)));
    building3Asset.setId(UniqueIdentifierGenerator.generateId(building3Asset.getName() + "building"));
    building3Asset = assetStorageService.merge(building3Asset);
    ElectricityProducerSolarAsset production3Asset = createDemoElectricitySolarProducerAsset("Solar Markthal", building3Asset, new GeoJSONPoint(4.47945, 51.92301));
    production3Asset.getAttribute(ElectricityProducerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), -2), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), -6), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), -10), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), -13), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), -21), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), -14), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), -17), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), -10), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), -9), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), -7), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), -5), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), -4), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), -2), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    });
    production3Asset.setEnergyExportTotal(24134d);
    production3Asset.setPowerExportMax(29.8);
    production3Asset.setEfficiencyExport(91);
    production3Asset.setPanelOrientation(ElectricityProducerSolarAsset.PanelOrientation.SOUTH);
    production3Asset.setManufacturer("Sunpower");
    production3Asset.setModel("E20-327");
    production3Asset.setPanelAzimuth(10);
    production3Asset.setPanelPitch(5);
    production3Asset.setId(UniqueIdentifierGenerator.generateId(production3Asset.getName()));
    production3Asset = assetStorageService.merge(production3Asset);
    ElectricityChargerAsset charger1Asset = createDemoElectricityChargerAsset("Charger 1 Markthal", building3Asset, new GeoJSONPoint(4.486143, 51.920058));
    charger1Asset.setPower(0d);
    charger1Asset.getAttributes().getOrCreate(ElectricityChargerAsset.POWER).addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 2), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 10), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 15), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 35), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 17), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    charger1Asset.setManufacturer("Allego");
    charger1Asset.setModel("HPC");
    charger1Asset.setId(UniqueIdentifierGenerator.generateId(charger1Asset.getName()));
    charger1Asset = assetStorageService.merge(charger1Asset);
    ElectricityChargerAsset charger2Asset = createDemoElectricityChargerAsset("Charger 2 Markthal", building3Asset, new GeoJSONPoint(4.486188, 51.919957));
    charger2Asset.setPower(0d);
    charger2Asset.getAttributes().getOrCreate(ElectricityChargerAsset.POWER).addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 11), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 10), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 17), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 14), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 28), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 26), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 13), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    charger2Asset.setManufacturer("Bosch");
    charger2Asset.setModel("EV800");
    charger2Asset.setId(UniqueIdentifierGenerator.generateId(charger2Asset.getName()));
    charger2Asset = assetStorageService.merge(charger2Asset);
    ElectricityChargerAsset charger3Asset = createDemoElectricityChargerAsset("Charger 3 Markthal", building3Asset, new GeoJSONPoint(4.486232, 51.919856));
    charger3Asset.setPower(0d);
    charger3Asset.getAttributes().getOrCreate(ElectricityChargerAsset.POWER).addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 2), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 18), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 29), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 22), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 14), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    charger3Asset.setManufacturer("Siemens");
    charger3Asset.setModel("CPC 50");
    charger3Asset.setId(UniqueIdentifierGenerator.generateId(charger3Asset.getName()));
    charger3Asset = assetStorageService.merge(charger3Asset);
    ElectricityChargerAsset charger4Asset = createDemoElectricityChargerAsset("Charger 4 Markthal", building3Asset, new GeoJSONPoint(4.486286, 51.919733));
    charger4Asset.setPower(0d);
    charger4Asset.getAttributes().getOrCreate(ElectricityChargerAsset.POWER).addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 3), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 17), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 15), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 8), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 4), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 15), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 30), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 11), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 4) })));
    charger4Asset.setManufacturer("SemaConnect");
    charger4Asset.setModel("The Series 6");
    charger4Asset.setId(UniqueIdentifierGenerator.generateId(charger4Asset.getName()));
    charger4Asset = assetStorageService.merge(charger4Asset);
    // ### Erasmianum ###
    BuildingAsset building4Asset = new BuildingAsset("Erasmianum");
    building4Asset.setParent(energyManagement);
    building4Asset.getAttributes().addOrReplace(new Attribute<>(BuildingAsset.STREET, "Wytemaweg 25"), new Attribute<>(BuildingAsset.POSTAL_CODE, "3015 CN"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"), new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.468324, 51.912062)));
    building4Asset.setId(UniqueIdentifierGenerator.generateId(building4Asset.getName() + "building"));
    building4Asset = assetStorageService.merge(building4Asset);
    ElectricityConsumerAsset consumption4Asset = createDemoElectricityConsumerAsset("Consumption Erasmianum", building4Asset, new GeoJSONPoint(4.468324, 51.912062));
    consumption4Asset.getAttribute(ElectricityConsumerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 5), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 6), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 9), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 23), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 37), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 41), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 47), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 49), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 51), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 43), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 48), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 45), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 46), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 41), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 30), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 19), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 15), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 6) })));
    });
    consumption4Asset.setId(UniqueIdentifierGenerator.generateId(consumption4Asset.getName()));
    consumption4Asset = assetStorageService.merge(consumption4Asset);
    // ### Oostelijk zwembad ###
    BuildingAsset building5Asset = new BuildingAsset("Oostelijk zwembad");
    building5Asset.setParent(energyManagement);
    building5Asset.getAttributes().addOrReplace(new Attribute<>(BuildingAsset.STREET, "Gerdesiaweg 480"), new Attribute<>(BuildingAsset.POSTAL_CODE, "3061 RA"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"), new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.498048, 51.925770)));
    building5Asset.setId(UniqueIdentifierGenerator.generateId(building5Asset.getName() + "building"));
    building5Asset = assetStorageService.merge(building5Asset);
    ElectricityConsumerAsset consumption5Asset = createDemoElectricityConsumerAsset("Consumption Zwembad", building5Asset, new GeoJSONPoint(4.498048, 51.925770));
    consumption5Asset.getAttribute(ElectricityConsumerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 15), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 17), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 16), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 24), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 35), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 33), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 33), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 31), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 37), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 37), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 35), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 24), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 19) })));
    });
    consumption5Asset.setId(UniqueIdentifierGenerator.generateId(consumption5Asset.getName()));
    consumption5Asset = assetStorageService.merge(consumption5Asset);
    ElectricityProducerSolarAsset production5Asset = createDemoElectricitySolarProducerAsset("Solar Zwembad", building5Asset, new GeoJSONPoint(4.498281, 51.925507));
    production5Asset.getAttribute(ElectricityProducerAsset.POWER).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), -1), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), -3), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), -8), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), -30), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), -44), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), -42), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), -41), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), -29), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), -19), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), -16), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), -11), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), -4), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), -3), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), -2), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 0), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0) })));
    });
    production5Asset.setEnergyExportTotal(23461d);
    production5Asset.setPowerExportMax(76.2);
    production5Asset.setEfficiencyExport(86);
    production5Asset.setPanelOrientation(ElectricityProducerSolarAsset.PanelOrientation.SOUTH);
    production5Asset.setManufacturer("S-Energy");
    production5Asset.setModel("SN260P-10");
    production5Asset.setPanelAzimuth(50);
    production5Asset.setPanelPitch(15);
    production5Asset.setId(UniqueIdentifierGenerator.generateId(production5Asset.getName()));
    production5Asset = assetStorageService.merge(production5Asset);
    // ### Weather ###
    HTTPAgent weatherHttpApiAgent = new HTTPAgent("Weather Agent");
    weatherHttpApiAgent.setParent(energyManagement);
    weatherHttpApiAgent.setBaseURI("https://api.openweathermap.org/data/2.5/");
    MultivaluedStringMap queryParams = new MultivaluedStringMap();
    queryParams.put("appid", Collections.singletonList("c3ecbf09be5267cd280676a01acd3360"));
    queryParams.put("lat", Collections.singletonList("51.918849"));
    queryParams.put("lon", Collections.singletonList("4.463250"));
    queryParams.put("units", Collections.singletonList("metric"));
    weatherHttpApiAgent.setRequestQueryParameters(queryParams);
    MultivaluedStringMap headers = new MultivaluedStringMap();
    headers.put("Accept", Collections.singletonList("application/json"));
    weatherHttpApiAgent.setRequestHeaders(headers);
    weatherHttpApiAgent = assetStorageService.merge(weatherHttpApiAgent);
    weatherHttpApiAgentId = weatherHttpApiAgent.getId();
    WeatherAsset weather = new WeatherAsset("Weather");
    weather.setParent(energyManagement);
    weather.setId(UniqueIdentifierGenerator.generateId(weather.getName()));
    HTTPAgentLink agentLink = new HTTPAgentLink(weatherHttpApiAgentId);
    agentLink.setPath("weather");
    agentLink.setPollingMillis((int) halfHourInMillis);
    weather.getAttributes().addOrReplace(new Attribute<>("currentWeather", ValueType.JSON_OBJECT).addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, agentLink), new MetaItem<>(MetaItemType.LABEL, "Open Weather Map API weather end point"), new MetaItem<>(MetaItemType.READ_ONLY, true), new MetaItem<>(MetaItemType.STORE_DATA_POINTS, false), new MetaItem<>(MetaItemType.RULE_STATE, false), new MetaItem<>(MetaItemType.ATTRIBUTE_LINKS, new AttributeLink[] { createWeatherApiAttributeLink(weather.getId(), "main", "temp", "temperature"), createWeatherApiAttributeLink(weather.getId(), "main", "humidity", "humidity"), createWeatherApiAttributeLink(weather.getId(), "wind", "speed", "windSpeed"), createWeatherApiAttributeLink(weather.getId(), "wind", "deg", "windDirection") })));
    weather.getAttribute("windSpeed").ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.STORE_DATA_POINTS), new MetaItem<>(MetaItemType.RULE_STATE));
    });
    weather.getAttribute("temperature").ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.STORE_DATA_POINTS), new MetaItem<>(MetaItemType.RULE_STATE));
    });
    weather.getAttribute("windDirection").ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.STORE_DATA_POINTS), new MetaItem<>(MetaItemType.RULE_STATE));
    });
    weather.getAttribute("humidity").ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.STORE_DATA_POINTS), new MetaItem<>(MetaItemType.RULE_STATE));
    });
    new Attribute<>(Asset.LOCATION, new GeoJSONPoint(4.463250, 51.918849));
    weather = assetStorageService.merge(weather);
    // ################################ Realm smartcity - Environment monitor ###################################
    Asset<?> environmentMonitor = new ThingAsset("Environment monitor");
    environmentMonitor.setRealm(this.realmCityTenant);
    environmentMonitor.setId(UniqueIdentifierGenerator.generateId(environmentMonitor.getName()));
    environmentMonitor = assetStorageService.merge(environmentMonitor);
    EnvironmentSensorAsset environment1Asset = createDemoEnvironmentAsset("Oudehaven", environmentMonitor, new GeoJSONPoint(4.49313, 51.91885), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    EnvironmentSensorAsset environment2Asset = createDemoEnvironmentAsset("Kaappark", environmentMonitor, new GeoJSONPoint(4.480434, 51.899287), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    EnvironmentSensorAsset environment3Asset = createDemoEnvironmentAsset("Museumpark", environmentMonitor, new GeoJSONPoint(4.472457, 51.912047), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    EnvironmentSensorAsset environment4Asset = createDemoEnvironmentAsset("Eendrachtsplein", environmentMonitor, new GeoJSONPoint(4.473599, 51.916292), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    EnvironmentSensorAsset[] environmentArray = { environment1Asset, environment2Asset, environment3Asset, environment4Asset };
    for (EnvironmentSensorAsset asset : environmentArray) {
        asset.setManufacturer("Intemo");
        asset.setModel("Josene outdoor");
        asset.getAttribute(EnvironmentSensorAsset.OZONE).ifPresent(assetAttribute -> {
            assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), getRandomNumberInRange(115, 125)), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), getRandomNumberInRange(115, 125)), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), getRandomNumberInRange(80, 90)) })));
        });
        asset.setId(UniqueIdentifierGenerator.generateId(asset.getName()));
        asset = assetStorageService.merge(asset);
    }
    GroundwaterSensorAsset groundwater1Asset = createDemoGroundwaterAsset("Leuvehaven", environmentMonitor, new GeoJSONPoint(4.48413, 51.91431));
    GroundwaterSensorAsset groundwater2Asset = createDemoGroundwaterAsset("Steiger", environmentMonitor, new GeoJSONPoint(4.482887, 51.920082));
    GroundwaterSensorAsset groundwater3Asset = createDemoGroundwaterAsset("Stadhuis", environmentMonitor, new GeoJSONPoint(4.480876, 51.923212));
    GroundwaterSensorAsset[] groundwaterArray = { groundwater1Asset, groundwater2Asset, groundwater3Asset };
    for (GroundwaterSensorAsset asset : groundwaterArray) {
        asset.setManufacturer("Eijkelkamp");
        asset.setModel("TeleControlNet");
        asset.getAttribute(GroundwaterSensorAsset.SOIL_TEMPERATURE).ifPresent(assetAttribute -> {
            assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 12.2), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 12.1), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 12.0), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 11.8), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 11.7), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 11.7), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 11.9), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 12.1), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 12.8), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 13.5), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 13.9), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 15.2), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 15.3), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 15.5), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 15.5), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 15.4), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 15.2), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 15.2), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 14.6), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 14.2), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 13.8), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 13.4), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 12.8), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 12.3) })));
        });
        asset.getAttribute(GroundwaterSensorAsset.WATER_LEVEL).ifPresent(assetAttribute -> {
            assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), getRandomNumberInRange(100, 120)), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), getRandomNumberInRange(100, 120)), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), getRandomNumberInRange(90, 110)), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), getRandomNumberInRange(100, 110)), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), getRandomNumberInRange(100, 120)), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), getRandomNumberInRange(110, 120)) })));
        });
        asset.setId(UniqueIdentifierGenerator.generateId(asset.getName()));
        asset = assetStorageService.merge(asset);
    }
    // ################################ Realm smartcity - Mobility and Safety ###################################
    Asset<?> mobilityAndSafety = new ThingAsset("Mobility and safety");
    mobilityAndSafety.setRealm(this.realmCityTenant);
    mobilityAndSafety.setId(UniqueIdentifierGenerator.generateId(mobilityAndSafety.getName()));
    mobilityAndSafety = assetStorageService.merge(mobilityAndSafety);
    // ### Parking ###
    GroupAsset parkingGroupAsset = new GroupAsset("Parking group", ParkingAsset.class);
    parkingGroupAsset.setParent(mobilityAndSafety);
    parkingGroupAsset.getAttributes().addOrReplace(new Attribute<>("totalOccupancy", ValueType.POSITIVE_INTEGER).addMeta(new MetaItem<>(MetaItemType.UNITS, Constants.units(Constants.UNITS_PERCENTAGE)), new MetaItem<>(MetaItemType.CONSTRAINTS, ValueConstraint.constraints(new ValueConstraint.Min(0), new ValueConstraint.Max(100))), new MetaItem<>(MetaItemType.READ_ONLY), new MetaItem<>(MetaItemType.RULE_STATE), new MetaItem<>(MetaItemType.STORE_DATA_POINTS)));
    parkingGroupAsset.setId(UniqueIdentifierGenerator.generateId(parkingGroupAsset.getName()));
    parkingGroupAsset = assetStorageService.merge(parkingGroupAsset);
    ParkingAsset parking1Asset = createDemoParkingAsset("Markthal", parkingGroupAsset, new GeoJSONPoint(4.48527, 51.91984)).setManufacturer("SKIDATA").setModel("Barrier.Gate");
    parking1Asset.getAttribute(ParkingAsset.SPACES_OCCUPIED).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 34), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 37), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 31), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 32), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 39), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 47), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 53), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 165), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 301), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 417), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 442), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 489), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 467), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 490), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 438), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 457), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 402), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 379), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 336), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 257), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 204), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 112), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 75) })));
    });
    parking1Asset.setPriceHourly(3.75);
    parking1Asset.setPriceDaily(25.00);
    parking1Asset.setSpacesTotal(512);
    parking1Asset.getAttribute(ParkingAsset.SPACES_TOTAL).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.RULE_STATE));
    });
    parking1Asset.setId(UniqueIdentifierGenerator.generateId(parking1Asset.getName()));
    parking1Asset = assetStorageService.merge(parking1Asset);
    ParkingAsset parking2Asset = createDemoParkingAsset("Lijnbaan", parkingGroupAsset, new GeoJSONPoint(4.47681, 51.91849));
    parking2Asset.setManufacturer("SKIDATA");
    parking2Asset.setModel("Barrier.Gate");
    parking2Asset.getAttribute(ParkingAsset.SPACES_OCCUPIED).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 31), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 24), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 38), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 46), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 48), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 52), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 89), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 142), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 246), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 231), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 367), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 345), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 386), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 312), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 363), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 276), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 249), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 256), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 123), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 153), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 83), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 25) })));
    });
    parking2Asset.setPriceHourly(3.50);
    parking2Asset.setPriceDaily(23.00);
    parking2Asset.setSpacesTotal(390);
    parking2Asset.getAttribute(ParkingAsset.SPACES_TOTAL).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.RULE_STATE));
    });
    parking2Asset.setId(UniqueIdentifierGenerator.generateId(parking2Asset.getName()));
    parking2Asset = assetStorageService.merge(parking2Asset);
    ParkingAsset parking3Asset = createDemoParkingAsset("Erasmusbrug", parkingGroupAsset, new GeoJSONPoint(4.48207, 51.91127));
    parking3Asset.setManufacturer("Kiestra");
    parking3Asset.setModel("Genius Rainbow");
    parking3Asset.getAttribute(ParkingAsset.SPACES_OCCUPIED).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 25), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 23), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 23), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 21), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 18), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 13), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 29), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 36), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 119), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 257), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 357), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 368), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 362), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 349), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 370), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 367), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 355), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 314), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 254), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 215), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 165), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 149), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 108), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 47) })));
    });
    parking3Asset.setPriceHourly(3.40);
    parking3Asset.setPriceDaily(20.00);
    parking3Asset.setSpacesTotal(373);
    parking3Asset.getAttribute(ParkingAsset.SPACES_TOTAL).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.RULE_STATE));
    });
    parking3Asset.setId(UniqueIdentifierGenerator.generateId(parking3Asset.getName()));
    parking3Asset = assetStorageService.merge(parking3Asset);
    // ### Crowd control ###
    ThingAsset assetAreaStation = new ThingAsset("Stationsplein");
    assetAreaStation.setParent(mobilityAndSafety).getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, STATIONSPLEIN_LOCATION), new Attribute<>(BuildingAsset.POSTAL_CODE, "3013 AK"), new Attribute<>(BuildingAsset.CITY, "Rotterdam"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"));
    assetAreaStation.setId(UniqueIdentifierGenerator.generateId(assetAreaStation.getName()));
    assetAreaStation = assetStorageService.merge(assetAreaStation);
    area1Id = assetAreaStation.getId();
    PeopleCounterAsset peopleCounter1Asset = createDemoPeopleCounterAsset("People Counter South", assetAreaStation, new GeoJSONPoint(4.470147, 51.923171), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    peopleCounter1Asset.setManufacturer("ViNotion");
    peopleCounter1Asset.setModel("ViSense");
    peopleCounter1Asset.getAttribute(PeopleCounterAsset.COUNT_GROWTH_PER_MINUTE).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0.2), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0.3), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0.1), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0.0), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0.2), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0.4), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0.5), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0.7), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 1.8), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 2.1), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 2.4), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 1.9), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 1.8), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 2.1), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 1.8), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 1.7), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 2.3), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 3.1), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 2.8), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 2.2), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 1.6), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 1.7), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 1.1), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0.8) })));
    });
    peopleCounter1Asset.setId(UniqueIdentifierGenerator.generateId(peopleCounter1Asset.getName()));
    peopleCounter1Asset = assetStorageService.merge(peopleCounter1Asset);
    Asset<?> peopleCounter2Asset = createDemoPeopleCounterAsset("People Counter North", assetAreaStation, new GeoJSONPoint(4.469329, 51.923700), () -> new SimulatorAgentLink(smartcitySimulatorAgentId));
    peopleCounter2Asset.setManufacturer("Axis");
    peopleCounter2Asset.setModel("P1375-E");
    peopleCounter2Asset.getAttribute(PeopleCounterAsset.COUNT_GROWTH_PER_MINUTE).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), 0.3), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), 0.2), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), 0.3), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), 0.1), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), 0.0), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), 0.3), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 0.7), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 0.6), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 1.9), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 2.2), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 2.8), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 1.6), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 1.9), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 2.2), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 1.9), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 1.6), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 2.4), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 3.2), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 2.9), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 2.3), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 1.7), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 1.4), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 1.2), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 0.7) })));
    });
    peopleCounter2Asset.setId(UniqueIdentifierGenerator.generateId(peopleCounter2Asset.getName()));
    peopleCounter2Asset = assetStorageService.merge(peopleCounter2Asset);
    MicrophoneAsset microphone1Asset = createDemoMicrophoneAsset("Microphone South", assetAreaStation, new GeoJSONPoint(4.470362, 51.923201), () -> new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), getRandomNumberInRange(50, 60)), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), getRandomNumberInRange(60, 70)), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), getRandomNumberInRange(60, 70)), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), getRandomNumberInRange(50, 60)) }));
    microphone1Asset.setManufacturer("Sorama");
    microphone1Asset.setModel("CAM1K");
    microphone1Asset.setId(UniqueIdentifierGenerator.generateId(microphone1Asset.getName()));
    microphone1Asset = assetStorageService.merge(microphone1Asset);
    MicrophoneAsset microphone2Asset = createDemoMicrophoneAsset("Microphone North", assetAreaStation, new GeoJSONPoint(4.469190, 51.923786), () -> new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.get(SECOND_OF_DAY), getRandomNumberInRange(50, 60)), new SimulatorReplayDatapoint(midnight.plusHours(1).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(2).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(3).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(4).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(5).get(SECOND_OF_DAY), getRandomNumberInRange(45, 50)), new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), getRandomNumberInRange(50, 55)), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), getRandomNumberInRange(60, 70)), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), getRandomNumberInRange(55, 60)), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), getRandomNumberInRange(60, 70)), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), getRandomNumberInRange(60, 65)), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), getRandomNumberInRange(50, 60)) }));
    microphone2Asset.setManufacturer("Sorama");
    microphone2Asset.setModel("CAM1K");
    microphone2Asset.setId(UniqueIdentifierGenerator.generateId(microphone2Asset.getName()));
    microphone2Asset = assetStorageService.merge(microphone2Asset);
    LightAsset lightStation1Asset = createDemoLightAsset("Station Light NW", assetAreaStation, new GeoJSONPoint(4.468874, 51.923881));
    lightStation1Asset.setManufacturer("Philips");
    lightStation1Asset.setModel("CityTouch");
    lightStation1Asset.setId(UniqueIdentifierGenerator.generateId(lightStation1Asset.getName()));
    lightStation1Asset = assetStorageService.merge(lightStation1Asset);
    LightAsset lightStation2Asset = createDemoLightAsset("Station Light NE", assetAreaStation, new GeoJSONPoint(4.470539, 51.923991));
    lightStation2Asset.setManufacturer("Philips");
    lightStation2Asset.setModel("CityTouch");
    lightStation2Asset.setId(UniqueIdentifierGenerator.generateId(lightStation2Asset.getName()));
    lightStation2Asset = assetStorageService.merge(lightStation2Asset);
    LightAsset lightStation3Asset = createDemoLightAsset("Station Light S", assetAreaStation, new GeoJSONPoint(4.470558, 51.923186));
    lightStation3Asset.setManufacturer("Philips");
    lightStation3Asset.setModel("CityTouch");
    lightStation3Asset.setId(UniqueIdentifierGenerator.generateId(lightStation3Asset.getName()));
    lightStation3Asset = assetStorageService.merge(lightStation3Asset);
    // ### Lighting controller ###
    LightAsset lightingControllerOPAsset = createDemoLightControllerAsset("Lighting Noordereiland", mobilityAndSafety, new GeoJSONPoint(4.496177, 51.915060));
    lightingControllerOPAsset.setManufacturer("Pharos");
    lightingControllerOPAsset.setModel("LPC X");
    lightingControllerOPAsset.setId(UniqueIdentifierGenerator.generateId(lightingControllerOPAsset.getName()));
    lightingControllerOPAsset = assetStorageService.merge(lightingControllerOPAsset);
    LightAsset lightOP1Asset = createDemoLightAsset("Ons Park 1", lightingControllerOPAsset, new GeoJSONPoint(4.49626, 51.91516));
    lightOP1Asset.setManufacturer("Schréder");
    lightOP1Asset.setModel("Axia 2");
    lightOP1Asset.setId(UniqueIdentifierGenerator.generateId(lightOP1Asset.getName()));
    lightOP1Asset = assetStorageService.merge(lightOP1Asset);
    LightAsset lightOP2Asset = createDemoLightAsset("Ons Park 2", lightingControllerOPAsset, new GeoJSONPoint(4.49705, 51.91549));
    lightOP2Asset.setManufacturer("Schréder");
    lightOP2Asset.setModel("Axia 2");
    lightOP2Asset.setId(UniqueIdentifierGenerator.generateId(lightOP2Asset.getName()));
    lightOP2Asset = assetStorageService.merge(lightOP2Asset);
    LightAsset lightOP3Asset = createDemoLightAsset("Ons Park 3", lightingControllerOPAsset, new GeoJSONPoint(4.49661, 51.91495));
    lightOP3Asset.setManufacturer("Schréder");
    lightOP3Asset.setModel("Axia 2");
    lightOP3Asset.setId(UniqueIdentifierGenerator.generateId(lightOP3Asset.getName()));
    lightOP3Asset = assetStorageService.merge(lightOP3Asset);
    LightAsset lightOP4Asset = createDemoLightAsset("Ons Park 4", lightingControllerOPAsset, new GeoJSONPoint(4.49704, 51.91520));
    lightOP4Asset.setManufacturer("Schréder");
    lightOP4Asset.setModel("Axia 2");
    lightOP4Asset.setId(UniqueIdentifierGenerator.generateId(lightOP4Asset.getName()));
    lightOP4Asset = assetStorageService.merge(lightOP4Asset);
    LightAsset lightOP5Asset = createDemoLightAsset("Ons Park 5", lightingControllerOPAsset, new GeoJSONPoint(4.49758, 51.91440));
    lightOP5Asset.setManufacturer("Schréder");
    lightOP5Asset.setModel("Axia 2");
    lightOP5Asset.setId(UniqueIdentifierGenerator.generateId(lightOP5Asset.getName()));
    lightOP5Asset = assetStorageService.merge(lightOP5Asset);
    LightAsset lightOP6Asset = createDemoLightAsset("Ons Park 6", lightingControllerOPAsset, new GeoJSONPoint(4.49786, 51.91452));
    lightOP6Asset.setManufacturer("Schréder");
    lightOP6Asset.setModel("Axia 2");
    lightOP6Asset.setId(UniqueIdentifierGenerator.generateId(lightOP6Asset.getName()));
    lightOP6Asset = assetStorageService.merge(lightOP6Asset);
    // ### Ships ###
    GroupAsset shipGroupAsset = new GroupAsset("Ship group", ShipAsset.class);
    shipGroupAsset.setParent(mobilityAndSafety);
    shipGroupAsset.setId(UniqueIdentifierGenerator.generateId(shipGroupAsset.getName()));
    shipGroupAsset = assetStorageService.merge(shipGroupAsset);
    ShipAsset ship1Asset = createDemoShipAsset("Hotel New York", shipGroupAsset, new GeoJSONPoint(4.482669, 51.916436));
    ship1Asset.setLength(12);
    ship1Asset.setShipType("Passenger");
    ship1Asset.setIMONumber(9183527);
    ship1Asset.setMSSINumber(244650537);
    ship1Asset.getAttribute(ShipAsset.DIRECTION).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(30).get(SECOND_OF_DAY), 7), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), 187), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(30).get(SECOND_OF_DAY), 7) })));
    });
    ship1Asset.getAttribute(Asset.LOCATION).ifPresent(assetAttribute -> {
        assetAttribute.addMeta(new MetaItem<>(MetaItemType.AGENT_LINK, new SimulatorAgentLink(smartcitySimulatorAgentId).setReplayData(new SimulatorReplayDatapoint[] { new SimulatorReplayDatapoint(midnight.plusHours(6).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(6).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(7).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(7).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(8).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(8).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(9).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(9).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(10).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(11).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(11).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(12).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(12).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(13).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(13).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(14).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(14).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(15).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(16).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(16).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(17).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(17).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(18).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(18).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(19).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(19).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(20).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(21).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(21).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(22).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(22).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(23).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(5).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(10).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(15).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(20).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(25).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(30).get(SECOND_OF_DAY), new GeoJSONPoint(4.484374, 51.903518)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(35).get(SECOND_OF_DAY), new GeoJSONPoint(4.479779, 51.904404)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(40).get(SECOND_OF_DAY), new GeoJSONPoint(4.482914, 51.906769)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(45).get(SECOND_OF_DAY), new GeoJSONPoint(4.486156, 51.908570)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(50).get(SECOND_OF_DAY), new GeoJSONPoint(4.483362, 51.911897)), new SimulatorReplayDatapoint(midnight.plusHours(23).plusMinutes(55).get(SECOND_OF_DAY), new GeoJSONPoint(4.482669, 51.916436)) })));
    });
    ship1Asset.setId(UniqueIdentifierGenerator.generateId(ship1Asset.getName()));
    ship1Asset = assetStorageService.merge(ship1Asset);
}
Also used : Attribute(org.openremote.model.attribute.Attribute) Tenant(org.openremote.model.security.Tenant) GeoJSONPoint(org.openremote.model.geo.GeoJSONPoint) HTTPAgentLink(org.openremote.agent.protocol.http.HTTPAgentLink) SimulatorAgent(org.openremote.agent.protocol.simulator.SimulatorAgent) SimulatorAgentLink(org.openremote.agent.protocol.simulator.SimulatorAgentLink) MetaItem(org.openremote.model.attribute.MetaItem) MultivaluedStringMap(org.openremote.model.value.ValueType.MultivaluedStringMap) LocalTime(java.time.LocalTime) SimulatorReplayDatapoint(org.openremote.model.simulator.SimulatorReplayDatapoint) HTTPAgent(org.openremote.agent.protocol.http.HTTPAgent)

Example 14 with Attribute

use of org.openremote.model.attribute.Attribute in project openremote by openremote.

the class ManagerTestSetup method onStart.

@Override
public void onStart() throws Exception {
    super.onStart();
    KeycloakTestSetup keycloakTestSetup = setupService.getTaskOfType(KeycloakTestSetup.class);
    Tenant masterTenant = keycloakTestSetup.masterTenant;
    Tenant tenantBuilding = keycloakTestSetup.tenantBuilding;
    Tenant tenantCity = keycloakTestSetup.tenantCity;
    masterRealm = masterTenant.getRealm();
    this.realmBuildingTenant = tenantBuilding.getRealm();
    this.realmCityTenant = tenantCity.getRealm();
    this.realmEnergyTenant = keycloakTestSetup.energyTenant.getRealm();
    // ################################ Assets for 'master' realm ###################################
    BuildingAsset smartOffice = new BuildingAsset("Smart office");
    smartOffice.setRealm(masterRealm);
    smartOffice.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_OFFICE_LOCATION), new Attribute<>(BuildingAsset.STREET, "Torenallee 20"), new Attribute<>(BuildingAsset.POSTAL_CODE, "5617"), new Attribute<>(BuildingAsset.CITY, "Eindhoven"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"));
    smartOffice = assetStorageService.merge(smartOffice);
    smartOfficeId = smartOffice.getId();
    Asset<?> groundFloor = new ThingAsset("Ground floor");
    groundFloor.setParent(smartOffice);
    groundFloor.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_OFFICE_LOCATION));
    groundFloor = assetStorageService.merge(groundFloor);
    groundFloorId = groundFloor.getId();
    RoomAsset lobby = new RoomAsset("Lobby");
    lobby.setParent(groundFloor);
    lobby.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_OFFICE_LOCATION), new Attribute<>("lobbyLocations", JSON_OBJECT.asArray()));
    lobby = assetStorageService.merge(lobby);
    lobbyId = lobby.getId();
    SimulatorAgent agent = new SimulatorAgent("Demo Agent");
    agent.setParent(lobby);
    agent.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_OFFICE_LOCATION));
    agent = assetStorageService.merge(agent);
    agentId = agent.getId();
    Asset<?> thing = new ThingAsset("Demo Thing");
    thing.setParent(agent);
    thing.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_OFFICE_LOCATION).addMeta(new MetaItem<>(RULE_STATE, true)), new Attribute<>(thingLightToggleAttributeName, BOOLEAN, true).addOrReplaceMeta(new MetaItem<>(LABEL, "Light 1 Toggle"), new MetaItem<>(STORE_DATA_POINTS, true), new MetaItem<>(DATA_POINTS_MAX_AGE_DAYS, DATA_POINTS_MAX_AGE_DAYS_DEFAULT * 7), new MetaItem<>(AGENT_LINK, new SimulatorAgentLink(agent.getId()))), new Attribute<>("light1Dimmer", POSITIVE_INTEGER).addOrReplaceMeta(new MetaItem<>(LABEL, "Light 1 Dimmer"), new MetaItem<>(AGENT_LINK, new SimulatorAgentLink(agent.getId())), new MetaItem<>(UNITS, Constants.units(UNITS_PERCENTAGE)), new MetaItem<>(CONSTRAINTS, ValueConstraint.constraints(new ValueConstraint.Min(0), new ValueConstraint.Max(100)))), new Attribute<>("light1Color", COLOUR_RGB, new ColourRGB(88, 123, 88)).addOrReplaceMeta(new MetaItem<>(LABEL, "Light 1 Color"), new MetaItem<>(AGENT_LINK, new SimulatorAgentLink(agent.getId()))), new Attribute<>("light1PowerConsumption", POSITIVE_NUMBER, 12.345).addOrReplaceMeta(new MetaItem<>(LABEL, "Light 1 Usage"), new MetaItem<>(READ_ONLY, true), new MetaItem<>(UNITS, Constants.units(UNITS_KILO, UNITS_WATT, UNITS_HOUR)), new MetaItem<>(AGENT_LINK, new SimulatorAgentLink(agent.getId()))));
    thing = assetStorageService.merge(thing);
    thingId = thing.getId();
    // ################################ Assets for 'energy' realm ###################################
    EnergyOptimisationAsset electricityOptimisationAsset = new EnergyOptimisationAsset("Optimisation");
    electricityOptimisationAsset.setIntervalSize(3d);
    electricityOptimisationAsset.setRealm(keycloakTestSetup.energyTenant.getRealm());
    electricityOptimisationAsset.setFinancialWeighting(100);
    electricityOptimisationAsset = assetStorageService.merge(electricityOptimisationAsset);
    electricityOptimisationAssetId = electricityOptimisationAsset.getId();
    ElectricityConsumerAsset electricityConsumerAsset = new ElectricityConsumerAsset("Consumer");
    electricityConsumerAsset.setParent(electricityOptimisationAsset);
    electricityConsumerAsset.getAttribute(ElectricityAsset.POWER).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricityConsumerAsset = assetStorageService.merge(electricityConsumerAsset);
    electricityConsumerAssetId = electricityConsumerAsset.getId();
    ElectricityProducerSolarAsset electricitySolarAsset = new ElectricityProducerSolarAsset("Producer");
    electricitySolarAsset.setParent(electricityOptimisationAsset);
    electricitySolarAsset.getAttribute(ElectricityAsset.POWER).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricitySolarAsset.setPanelOrientation(ElectricityProducerSolarAsset.PanelOrientation.SOUTH);
    electricitySolarAsset.setPanelAzimuth(0);
    electricitySolarAsset.setPanelPitch(30);
    electricitySolarAsset.setEfficiencyExport(100);
    electricitySolarAsset.setPowerExportMax(2.5);
    electricitySolarAsset.setLocation(new GeoJSONPoint(9.195285, 48.787418));
    electricitySolarAsset.setSetActualSolarValueWithForecast(true);
    electricitySolarAsset.setIncludeForecastSolarService(true);
    electricitySolarAsset = assetStorageService.merge(electricitySolarAsset);
    electricitySolarAssetId = electricitySolarAsset.getId();
    ElectricityProducerWindAsset electricityWindAsset = new ElectricityProducerWindAsset("Wind Turbine");
    electricityWindAsset.setParent(electricityOptimisationAsset);
    electricityWindAsset.getAttribute(ElectricityAsset.POWER).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricityWindAsset.setWindSpeedMax(18d);
    electricityWindAsset.setWindSpeedMin(2d);
    electricityWindAsset.setWindSpeedReference(12d);
    electricityWindAsset.setPowerExportMax(9000d);
    electricityWindAsset.setEfficiencyExport(100);
    electricityWindAsset.setPowerExportMax(2.5);
    electricityWindAsset.setLocation(new GeoJSONPoint(9.195285, 48.787418));
    electricityWindAsset.setSetActualWindValueWithForecast(true);
    electricityWindAsset.setIncludeForecastWindService(true);
    electricityWindAsset = assetStorageService.merge(electricityWindAsset);
    electricityWindAssetId = electricityWindAsset.getId();
    ElectricityBatteryAsset electricityBatteryAsset = new ElectricityBatteryAsset("Battery");
    electricityBatteryAsset.setParent(electricityOptimisationAsset);
    electricityBatteryAsset.setEnergyCapacity(200d);
    electricityBatteryAsset.setEnergyLevelPercentageMin(20);
    electricityBatteryAsset.setEnergyLevelPercentageMax(80);
    electricityBatteryAsset.setEnergyLevel(100d);
    electricityBatteryAsset.setPowerImportMax(7d);
    electricityBatteryAsset.setPowerExportMax(20d);
    electricityBatteryAsset.setPowerSetpoint(0d);
    electricityBatteryAsset.setEfficiencyImport(95);
    electricityBatteryAsset.setEfficiencyExport(98);
    electricityBatteryAsset.setSupportsExport(true);
    electricityBatteryAsset.setSupportsImport(true);
    electricityBatteryAsset.getAttribute(ElectricityAsset.POWER_SETPOINT).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricityBatteryAsset = assetStorageService.merge(electricityBatteryAsset);
    electricityBatteryAssetId = electricityBatteryAsset.getId();
    ElectricitySupplierAsset electricitySupplierAsset = new ElectricitySupplierAsset("Supplier");
    electricitySupplierAsset.setParent(electricityOptimisationAsset);
    electricitySupplierAsset.setTariffExport(-0.05);
    electricitySupplierAsset.setTariffImport(0.08);
    electricitySupplierAsset.getAttribute(ElectricityAsset.TARIFF_IMPORT).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricitySupplierAsset.getAttribute(ElectricityAsset.TARIFF_EXPORT).ifPresent(attr -> attr.addMeta(new MetaItem<>(HAS_PREDICTED_DATA_POINTS)));
    electricitySupplierAsset = assetStorageService.merge(electricitySupplierAsset);
    electricitySupplierAssetId = electricitySupplierAsset.getId();
    // ################################ Assets for 'building' realm ###################################
    BuildingAsset smartBuilding = new BuildingAsset("Smart building");
    smartBuilding.setRealm(this.realmBuildingTenant);
    smartBuilding.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, SMART_BUILDING_LOCATION), new Attribute<>(BuildingAsset.STREET, "Kastanjelaan 500"), new Attribute<>(BuildingAsset.POSTAL_CODE, "5616"), new Attribute<>(BuildingAsset.CITY, "Eindhoven"), new Attribute<>(BuildingAsset.COUNTRY, "Netherlands"));
    smartBuilding = assetStorageService.merge(smartBuilding);
    smartBuildingId = smartBuilding.getId();
    // The "Apartment 1" is the demo apartment with complex scenes
    BuildingAsset apartment1 = createDemoApartment(smartBuilding, "Apartment 1", new GeoJSONPoint(5.454233, 51.446800));
    apartment1.setParent(smartBuilding);
    apartment1.setAccessPublicRead(true);
    apartment1.getAttribute(Asset.LOCATION).ifPresent(locationAttr -> locationAttr.getMeta().addOrReplace(new MetaItem<>(ACCESS_PUBLIC_READ), new MetaItem<>(ACCESS_PUBLIC_WRITE)));
    apartment1 = assetStorageService.merge(apartment1);
    apartment1Id = apartment1.getId();
    SimulatorAgent apartment1ServiceAgent = new SimulatorAgent("Service Agent (Simulator)");
    apartment1ServiceAgent.setParent(apartment1);
    apartment1ServiceAgent = assetStorageService.merge(apartment1ServiceAgent);
    apartment1ServiceAgentId = apartment1ServiceAgent.getId();
    /* ############################ ROOMS ############################## */
    RoomAsset apartment1Livingroom = createDemoApartmentRoom(apartment1, "Living Room 1");
    apartment1Livingroom.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454213, 51.446884)), new Attribute<>("lightsCeiling", NUMBER, 0d).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true), new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)), new Attribute<>("lightsStand", BOOLEAN, true).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true), new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)));
    addDemoApartmentRoomMotionSensor(apartment1Livingroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentRoomCO2Sensor(apartment1Livingroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentRoomHumiditySensor(apartment1Livingroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentRoomThermometer(apartment1Livingroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentTemperatureControl(apartment1Livingroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    apartment1Livingroom.setId(apartment1LivingroomId);
    apartment1Livingroom = assetStorageService.merge(apartment1Livingroom);
    apartment1LivingroomId = apartment1Livingroom.getId();
    RoomAsset apartment1Kitchen = createDemoApartmentRoom(apartment1, "Kitchen 1");
    apartment1Kitchen.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454122, 51.446800)), new Attribute<>("lights", BOOLEAN, true).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true)).addMeta(new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)));
    addDemoApartmentRoomMotionSensor(apartment1Kitchen, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    for (String switchName : new String[] { "A", "B", "C" }) {
        addDemoApartmentSmartSwitch(apartment1Kitchen, switchName, true, attributeIndex -> {
            switch(attributeIndex) {
                case 2:
                case 3:
                case 4:
                    return new MetaItem[] { new MetaItem<>(AGENT_LINK, new SimulatorAgentLink(apartment1ServiceAgentId)) };
            }
            return null;
        });
    }
    apartment1Kitchen = assetStorageService.merge(apartment1Kitchen);
    apartment1KitchenId = apartment1Kitchen.getId();
    RoomAsset apartment1Hallway = createDemoApartmentRoom(apartment1, "Hallway 1");
    apartment1Hallway.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454342, 51.446762)), new Attribute<>("lights", BOOLEAN, true).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true)).addMeta(new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)));
    addDemoApartmentRoomMotionSensor(apartment1Hallway, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    apartment1Hallway = assetStorageService.merge(apartment1Hallway);
    apartment1HallwayId = apartment1Hallway.getId();
    RoomAsset apartment1Bedroom1 = createDemoApartmentRoom(apartment1, "Bedroom 1");
    apartment1Bedroom1.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454332, 51.446830)), new Attribute<>("lights", BOOLEAN, true).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true)).addMeta(new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)));
    addDemoApartmentRoomCO2Sensor(apartment1Bedroom1, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentRoomHumiditySensor(apartment1Bedroom1, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentRoomThermometer(apartment1Bedroom1, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentTemperatureControl(apartment1Bedroom1, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    apartment1Bedroom1 = assetStorageService.merge(apartment1Bedroom1);
    apartment1Bedroom1Id = apartment1Bedroom1.getId();
    RoomAsset apartment1Bathroom = new RoomAsset("Bathroom 1");
    apartment1Bathroom.setParent(apartment1);
    apartment1Bathroom.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454227, 51.446753)), new Attribute<>("lights", BOOLEAN, true).addMeta(new MetaItem<>(RULE_STATE, true), new MetaItem<>(ACCESS_RESTRICTED_READ, true), new MetaItem<>(ACCESS_RESTRICTED_WRITE, true)));
    addDemoApartmentRoomThermometer(apartment1Bathroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    addDemoApartmentTemperatureControl(apartment1Bathroom, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    apartment1Bathroom = assetStorageService.merge(apartment1Bathroom);
    apartment1BathroomId = apartment1Bathroom.getId();
    addDemoApartmentVentilation(apartment1, true, () -> new SimulatorAgentLink(apartment1ServiceAgentId));
    apartment1 = assetStorageService.merge(apartment1);
    apartment1Id = apartment1.getId();
    apartment2Id = UniqueIdentifierGenerator.generateId(tenantBuilding.getRealm() + "Apartment 2");
    BuildingAsset apartment2 = new BuildingAsset("Apartment 2");
    apartment2.setId(apartment2Id);
    apartment2.setParent(smartBuilding);
    apartment2.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454053, 51.446603)), new Attribute<>("allLightsOffSwitch", BOOLEAN, true).addMeta(new MetaItem<>(LABEL, "All Lights Off Switch"), new MetaItem<>(RULE_EVENT, true), new MetaItem<>(RULE_EVENT_EXPIRES, "PT3S")));
    apartment2 = assetStorageService.merge(apartment2);
    RoomAsset apartment2Livingroom = new RoomAsset("Living Room 2");
    apartment2Livingroom.setAccessPublicRead(true);
    apartment2Livingroom.setParent(apartment2);
    ObjectNode objectMap = ValueUtil.createJsonObject();
    objectMap.put("cactus", 0.8);
    apartment2Livingroom.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454109, 51.446631)).addMeta(new MetaItem<>(ACCESS_PUBLIC_READ)), new Attribute<>("motionSensor", BOOLEAN, false).addMeta(new MetaItem<>(LABEL, "Motion Sensor"), new MetaItem<>(RULE_STATE, true), new MetaItem<>(RULE_EVENT, true)), new Attribute<>("presenceDetected", BOOLEAN, false).addMeta(new MetaItem<>(LABEL, "Presence Detected"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("firstPresenceDetected", ValueType.TIMESTAMP).addMeta(new MetaItem<>(LABEL, "First Presence Timestamp"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("lastPresenceDetected", ValueType.TIMESTAMP).addMeta(new MetaItem<>(LABEL, "Last Presence Timestamp"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("co2Level", POSITIVE_INTEGER, 350).addMeta(new MetaItem<>(LABEL, "CO2 Level"), new MetaItem<>(UNITS, Constants.units(UNITS_PART_PER_MILLION)), new MetaItem<>(RULE_STATE, true)), new Attribute<>("lightSwitch", BOOLEAN, true).addMeta(new MetaItem<>(LABEL, "Light Switch"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("windowOpen", BOOLEAN, false).addMeta(new MetaItem<>(ACCESS_RESTRICTED_READ, true)), new Attribute<>("lightSwitchTriggerTimes", TEXT.asArray(), new String[] { "1800", "0830" }).addMeta(new MetaItem<>(LABEL, "Lightswitch Trigger Times"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("plantsWaterLevels", JSON_OBJECT, objectMap).addMeta(new MetaItem<>(LABEL, "Water levels of the plants"), new MetaItem<>(RULE_STATE, true)));
    apartment2Livingroom = assetStorageService.merge(apartment2Livingroom);
    apartment2LivingroomId = apartment2Livingroom.getId();
    RoomAsset apartment2Bathroom = new RoomAsset("Bathroom 2");
    apartment2Bathroom.setParent(apartment2);
    apartment2Bathroom.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.454015, 51.446665)), new Attribute<>("motionSensor", BOOLEAN, false).addMeta(new MetaItem<>(LABEL, "Motion Sensor"), new MetaItem<>(RULE_STATE, true), new MetaItem<>(RULE_EVENT, true)), new Attribute<>("presenceDetected", BOOLEAN, false).addMeta(new MetaItem<>(LABEL, "Presence Detected"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("firstPresenceDetected", ValueType.TIMESTAMP).addMeta(new MetaItem<>(LABEL, "First Presence Timestamp"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("lastPresenceDetected", ValueType.TIMESTAMP).addMeta(new MetaItem<>(LABEL, "Last Presence Timestamp"), new MetaItem<>(RULE_STATE, true)), new Attribute<>("lightSwitch", BOOLEAN, true).addMeta(new MetaItem<>(LABEL, "Light Switch"), new MetaItem<>(RULE_STATE, true)));
    apartment2Bathroom = assetStorageService.merge(apartment2Bathroom);
    apartment2BathroomId = apartment2Bathroom.getId();
    BuildingAsset apartment3 = new BuildingAsset("Apartment 3");
    apartment3.setParent(smartBuilding);
    apartment3.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.453859, 51.446379)));
    apartment3 = assetStorageService.merge(apartment3);
    apartment3Id = apartment3.getId();
    RoomAsset apartment3Livingroom = new RoomAsset("Living Room 3");
    apartment3Livingroom.setParent(apartment3);
    apartment3Livingroom.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, new GeoJSONPoint(5.453932, 51.446422)), new Attribute<>("lightSwitch", BOOLEAN));
    apartment3Livingroom = assetStorageService.merge(apartment3Livingroom);
    apartment3LivingroomId = apartment3Livingroom.getId();
    // ################################ Link users and assets ###################################
    assetStorageService.storeUserAssetLinks(Arrays.asList(new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1Id), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1LivingroomId), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1KitchenId), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1Bedroom1Id), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1BathroomId), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, apartment1HallwayId)));
    assetStorageService.storeUserAssetLinks(Arrays.asList(new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.buildingUserId, apartment2Id), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.buildingUserId, apartment2LivingroomId), new UserAssetLink(keycloakTestSetup.tenantBuilding.getRealm(), keycloakTestSetup.buildingUserId, apartment2BathroomId)));
    // ################################ Make users restricted ###################################
    ManagerIdentityProvider identityProvider = identityService.getIdentityProvider();
    identityProvider.updateUserRealmRoles(tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, identityProvider.addRealmRoles(tenantBuilding.getRealm(), keycloakTestSetup.testuser3Id, RESTRICTED_USER_REALM_ROLE));
    identityProvider.updateUserRealmRoles(tenantBuilding.getRealm(), keycloakTestSetup.buildingUserId, identityProvider.addRealmRoles(tenantBuilding.getRealm(), keycloakTestSetup.buildingUserId, RESTRICTED_USER_REALM_ROLE));
    // ################################ Realm smartcity ###################################
    CityAsset smartCity = new CityAsset("Smart city");
    smartCity.setRealm(this.realmCityTenant);
    smartCity.addOrReplaceAttributes(new Attribute<>(Asset.LOCATION, SMART_CITY_LOCATION), new Attribute<>(CityAsset.CITY, "Eindhoven"), new Attribute<>(CityAsset.COUNTRY, "Netherlands"));
    smartCity = assetStorageService.merge(smartCity);
    SimulatorAgent smartCityServiceAgent = new SimulatorAgent("Service Agent (Simulator)");
    smartCityServiceAgent.setParent(smartCity);
    smartCityServiceAgent = assetStorageService.merge(smartCityServiceAgent);
    smartCityServiceAgentId = smartCityServiceAgent.getId();
    // ################################ Realm B Area 1 ###################################
    Asset<?> assetArea1 = new ThingAsset("Area 1");
    assetArea1.setParent(smartCity);
    assetArea1.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, AREA_1_LOCATION));
    assetArea1 = assetStorageService.merge(assetArea1);
    area1Id = assetArea1.getId();
    PeopleCounterAsset peopleCounter1Asset = createDemoPeopleCounterAsset("PeopleCounter 1", assetArea1, new GeoJSONPoint(5.477126, 51.439137), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    peopleCounter1Asset = assetStorageService.merge(peopleCounter1Asset);
    Asset<?> microphone1Asset = createDemoMicrophoneAsset("Microphone 1", assetArea1, new GeoJSONPoint(5.478092, 51.438655), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    microphone1Asset = assetStorageService.merge(microphone1Asset);
    microphone1Id = microphone1Asset.getId();
    Asset<?> enviroment1Asset = createDemoEnvironmentAsset("Environment 1", assetArea1, new GeoJSONPoint(5.478907, 51.438943), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    enviroment1Asset = assetStorageService.merge(enviroment1Asset);
    Asset<?> light1Asset = createDemoLightAsset("Light 1", assetArea1, new GeoJSONPoint(5.476111, 51.438492));
    light1Asset = assetStorageService.merge(light1Asset);
    Asset<?> light2Asset = createDemoLightAsset("Light 2", assetArea1, new GeoJSONPoint(5.477272, 51.439214));
    light2Asset = assetStorageService.merge(light2Asset);
    // ################################ Realm B Area 2 ###################################
    Asset<?> assetArea2 = new ThingAsset("Area 2");
    assetArea2.setParent(smartCity);
    assetArea2.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, AREA_2_LOCATION));
    assetArea2 = assetStorageService.merge(assetArea2);
    Asset<?> peopleCounter2Asset = createDemoPeopleCounterAsset("PeopleCounter 2", assetArea2, new GeoJSONPoint(5.473686, 51.438603), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    peopleCounter2Asset = assetStorageService.merge(peopleCounter2Asset);
    Asset<?> environment2Asset = createDemoEnvironmentAsset("Environment 2", assetArea2, new GeoJSONPoint(5.473552, 51.438412), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    environment2Asset = assetStorageService.merge(environment2Asset);
    // ################################ Realm B Area 3 ###################################
    Asset<?> assetArea3 = new ThingAsset("Area 3");
    assetArea3.setParent(smartCity);
    assetArea3.getAttributes().addOrReplace(new Attribute<>(Asset.LOCATION, AREA_3_LOCATION));
    assetArea3 = assetStorageService.merge(assetArea3);
    Asset<?> peopleCounter3Asset = createDemoPeopleCounterAsset("PeopleCounter 3", assetArea3, new GeoJSONPoint(5.487234, 51.447065), () -> new SimulatorAgentLink(smartCityServiceAgentId));
    peopleCounter3Asset = assetStorageService.merge(peopleCounter3Asset);
    peopleCounter3AssetId = peopleCounter3Asset.getId();
    LightAsset lightController_3Asset = createDemoLightControllerAsset("LightController 3", assetArea3, new GeoJSONPoint(5.487478, 51.446979));
    lightController_3Asset = assetStorageService.merge(lightController_3Asset);
}
Also used : Attribute(org.openremote.model.attribute.Attribute) UserAssetLink(org.openremote.model.asset.UserAssetLink) Tenant(org.openremote.model.security.Tenant) ManagerIdentityProvider(org.openremote.manager.security.ManagerIdentityProvider) GeoJSONPoint(org.openremote.model.geo.GeoJSONPoint) SimulatorAgent(org.openremote.agent.protocol.simulator.SimulatorAgent) SimulatorAgentLink(org.openremote.agent.protocol.simulator.SimulatorAgentLink) MetaItem(org.openremote.model.attribute.MetaItem) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ColourRGB(org.openremote.model.value.impl.ColourRGB)

Example 15 with Attribute

use of org.openremote.model.attribute.Attribute in project openremote by openremote.

the class HTTPProtocol method doLinkAttribute.

@Override
protected void doLinkAttribute(String assetId, Attribute<?> attribute, HTTPAgentLink agentLink) {
    AttributeRef attributeRef = new AttributeRef(assetId, attribute.getName());
    String method = agentLink.getMethod().map(Enum::name).orElse(DEFAULT_HTTP_METHOD);
    String path = agentLink.getPath().orElse(null);
    String contentType = agentLink.getContentType().orElse(null);
    Map<String, List<String>> headers = agentLink.getHeaders().orElse(null);
    Map<String, List<String>> queryParams = agentLink.getQueryParameters().orElse(null);
    Integer pollingMillis = agentLink.getPollingMillis().map(millis -> Math.max(millis, MIN_POLLING_MILLIS)).orElse(null);
    boolean pagingEnabled = agentLink.getPagingMode().orElse(false);
    String pollingAttribute = agentLink.getPollingAttribute().orElse(null);
    if (!TextUtil.isNullOrEmpty(pollingAttribute)) {
        synchronized (pollingLinkedAttributeMap) {
            AttributeRef pollingSourceRef = new AttributeRef(attributeRef.getId(), pollingAttribute);
            pollingLinkedAttributeMap.compute(pollingSourceRef, (ref, links) -> {
                if (links == null) {
                    links = new HashSet<>();
                }
                links.add(attributeRef);
                return links;
            });
        }
    }
    String body = agentLink.getWriteValue().orElse(null);
    if (client == null) {
        LOG.warning("Client is undefined: " + this);
        return;
    }
    HttpClientRequest clientRequest = buildClientRequest(path, method, headers != null ? WebTargetBuilder.mapToMultivaluedMap(headers, new MultivaluedHashMap<>()) : null, queryParams != null ? WebTargetBuilder.mapToMultivaluedMap(queryParams, new MultivaluedHashMap<>()) : null, pagingEnabled, contentType);
    LOG.fine("Creating HTTP request for attributeRef '" + clientRequest + "': " + attributeRef);
    requestMap.put(attributeRef, clientRequest);
    Optional.ofNullable(pollingMillis).ifPresent(seconds -> pollingMap.put(attributeRef, schedulePollingRequest(attributeRef, agentLink, clientRequest, body, seconds)));
}
Also used : java.util(java.util) ScheduledFuture(java.util.concurrent.ScheduledFuture) Protocol(org.openremote.model.asset.agent.Protocol) ConnectionStatus(org.openremote.model.asset.agent.ConnectionStatus) URISyntaxException(java.net.URISyntaxException) AttributeRef(org.openremote.model.attribute.AttributeRef) ResponseBuilderImpl(org.jboss.resteasy.specimpl.ResponseBuilderImpl) ValueUtil(org.openremote.model.util.ValueUtil) ResteasyWebTarget(org.jboss.resteasy.client.jaxrs.ResteasyWebTarget) HttpMethod(javax.ws.rs.HttpMethod) WebTargetBuilder(org.openremote.container.web.WebTargetBuilder) Level(java.util.logging.Level) AgentLink(org.openremote.model.asset.agent.AgentLink) MediaType(javax.ws.rs.core.MediaType) Attribute(org.openremote.model.attribute.Attribute) AttributeEvent(org.openremote.model.attribute.AttributeEvent) SyslogCategory(org.openremote.model.syslog.SyslogCategory) TextUtil(org.openremote.model.util.TextUtil) URI(java.net.URI) AttributeState(org.openremote.model.attribute.AttributeState) OAuthGrant(org.openremote.model.auth.OAuthGrant) ValueType(org.openremote.model.value.ValueType) QUERY_PARAMETERS_PROPERTY(org.openremote.container.web.QueryParameterInjectorFilter.QUERY_PARAMETERS_PROPERTY) URIBuilder(org.apache.http.client.utils.URIBuilder) Invocation(javax.ws.rs.client.Invocation) Logger(java.util.logging.Logger) Entity(javax.ws.rs.client.Entity) MultivaluedHashMap(javax.ws.rs.core.MultivaluedHashMap) AbstractProtocol(org.openremote.agent.protocol.AbstractProtocol) Container(org.openremote.model.Container) PROTOCOL(org.openremote.model.syslog.SyslogCategory.PROTOCOL) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) BuiltResponse(org.jboss.resteasy.specimpl.BuiltResponse) Headers(org.jboss.resteasy.core.Headers) Response(javax.ws.rs.core.Response) Type(java.lang.reflect.Type) ResteasyClient(org.jboss.resteasy.client.jaxrs.ResteasyClient) Annotation(java.lang.annotation.Annotation) WebTargetBuilder.createClient(org.openremote.container.web.WebTargetBuilder.createClient) UsernamePassword(org.openremote.model.auth.UsernamePassword) WebTarget(javax.ws.rs.client.WebTarget) QueryParameterInjectorFilter(org.openremote.container.web.QueryParameterInjectorFilter) ProtocolUtil(org.openremote.model.protocol.ProtocolUtil) GlobalLock.withLock(org.openremote.container.concurrent.GlobalLock.withLock) AttributeRef(org.openremote.model.attribute.AttributeRef)

Aggregations

Attribute (org.openremote.model.attribute.Attribute)18 Logger (java.util.logging.Logger)13 Level (java.util.logging.Level)11 AttributeEvent (org.openremote.model.attribute.AttributeEvent)10 Consumer (java.util.function.Consumer)9 Container (org.openremote.model.Container)9 ValueUtil (org.openremote.model.util.ValueUtil)9 java.util (java.util)8 AttributeState (org.openremote.model.attribute.AttributeState)8 SyslogCategory (org.openremote.model.syslog.SyslogCategory)8 ConnectionStatus (org.openremote.model.asset.agent.ConnectionStatus)7 AttributeRef (org.openremote.model.attribute.AttributeRef)7 Pair (org.openremote.model.util.Pair)7 MetaItemType (org.openremote.model.value.MetaItemType)7 Asset (org.openremote.model.asset.Asset)6 Map (java.util.Map)5 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)5 TimeUnit (java.util.concurrent.TimeUnit)5 Collectors (java.util.stream.Collectors)5 AbstractProtocol (org.openremote.agent.protocol.AbstractProtocol)5