Unfortunately, breaking changes happen like this all the time. Admittedly, I’ve never used much AxCommunity because we had many customers (when I worked for several BAS Contractors) who wouldn’t allow modules line AxCommunity or VykonPro in their installations
The problem with open source modules such as this is that they may not have the ability to be maintained over the lifespan of a framework. VykonPro will always be maintained since Vykon is Tridium’s OEM channel
Also, what did you upgrade from? I assume it was an early rev of 4.10? Those changes mentioned started over 3 years ago.
The object in its entirety would have to be put in a module, at a minimum a program module. Since it’s accessing protected spaces, there are safeguards from program objects accessing these.
I’ll have to research this more. I’ll load this on a 9000 that I have with 4.15 and monitor.
You bring up an interesting point about how many people are actually using AXCommunity. I wonder how many installed systems are out there. Did notice a post on this forum asking what functions people use.
It would be interesting to see Tridium adopt the AXCommunity module and make it repository for popular customer requested add-ins. They could having a voting session at the summit.
Like for example, I don’t know what all information people really look at for the SysInfo. I saw where it gives an error to me in my 9000 in that try/catch block… But honestly, I don’t know how many people need information about protected spaces and such. I also don’t like the fact that it allows you to restart or reboot from that block… I think that’s a terrible design because of a customer gets a hold of that and just reboots willy nilly from that object…. Seems kinda bad.
Just try using the StringToFile function in 4.15 and I get access errors. Made sure the path and file have write permission and I can edit the file from workbench and notepad.
Not sure if something in Tridium changed and this is another AXCommunity function that needs repair.
Just looking for a function to append string data to a text file. Really question the value of Tridium if you can’t do simple file IO from the environment.
This likely isn’t a Tridium issue directly. It’s more a side effect of using a module that’s no longer actively maintained.
Niagara 4.15 introduced a number of security changes, especially around file system access, so behavior like this isn’t entirely unexpected. If the module is relying on older or internal APIs, those can change at any time and aren’t guaranteed to remain compatible.
Tridium generally does a good job documenting breaking changes, but third-party modules still need to be updated to stay aligned with those changes. If they aren’t, things that once worked can start failing as the platform evolves.
It’s similar to any community-developed module—if development stops and the platform continues to move forward, compatibility issues are almost inevitable.
So this is less about a limitation of the platform and more about the need for the module to be updated to meet current security and API requirements.
I guess we just put it on the list of AXCommunity modules that need to be updated.
In the meantime I need to write a series of values to a .CSV log file. I have looked around for examples and everything points to using the Java.IO.writer function. Just figured that is what StringtoFile used and don’t feel like going down rabbit holes that don’t work.
Do you know of any file write examples that work in 4.15?
public void onExecute() throws Exception {
// Generate the filename with the current date in the format: "MyCSVFile MM-DD-YY.csv"
String fileName = generateFileName();
// Create a BOrd object using the path composed by the getDirectory() method concatenated with the filename
BOrd fileOrd = createFileOrd(fileName);
FileWriter fileWriter = null;
try {
// Try to get the file from the fileOrd if it exists, or make a new file
BIFile file = getFile(fileOrd, fileName);
// Initialize a FileWriter to write to the file
fileWriter = initializeFileWriter(file);
// Write a string to the file
fileWriter.write("This is my file. There are many like this but this one is mine");
} catch (IOException e) {
// Print an error message and the stack trace if an exception occurs
System.out.println("Failed creating file " + fileName);
e.printStackTrace();
} finally {
// Ensuring that the FileWriter is properly closed in a finally block after writing to the file
closeFileWriter(fileWriter);
}
}
private String generateFileName() {
// Get the current system time
BAbsTime time = Clock.time();
// Generate the filename using the current date
return "MyCSVFile " + time.getMonth().getMonthOfYear() + "-" + time.getDay() + "-" + time.getYear() % 100 + ".csv";
}
private BOrd createFileOrd(String fileName) {
// Generate the BOrd (Binary-Object Resource Descriptor) for the file from its file path
return BOrd.make(getDirectory() + "/" + fileName);
}
private BIFile getFile(BOrd fileOrd, String fileName) throws IOException {
try {
// Try fetch an existing file
BIFile file = (BIFile) fileOrd.get(fileOrd.resolve().getComponent());
System.out.println("A file named " + fileName + " already exists.");
return file;
} catch (UnresolvedException ure) {
// In case the file doesn't exist, create a new file
FilePath filePath = getLastQuery(fileOrd);
System.out.println("Creating a new file named " + fileName);
return BFileSystem.INSTANCE.makeFile(filePath);
}
}
private FilePath getLastQuery(BOrd fileOrd) {
// Parse the BOrd object fileOrd to an array ofOrdQuery objects
OrdQuery[] query = fileOrd.parse();
// Retrieve the last query from the array, and cast it to a FilePath
return (FilePath) query[query.length - 1];
}
private FileWriter initializeFileWriter(BIFile file) throws IOException {
// Convert the file to a local file
File localFile = BFileSystem.INSTANCE.pathToLocalFile(file.getFilePath());
// Create and return a FileWriter object to write to the file
return new FileWriter(localFile, false);
}
private void closeFileWriter(FileWriter fileWriter) {
if (fileWriter != null) {
try {
// Ensure that the FileWriter is closed to release resources
fileWriter.close();
} catch (IOException e) {
// Print the stack trace for the exception
e.printStackTrace();
}
}
}
That is a program object that requires no security requirements and uses all public API.
That is the directory in which I’m writing to. This is also on a supervisor running a station.
The entire Java.io file stuff is really messing with me! Inspired by getting StringTo File working, decided to press on with adding writing an event log CSV file only to be stumped again by File.exists which only works with the Unix path delimiter / instead of windows \.
All I wanted to do is check to see if the file was there and if not create a new one with a header before writing the latest event values.
Thank you for listening to my rants, sometimes it feels lonely out here…