use of io.openems.api.doc.ThingDoc in project openems by OpenEMS.
the class ClassRepository method getThingDoc.
/**
* Returns the cached ThingDoc or parses the class and adds it to the cache.
* Field annotations have higher priority than method annotations!
*
* @param clazz
*/
public ThingDoc getThingDoc(Class<? extends Thing> clazz) {
if (this.thingDocs.containsKey(clazz)) {
// return from cache
return this.thingDocs.get(clazz);
}
ThingDoc thingDoc = new ThingDoc(clazz);
// get info about thing
ThingInfo thing = clazz.getAnnotation(ThingInfo.class);
if (thing == null) {
log.warn("Thing [" + clazz.getName() + "] has no @ThingInfo annotation");
} else {
thingDoc.setThingDescription(thing);
}
// parse all methods
for (Method method : clazz.getMethods()) {
Class<?> type = null;
if (method.getReturnType().isArray()) {
Class<?> rtype = method.getReturnType();
type = rtype.getComponentType();
} else {
type = method.getReturnType();
}
if (Channel.class.isAssignableFrom(type)) {
Optional<ChannelInfo> channelInfoOpt = getAnnotationForMethod(clazz, method.getName());
String channelId = method.getName();
ChannelDoc channelDoc = new ChannelDoc(method, channelId, channelInfoOpt);
thingDoc.addChannelDoc(channelDoc);
if (ConfigChannel.class.isAssignableFrom(type)) {
thingDoc.addConfigChannelDoc(channelDoc);
}
}
}
// parse all fields
for (Field field : clazz.getFields()) {
Class<?> type = field.getType();
if (Channel.class.isAssignableFrom(type)) {
String channelId = field.getName();
ChannelDoc channelDoc = new ChannelDoc(field, channelId, Optional.ofNullable(field.getAnnotation(ChannelInfo.class)));
thingDoc.addChannelDoc(channelDoc);
if (ConfigChannel.class.isAssignableFrom(type)) {
thingDoc.addConfigChannelDoc(channelDoc);
}
}
}
// add to cache
this.thingDocs.put(clazz, thingDoc);
return thingDoc;
}
use of io.openems.api.doc.ThingDoc in project openems by OpenEMS.
the class Config method getJson.
/**
* Gets the Config as Json in the given format
*
* @param format
* @return
* @throws NotImplementedException
*/
public synchronized JsonObject getJson(ConfigFormat format, Role role, String language) throws NotImplementedException {
JsonObject jConfig = new JsonObject();
if (format == ConfigFormat.FILE) {
/*
* Prepare Json in format for config.json file
*/
// Bridge
jConfig.add("things", getBridgesJson(format, role));
// Scheduler
jConfig.add("scheduler", getSchedulerJson(format, role));
// Persistence
jConfig.add("persistence", getPersistenceJson(format, role));
// Users
jConfig.add("users", getUsersJson());
} else {
/*
* Prepare Json in format for OpenEMS UI
*/
// things...
JsonObject jThings = new JsonObject();
Set<Thing> things = ThingRepository.getInstance().getThings();
for (Thing thing : things) {
JsonObject jThing = (JsonObject) ConfigUtils.getAsJsonElement(thing, format, role);
jThings.add(thing.id(), jThing);
}
jConfig.add("things", jThings);
// meta...
JsonObject jMeta = new JsonObject();
try {
Iterable<ThingDoc> availableThings = ClassRepository.getInstance().getAvailableThings();
for (ThingDoc availableThing : availableThings) {
jMeta.add(availableThing.getClazz().getName(), availableThing.getAsJsonObject());
}
} catch (ReflectionException e) {
log.error(e.getMessage());
e.printStackTrace();
}
jConfig.add("meta", jMeta);
}
return jConfig;
}
use of io.openems.api.doc.ThingDoc in project openems by OpenEMS.
the class ThingRepository method applyChannelAnnotation.
public void applyChannelAnnotation(Thing thing) {
ThingDoc thingDoc = classRepository.getThingDoc(thing.getClass());
for (ChannelDoc channelDoc : thingDoc.getChannelDocs()) {
try {
Channel channel = getChannel(thing, channelDoc.getMember());
channel.setChannelDoc(channelDoc);
} catch (OpenemsException e) {
log.debug(e.getMessage());
}
}
}
use of io.openems.api.doc.ThingDoc in project openems by OpenEMS.
the class ChannelExport method main.
public static void main(String[] args) throws OpenemsException {
String openemsPath = "C:\\Users\\matthias.rossmann\\Dev\\git\\openems-neu\\edge\\src";
Collection<ThingDoc> deviceNatures;
HashMap<Path, FileWriter> files = new HashMap<>();
try {
deviceNatures = ClassRepository.getInstance().getAvailableDeviceNatures();
FileWriter devices = new FileWriter(Paths.get(openemsPath, "\\io\\openems\\impl\\device\\Readme.md").toFile());
devices.write("# List of implemented Devices.\r\n\r\n");
for (ThingDoc thingDoc : deviceNatures) {
try {
System.out.println(thingDoc.getClazz().getName());
if (thingDoc.getClazz().equals(AsymmetricSymmetricCombinationEssNature.class) || thingDoc.getClazz().equals(EssClusterNature.class) || thingDoc.getClazz().isInterface() || Modifier.isAbstract(thingDoc.getClazz().getModifiers())) {
continue;
}
Path p = Paths.get(openemsPath, thingDoc.getClazz().getName().replaceAll("[^\\.]*$", "").replace(".", "/"), "Readme.md");
FileWriter fw;
if (files.containsKey(p)) {
fw = files.get(p);
} else {
fw = new FileWriter(p.toFile());
files.put(p, fw);
fw.write("");
}
fw.append("# " + thingDoc.getTitle() + "\r\n" + thingDoc.getText() + "\r\n\r\nFollowing Values are implemented:\r\n\r\n" + "|ChannelName|Unit|\r\n" + "|---|---|\r\n");
devices.append("* [" + thingDoc.getTitle() + "](" + Paths.get(thingDoc.getClazz().getName().replaceAll("io.openems.impl.device.", "").replaceAll("[^\\.]*$", "").replace(".", "/"), "Readme.md").toString().replace("\\", "/") + ")\r\n");
Thing thing = thingDoc.getClazz().getConstructor(String.class, Device.class).newInstance("", null);
if (thing instanceof ModbusDeviceNature) {
((ModbusDeviceNature) thing).init();
}
List<ChannelDoc> channelDocs = new LinkedList<>(thingDoc.getChannelDocs());
Collections.sort(channelDocs, new Comparator<ChannelDoc>() {
@Override
public int compare(ChannelDoc arg0, ChannelDoc arg1) {
return arg0.getName().compareTo(arg1.getName());
}
});
for (ChannelDoc channelDoc : channelDocs) {
Member member = channelDoc.getMember();
try {
List<Channel> channels = new ArrayList<>();
if (member instanceof Method) {
if (((Method) member).getReturnType().isArray()) {
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 (channels.isEmpty()) {
System.out.println("Channel is returning null! Thing [" + thing.id() + "], Member [" + member.getName() + "]");
continue;
}
for (Channel channel : channels) {
if (channel != null) {
StringBuilder unit = new StringBuilder();
if (channel instanceof ReadChannel) {
ReadChannel rchannel = ((ReadChannel) channel);
unit.append(rchannel.unitOptional());
rchannel.getLabels().forEach((key, value) -> {
unit.append(key + ": " + value + "<br/>");
});
}
fw.append("|" + channel.id() + "|" + unit + "|\r\n");
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
System.out.println("Unable to add Channel. Member [" + member.getName() + "]");
}
}
} catch (NoSuchMethodException e) {
}
}
for (FileWriter fw : files.values()) {
fw.close();
}
devices.close();
} catch (Exception e) {
e.printStackTrace();
}
}
use of io.openems.api.doc.ThingDoc 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);
}
}
Aggregations