Search in sources :

Example 1 with ConfigChannel

use of io.openems.api.channel.ConfigChannel in project openems by OpenEMS.

the class EdgeWebsocketHandler method config.

/**
 * Handle "config" messages
 *
 * @param jConfig
 * @return
 */
private synchronized void config(Role role, JsonObject jMessageId, Optional<ApiWorker> apiWorkerOpt, JsonObject jConfig) {
    Optional<String> modeOpt = JsonUtils.getAsOptionalString(jConfig, "mode");
    switch(modeOpt.orElse("")) {
        case "query":
            /*
			 * Query current config
			 */
            try {
                String language = JsonUtils.getAsString(jConfig, "language");
                JsonObject jReplyConfig = Config.getInstance().getJson(ConfigFormat.OPENEMS_UI, role, language);
                WebSocketUtils.send(this.websocket, DefaultMessages.configQueryReply(jMessageId, jReplyConfig));
                return;
            } catch (OpenemsException e) {
                WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.UNABLE_TO_READ_CURRENT_CONFIG, e.getMessage());
            }
        case "update":
            /*
			 * Update thing/channel config
			 */
            Optional<String> thingIdOpt = JsonUtils.getAsOptionalString(jConfig, "thing");
            Optional<String> channelIdOpt = JsonUtils.getAsOptionalString(jConfig, "channel");
            try {
                String thingId = thingIdOpt.get();
                String channelId = channelIdOpt.get();
                JsonElement jValue = JsonUtils.getSubElement(jConfig, "value");
                Optional<Channel> channelOpt = ThingRepository.getInstance().getChannel(thingId, channelId);
                if (channelOpt.isPresent()) {
                    Channel channel = channelOpt.get();
                    // check write permissions
                    channel.assertWriteAllowed(role);
                    if (channel instanceof ConfigChannel<?>) {
                        /*
						 * ConfigChannel
						 */
                        ConfigChannel<?> configChannel = (ConfigChannel<?>) channel;
                        Object value = ConfigUtils.getConfigObject(configChannel, jValue);
                        configChannel.updateValue(value, true);
                        WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.EDGE_CHANNEL_UPDATE_SUCCESS, channel.address() + " => " + jValue);
                    } else if (channel instanceof WriteChannel<?>) {
                        /*
						 * WriteChannel
						 */
                        WriteChannel<?> writeChannel = (WriteChannel<?>) channel;
                        if (!apiWorkerOpt.isPresent()) {
                            WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.BACKEND_NOT_ALLOWED, "set " + channel.address() + " => " + jValue);
                        } else {
                            ApiWorker apiWorker = apiWorkerOpt.get();
                            WriteObject writeObject = new WriteJsonObject(jValue).onFirstSuccess(() -> {
                                WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.EDGE_CHANNEL_UPDATE_SUCCESS, "set " + channel.address() + " => " + jValue);
                            }).onFirstError((e) -> {
                                WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.EDGE_CHANNEL_UPDATE_FAILED, "set " + channel.address() + " => " + jValue, e.getMessage());
                            }).onTimeout(() -> {
                                WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.EDGE_CHANNEL_UPDATE_TIMEOUT, "set " + channel.address() + " => " + jValue);
                            });
                            apiWorker.addValue(writeChannel, writeObject);
                        }
                    }
                } else {
                    WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.CHANNEL_NOT_FOUND, thingId + "/" + channelId);
                }
            } catch (NoSuchElementException | OpenemsException e) {
                WebSocketUtils.sendNotificationOrLogError(this.websocket, jMessageId, LogBehaviour.WRITE_TO_LOG, Notification.EDGE_CHANNEL_UPDATE_FAILED, thingIdOpt.orElse("UNDEFINED") + "/" + channelIdOpt.orElse("UNDEFINED"), e.getMessage());
            }
    }
}
Also used : ApiWorker(io.openems.core.utilities.api.ApiWorker) ConfigChannel(io.openems.api.channel.ConfigChannel) WriteChannel(io.openems.api.channel.WriteChannel) ConfigChannel(io.openems.api.channel.ConfigChannel) Channel(io.openems.api.channel.Channel) JsonObject(com.google.gson.JsonObject) WriteJsonObject(io.openems.core.utilities.api.WriteJsonObject) OpenemsException(io.openems.common.exceptions.OpenemsException) JsonElement(com.google.gson.JsonElement) WriteChannel(io.openems.api.channel.WriteChannel) JsonObject(com.google.gson.JsonObject) WriteObject(io.openems.core.utilities.api.WriteObject) WriteJsonObject(io.openems.core.utilities.api.WriteJsonObject) WriteJsonObject(io.openems.core.utilities.api.WriteJsonObject) NoSuchElementException(java.util.NoSuchElementException) WriteObject(io.openems.core.utilities.api.WriteObject)

Example 2 with ConfigChannel

use of io.openems.api.channel.ConfigChannel in project openems by OpenEMS.

the class ChannelRegisterMap method setValue.

protected void setValue(MyRegister register, byte b1, byte b2) throws OpenemsException {
    int registerNo = register.getRegisterNo();
    this.setBuffer[registerNo * 2] = b1;
    this.setBuffer[registerNo * 2 + 1] = b2;
    // is the buffer full?
    for (int i = 0; i < this.setBuffer.length; i++) {
        if (this.setBuffer[i] == null) {
            // no, it is not full
            return;
        }
    }
    // yes, it is full -> parse value to Object
    byte[] value = new byte[this.setBuffer.length];
    boolean isPositive = true;
    for (int i = this.setBuffer.length - 1; i > 0; i -= 2) {
        if (((this.setBuffer[i - 1] >>> 8) & 1) != 0) {
            // test if the 'negative-bit' is set
            isPositive = false;
        }
        value[i] = this.setBuffer[i];
        value[i - 1] = this.setBuffer[i - 1];
    }
    if (!isPositive) {
        // fill leading bytes with 0xFF if the value is negative
        for (int i = 0; i < value.length; i++) {
            if (value[i] != 0) {
                break;
            }
            value[i] = (byte) 0xff;
        }
    }
    // int bitLength = getBitLength(type);
    // System.out.println(bitLength + " - " + bytesToHex(value));
    Object valueObj = BitUtils.toObject(this.channelDoc.getTypeOpt().get(), value);
    Channel channel = this.getChannel();
    if (channel instanceof ConfigChannel<?>) {
        // it is a ConfigChannel -> write directly
        ConfigChannel<?> configChannel = (ConfigChannel<?>) channel;
        configChannel.updateValue(valueObj, true);
        log.info("Updated [" + this.channelAddress + "] to [" + valueObj + "] via Modbus/TCP.");
    } else if (channel instanceof WriteChannel<?>) {
        // it is a WriteChannel -> handle by ApiWorker
        WriteChannel<?> writeChannel = (WriteChannel<?>) channel;
        WritePOJO writeObject = new WritePOJO(valueObj);
        apiWorker.addValue(writeChannel, writeObject);
    }
}
Also used : ConfigChannel(io.openems.api.channel.ConfigChannel) WriteChannel(io.openems.api.channel.WriteChannel) ConfigChannel(io.openems.api.channel.ConfigChannel) Channel(io.openems.api.channel.Channel) WriteChannel(io.openems.api.channel.WriteChannel) WritePOJO(io.openems.core.utilities.api.WritePOJO)

Example 3 with ConfigChannel

use of io.openems.api.channel.ConfigChannel in project openems by OpenEMS.

the class ConfigUtils method getAsJsonElement.

/**
 * Converts an object to a JsonElement
 *
 * @param value
 * @return
 * @throws NotImplementedException
 */
public static JsonElement getAsJsonElement(Object value, ConfigFormat format, Role role) throws NotImplementedException {
    // null
    if (value == null) {
        return null;
    }
    // optional
    if (value instanceof Optional<?>) {
        if (!((Optional<?>) value).isPresent()) {
            return null;
        } else {
            value = ((Optional<?>) value).get();
        }
    }
    try {
        /*
			 * test for simple types
			 */
        return JsonUtils.getAsJsonElement(value);
    } catch (NotImplementedException e) {
        ;
    }
    if (value instanceof Thing) {
        /*
			 * type Thing
			 */
        Thing thing = (Thing) value;
        JsonObject j = new JsonObject();
        if (format == ConfigFormat.OPENEMS_UI || !thing.id().startsWith("_")) {
            // ignore generated id names starting with "_"
            j.addProperty("id", thing.id());
            j.addProperty("alias", thing.getAlias());
        }
        // for file-format class is not needed for DeviceNatures
        j.addProperty("class", thing.getClass().getCanonicalName());
        ThingRepository thingRepository = ThingRepository.getInstance();
        for (ConfigChannel<?> channel : thingRepository.getConfigChannels(thing)) {
            if (channel.isReadAllowed(role)) {
                // check read permissions
                JsonElement jChannel = null;
                jChannel = ConfigUtils.getAsJsonElement(channel, format, role);
                if (jChannel != null) {
                    j.add(channel.id(), jChannel);
                }
            }
        }
        // for Bridge: add 'devices' array of thingIds
        if (value instanceof Bridge) {
            Bridge bridge = (Bridge) value;
            JsonArray jDevices = new JsonArray();
            for (Device device : bridge.getDevices()) {
                jDevices.add(device.id());
            }
            j.add("devices", jDevices);
        }
        return j;
    } else if (value instanceof ConfigChannel<?>) {
        /*
			 * type ConfigChannel
			 */
        ConfigChannel<?> channel = (ConfigChannel<?>) value;
        if (!channel.valueOptional().isPresent()) {
            // no value set
            return null;
        } else if (format == ConfigFormat.FILE && channel.getDefaultValue().equals(channel.valueOptional())) {
            // default value not changed
            return null;
        } else {
            // recursive call
            return ConfigUtils.getAsJsonElement(channel.valueOptional().get(), format, role);
        }
    } else if (value instanceof ThingMap) {
        /*
			 * ThingMap (we need only id)
			 */
        return new JsonPrimitive(((ThingMap) value).id());
    } else if (value instanceof List<?>) {
        /*
			 * List
			 */
        JsonArray jArray = new JsonArray();
        for (Object v : (List<?>) value) {
            jArray.add(ConfigUtils.getAsJsonElement(v, format, role));
        }
        return jArray;
    } else if (value instanceof Set<?>) {
        /*
			 * Set
			 */
        JsonArray jArray = new JsonArray();
        for (Object v : (Set<?>) value) {
            jArray.add(ConfigUtils.getAsJsonElement(v, format, role));
        }
        return jArray;
    }
    throw new NotImplementedException(// 
    "Converter for [" + value + "]" + " of type [" + value.getClass().getSimpleName() + // 
    "]" + " to JSON is not implemented.");
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) Optional(java.util.Optional) JsonPrimitive(com.google.gson.JsonPrimitive) Device(io.openems.api.device.Device) ConfigChannel(io.openems.api.channel.ConfigChannel) NotImplementedException(io.openems.common.exceptions.NotImplementedException) JsonObject(com.google.gson.JsonObject) ThingRepository(io.openems.core.ThingRepository) JsonArray(com.google.gson.JsonArray) JsonElement(com.google.gson.JsonElement) JsonObject(com.google.gson.JsonObject) ThingMap(io.openems.api.controller.ThingMap) Thing(io.openems.api.thing.Thing) Bridge(io.openems.api.bridge.Bridge)

Example 4 with ConfigChannel

use of io.openems.api.channel.ConfigChannel in project openems by OpenEMS.

the class ThingRepository method addThing.

/**
 * Add a Thing to the Repository and cache its Channels and other information for later usage.
 *
 * @param thing
 */
public synchronized void addThing(Thing thing) {
    if (thingIds.containsValue(thing)) {
        // Thing was already added
        return;
    }
    // Add to thingIds
    thingIds.forcePut(thing.id(), thing);
    // Add to thingClasses
    thingClasses.put(thing.getClass(), thing);
    // Add to bridges
    if (thing instanceof Bridge) {
        bridges.add((Bridge) thing);
    }
    // Add to schedulers
    if (thing instanceof Scheduler) {
        schedulers.add((Scheduler) thing);
    }
    // Add to persistences
    if (thing instanceof Persistence) {
        persistences.add((Persistence) thing);
    }
    // Add to queryablePersistences
    if (thing instanceof QueryablePersistence) {
        queryablePersistences.add((QueryablePersistence) thing);
    }
    // Add to device natures
    if (thing instanceof DeviceNature) {
        deviceNatures.add((DeviceNature) thing);
    }
    // Add Listener
    thing.addListener(this);
    // Apply channel annotation (this happens now and again after initializing the thing via init()
    this.applyChannelAnnotation(thing);
    // Add Channels thingConfigChannels
    ThingDoc thingDoc = classRepository.getThingDoc(thing.getClass());
    for (ChannelDoc channelDoc : thingDoc.getChannelDocs()) {
        Member member = channelDoc.getMember();
        try {
            List<Channel> channels = new ArrayList<>();
            java.util.function.Consumer<Channel> addToChannels = (c) -> {
                if (c == null) {
                // TODO this error is not handled properly
                // log.error(
                // "Channel is returning null! Thing [" + thing.id() + "], Member [" + member.getName() + "]");
                } else {
                    channels.add(c);
                }
            };
            if (member instanceof Method) {
                if (((Method) member).getReturnType().isArray()) {
                    Channel[] ch = (Channel[]) ((Method) member).invoke(thing);
                    for (Channel c : ch) {
                        addToChannels.accept(c);
                    }
                } else {
                    // It's a Method with ReturnType Channel
                    Channel c = (Channel) ((Method) member).invoke(thing);
                    addToChannels.accept(c);
                    if (c instanceof ThingStateChannels) {
                        ThingStateChannels tsc = (ThingStateChannels) c;
                        for (ThingStateChannel fc : tsc.getFaultChannels()) {
                            addToChannels.accept(fc);
                        }
                        for (ThingStateChannel wc : tsc.getWarningChannels()) {
                            addToChannels.accept(wc);
                        }
                    }
                }
            } else if (member instanceof Field) {
                // It's a Field with Type Channel
                Channel c = (Channel) ((Field) member).get(thing);
                addToChannels.accept(c);
            } else {
                continue;
            }
            if (channels.isEmpty()) {
                continue;
            }
            for (Channel channel : channels) {
                // Add Channel to thingChannels
                thingChannels.put(thing, channel.id(), channel);
                if (channel instanceof ConfigChannel) {
                    // Add Channel to configChannels
                    thingConfigChannels.put(thing, (ConfigChannel<?>) channel);
                }
            }
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            log.warn("Unable to add Channel. Member [" + member.getName() + "]", e);
        }
    }
    for (ThingsChangedListener listener : thingListeners) {
        listener.thingChanged(thing, Action.ADD);
    }
}
Also used : ReadChannel(io.openems.api.channel.ReadChannel) JsonObject(com.google.gson.JsonObject) Controller(io.openems.api.controller.Controller) OpenemsException(io.openems.common.exceptions.OpenemsException) LoggerFactory(org.slf4j.LoggerFactory) WriteChannel(io.openems.api.channel.WriteChannel) HashBasedTable(com.google.common.collect.HashBasedTable) ConfigChannel(io.openems.api.channel.ConfigChannel) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) HashMultimap(com.google.common.collect.HashMultimap) Bridge(io.openems.api.bridge.Bridge) Map(java.util.Map) DeviceNature(io.openems.api.device.nature.DeviceNature) Scheduler(io.openems.api.scheduler.Scheduler) LinkedList(java.util.LinkedList) Method(java.lang.reflect.Method) BiMap(com.google.common.collect.BiMap) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Member(java.lang.reflect.Member) Collection(java.util.Collection) JsonUtils(io.openems.common.utils.JsonUtils) Set(java.util.Set) Thing(io.openems.api.thing.Thing) ThingChannelsUpdatedListener(io.openems.api.thing.ThingChannelsUpdatedListener) Field(java.lang.reflect.Field) QueryablePersistence(io.openems.api.persistence.QueryablePersistence) InvocationTargetException(java.lang.reflect.InvocationTargetException) Device(io.openems.api.device.Device) Action(io.openems.core.ThingsChangedListener.Action) List(java.util.List) HashBiMap(com.google.common.collect.HashBiMap) ThingStateChannels(io.openems.api.channel.thingstate.ThingStateChannels) InjectionUtils(io.openems.core.utilities.InjectionUtils) Entry(java.util.Map.Entry) ConfigUtils(io.openems.core.utilities.ConfigUtils) Optional(java.util.Optional) Persistence(io.openems.api.persistence.Persistence) ChannelAddress(io.openems.common.types.ChannelAddress) ChannelDoc(io.openems.api.doc.ChannelDoc) ThingDoc(io.openems.api.doc.ThingDoc) Collections(java.util.Collections) Table(com.google.common.collect.Table) ThingStateChannel(io.openems.api.channel.ThingStateChannel) Channel(io.openems.api.channel.Channel) Scheduler(io.openems.api.scheduler.Scheduler) ConfigChannel(io.openems.api.channel.ConfigChannel) ArrayList(java.util.ArrayList) ThingStateChannels(io.openems.api.channel.thingstate.ThingStateChannels) ThingStateChannel(io.openems.api.channel.ThingStateChannel) Field(java.lang.reflect.Field) QueryablePersistence(io.openems.api.persistence.QueryablePersistence) DeviceNature(io.openems.api.device.nature.DeviceNature) Member(java.lang.reflect.Member) ThingDoc(io.openems.api.doc.ThingDoc) ReadChannel(io.openems.api.channel.ReadChannel) WriteChannel(io.openems.api.channel.WriteChannel) ConfigChannel(io.openems.api.channel.ConfigChannel) ThingStateChannel(io.openems.api.channel.ThingStateChannel) Channel(io.openems.api.channel.Channel) Method(java.lang.reflect.Method) ChannelDoc(io.openems.api.doc.ChannelDoc) InvocationTargetException(java.lang.reflect.InvocationTargetException) QueryablePersistence(io.openems.api.persistence.QueryablePersistence) Persistence(io.openems.api.persistence.Persistence) Bridge(io.openems.api.bridge.Bridge)

Example 5 with ConfigChannel

use of io.openems.api.channel.ConfigChannel in project openems by OpenEMS.

the class ThingRepository method thingChannelsUpdated.

@Override
public void thingChannelsUpdated(Thing thing) {
    // remove Channels from thingChannels, thingWriteChannels
    Databus databus = Databus.getInstance();
    Set<Entry<String, Channel>> thingRow = thingChannels.row(thing).entrySet();
    Iterator<Entry<String, Channel>> i = thingRow.iterator();
    while (i.hasNext()) {
        Entry<String, Channel> thingChannel = i.next();
        if (!(thingChannel.getValue() instanceof ConfigChannel)) {
            thingChannel.getValue().removeChangeListener(databus);
            thingChannel.getValue().removeUpdateListener(databus);
            i.remove();
        }
    }
    thingWriteChannels.removeAll(thing);
    // Add Channels to thingChannels, thingConfigChannels and thingWriteChannels
    ThingDoc thingDoc = classRepository.getThingDoc(thing.getClass());
    for (ChannelDoc channelDoc : thingDoc.getChannelDocs()) {
        Member member = channelDoc.getMember();
        try {
            List<Channel> channels = new ArrayList<>();
            boolean ignoreEmpty = false;
            if (member instanceof Method) {
                if (((Method) member).getReturnType().isArray()) {
                    // ignore e.g. if getFaultChannels is returning an empty array
                    ignoreEmpty = true;
                    Channel[] ch = (Channel[]) ((Method) member).invoke(thing);
                    for (Channel c : ch) {
                        channels.add(c);
                    }
                } else {
                    // It's a Method with ReturnType Channel
                    channels.add((Channel) ((Method) member).invoke(thing));
                }
            } else if (member instanceof Field) {
                // It's a Field with Type Channel
                channels.add((Channel) ((Field) member).get(thing));
            } else {
                continue;
            }
            if (!ignoreEmpty && channels.isEmpty()) {
                log.warn("Channel is returning null! Thing [" + thing.id() + "], Member [" + member.getName() + "]");
                continue;
            }
            for (Channel channel : channels) {
                if (channel != null) {
                    // Add Channel to thingChannels
                    thingChannels.put(thing, channel.id(), channel);
                    // Add Channel to writeChannels
                    if (channel instanceof WriteChannel) {
                        thingWriteChannels.put(thing, (WriteChannel<?>) channel);
                    }
                    // Register Databus as listener
                    if (channel instanceof ReadChannel) {
                        ((ReadChannel<?>) channel).addUpdateListener(databus);
                        ((ReadChannel<?>) channel).addChangeListener(databus);
                    }
                }
            }
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            log.warn("Unable to add Channel. Member [" + member.getName() + "]", e);
        }
    }
}
Also used : ConfigChannel(io.openems.api.channel.ConfigChannel) ReadChannel(io.openems.api.channel.ReadChannel) WriteChannel(io.openems.api.channel.WriteChannel) ConfigChannel(io.openems.api.channel.ConfigChannel) ThingStateChannel(io.openems.api.channel.ThingStateChannel) Channel(io.openems.api.channel.Channel) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) ChannelDoc(io.openems.api.doc.ChannelDoc) InvocationTargetException(java.lang.reflect.InvocationTargetException) ReadChannel(io.openems.api.channel.ReadChannel) Field(java.lang.reflect.Field) Entry(java.util.Map.Entry) WriteChannel(io.openems.api.channel.WriteChannel) Member(java.lang.reflect.Member) ThingDoc(io.openems.api.doc.ThingDoc)

Aggregations

ConfigChannel (io.openems.api.channel.ConfigChannel)7 WriteChannel (io.openems.api.channel.WriteChannel)5 JsonElement (com.google.gson.JsonElement)4 Channel (io.openems.api.channel.Channel)4 JsonObject (com.google.gson.JsonObject)3 Thing (io.openems.api.thing.Thing)3 Field (java.lang.reflect.Field)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 Set (java.util.Set)3 JsonArray (com.google.gson.JsonArray)2 Bridge (io.openems.api.bridge.Bridge)2 ReadChannel (io.openems.api.channel.ReadChannel)2 ThingStateChannel (io.openems.api.channel.ThingStateChannel)2 ThingMap (io.openems.api.controller.ThingMap)2 Device (io.openems.api.device.Device)2 DeviceNature (io.openems.api.device.nature.DeviceNature)2 ChannelDoc (io.openems.api.doc.ChannelDoc)2 ThingDoc (io.openems.api.doc.ThingDoc)2