use of io.openems.api.controller.ThingMap in project openems by OpenEMS.
the class FeneconPersistence method addChannelValueToQueue.
/**
* Add a channel value to the send queue
*
* @param channel
* @param valueOpt
*/
private void addChannelValueToQueue(Channel channel, Optional<?> valueOpt) {
// Ignore anything that is not a ReadChannel
if (!(channel instanceof ReadChannel<?>)) {
return;
}
ReadChannel<?> readChannel = (ReadChannel<?>) channel;
// Ignore channels that shall not be persisted
if (readChannel.isDoNotPersist()) {
return;
}
// Read and format value from channel
FieldValue<?> fieldValue;
if (!valueOpt.isPresent()) {
fieldValue = new NullFieldValue();
} else {
Object value = valueOpt.get();
if (value instanceof Number) {
fieldValue = new NumberFieldValue((Number) value);
} else if (value instanceof String) {
fieldValue = new StringFieldValue((String) value);
} else if (value instanceof Inet4Address) {
fieldValue = new StringFieldValue(((Inet4Address) value).getHostAddress());
} else if (value instanceof Boolean) {
fieldValue = new NumberFieldValue(((Boolean) value) ? 1 : 0);
} else if (value instanceof ChannelEnum) {
fieldValue = new NumberFieldValue(((ChannelEnum) value).getValue());
} else if (value instanceof DeviceNature || value instanceof JsonElement || value instanceof Map || value instanceof Set || value instanceof List || value instanceof ThingMap) {
// ignore
return;
} else {
log.warn("FENECON Persistence for value type [" + value.getClass().getName() + "] of channel [" + channel.address() + "] is not implemented.");
return;
}
}
// Add timestamp + value to queue
synchronized (queue) {
queue.put(readChannel.address(), fieldValue);
}
}
use of io.openems.api.controller.ThingMap 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.");
}
use of io.openems.api.controller.ThingMap in project openems by OpenEMS.
the class ConfigUtils method getConfigObject.
/**
* Receives a matching value for the ConfigChannel from a JsonElement
*
* @param channel
* @param j
* @return
* @throws OpenemsException
*/
public static Object getConfigObject(ConfigChannel<?> channel, JsonElement j, Object... args) throws OpenemsException {
Optional<Class<?>> typeOptional = channel.type();
if (!typeOptional.isPresent()) {
String clazz = channel.parent() != null ? " in implementation [" + channel.parent().getClass() + "]" : "";
throw new ReflectionException("Type is null for channel [" + channel.address() + "]" + clazz);
}
Class<?> type = typeOptional.get();
/*
* test for simple types
*/
try {
return JsonUtils.getAsType(type, j);
} catch (NotImplementedException e1) {
;
}
if (Thing.class.isAssignableFrom(type)) {
/*
* Asking for a Thing
*/
@SuppressWarnings("unchecked") Class<Thing> thingType = (Class<Thing>) type;
return getThingFromConfig(thingType, j, args);
} else if (ThingMap.class.isAssignableFrom(type)) {
/*
* Asking for a ThingMap
*/
return InjectionUtils.getThingMapsFromConfig(channel, j);
} else if (Inet4Address.class.isAssignableFrom(type)) {
/*
* Asking for an IPv4
*/
try {
return Inet4Address.getByName(j.getAsString());
} catch (UnknownHostException e) {
throw new ReflectionException("Unable to convert [" + j + "] to IPv4 address");
}
} else if (Long[].class.isAssignableFrom(type)) {
/*
* Asking for an Array of Long
*/
return getLongArrayFromConfig(channel, j);
}
throw new ReflectionException("Unable to match config [" + j + "] to class type [" + type + "]");
}
use of io.openems.api.controller.ThingMap in project openems by OpenEMS.
the class InjectionUtils method getThingMapsFromConfig.
public static Object getThingMapsFromConfig(ConfigChannel<?> channel, JsonElement j) throws ReflectionException {
/*
* Get "Field" in Channels parent class
*/
Field field;
try {
field = channel.parent().getClass().getField(channel.id());
} catch (NoSuchFieldException | SecurityException e) {
throw new ReflectionException("Field for ConfigChannel [" + channel.address() + "] is not named [" + channel.id() + "] in [" + channel.getClass().getSimpleName() + "]");
}
/*
* Get expected Object Type (List, Set, simple Object)
*/
Type expectedObjectType = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
if (expectedObjectType instanceof ParameterizedType) {
expectedObjectType = ((ParameterizedType) expectedObjectType).getRawType();
}
Class<?> expectedObjectClass = (Class<?>) expectedObjectType;
/*
* Get the ThingMap class
*/
Class<?> thingMapClass = channel.type().get();
/*
* Get the referenced Thing class
*/
IsThingMap isThingMapAnnotation = thingMapClass.getAnnotation(IsThingMap.class);
Class<? extends Thing> thingClass = isThingMapAnnotation.type();
/*
* Prepare filter for matching Things
* - Empty filter: accept nothing
* - Asterisk: accept everything
* - Otherwise: accept only exact string matches on the thing id
*/
Set<String> filter = new HashSet<>();
if (j.isJsonPrimitive()) {
String id = j.getAsJsonPrimitive().getAsString();
filter.add(id);
} else if (j.isJsonArray()) {
j.getAsJsonArray().forEach(id -> filter.add(id.getAsString()));
}
/*
* Create ThingMap instance(s) for each matching Thing
*/
ThingRepository thingRepository = ThingRepository.getInstance();
Set<Thing> matchingThings = thingRepository.getThingsAssignableByClass(thingClass);
Set<ThingMap> thingMaps = new HashSet<>();
for (Thing thing : matchingThings) {
if (filter.contains(thing.id()) || filter.contains("*")) {
ThingMap thingMap = (ThingMap) InjectionUtils.getInstance(thingMapClass, thing);
thingMaps.add(thingMap);
}
}
/*
* Prepare return
*/
if (thingMaps.isEmpty() && !filter.isEmpty()) {
throw new ReflectionException("No matching ThingMap found for ConfigChannel [" + channel.address() + "]");
}
if (Collection.class.isAssignableFrom(expectedObjectClass)) {
if (Set.class.isAssignableFrom(expectedObjectClass)) {
return thingMaps;
} else if (List.class.isAssignableFrom(expectedObjectClass)) {
return new ArrayList<>(thingMaps);
} else {
throw new ReflectionException("Only List and Set ConfigChannels are currently implemented, not [" + expectedObjectClass + "]. ConfigChannel [" + channel.address() + "]");
}
} else {
// No collection
if (thingMaps.size() > 1) {
throw new ReflectionException("Field for ConfigChannel [" + channel.address() + "] is no collection, but more than one ThingMaps [" + thingMaps + "] is fitting for [" + channel.id() + "] in [" + channel.getClass().getSimpleName() + "]");
} else {
return thingMaps.iterator().next();
}
}
}
Aggregations