Issue with Serial Port Data Source
-
Hey everyone,
I could use some advice in dealing with an issue regarding the serial data source in Mango. I currently have serial data source that is set to read from a SPI-12 to USB adapter through
/dev/ttyUSB0
. The data point currently looks for\r\n
line terminators and uses the regex()[^ ]+
Within the data source is a data point that I have set up as a "catch-all" of sorts. The catchall has no point identifier, uses a value group of 0 and uses RegEx that'll capture everything ([^]+
).I also have another data source that uses scripting to query the adapter at
/dev/ttyUSB0
. The script looks like this:// Send the ID command. We expect a response of // 013METER ATM41 529ATM-410004576 catchall.set('0I!\r\n'); // Give the sensor 1 second to respond RuntimeManager.sleep(1000); // response is a variable for a data point within the scripting data source response.set(catchall.value);
where
response
is a virtual and settable variable from the scripting data sourceNeither
response
nor thecatchall
data source thus far have been able to capture any sort of value. The serial IO log indicate that there is an output of0I!
and input of013METER ATM41 529ATM 410004576
as desired:2023/09/25-14:43:08,854 O: 0I! 2023/09/25-14:43:09,366 I: 013METER ATM41 529ATM-410004576
Looking through
ma.log
reveals that there's this:ERROR 2023-09-25T14:43:24,367 (com.infiniteautomation.serial.rt.SerialDataSourceRT.serialEvent:476) - No authentication set in security context com.serotonin.m2m2.vo.permission.PermissionException: No authentication set in security context at com.serotonin.m2m2.Common.getUser(Common.java:455) ~[mango-5.0.0.jar:?] at com.serotonin.timer.Task.<init>(Task.java:98) ~[mango-5.0.0.jar:?] at com.serotonin.timer.TimerTask.<init>(TimerTask.java:21) ~[mango-5.0.0.jar:?] at com.serotonin.m2m2.util.timeout.TimeoutTask.<init>(TimeoutTask.java:38) ~[mango-5.0.0.jar:?] at com.serotonin.m2m2.util.timeout.TimeoutTask.<init>(TimeoutTask.java:30) ~[mango-5.0.0.jar:?] at com.infiniteautomation.serial.rt.SerialDataSourceRT.serialEvent(SerialDataSourceRT.java:293) ~[?:?] at com.infiniteautomation.mango.io.serial.SerialPortProxyEventTask.run(SerialPortProxyEventTask.java:38) ~[mango-5.0.0.jar:?] at com.infiniteautomation.mango.io.serial.JsscSerialPortManager$1.run(JsscSerialPortManager.java:67) ~[mango-5.0.0.jar:?]
All of the data sources and data points have the correct permissions (i.e., they're editable and readable by users and the anonymous group). the Mango user is a member of the
dialout
group and can read/write to/dev/ttyUSB0
.Are there any potential avenues I should look into with getting Mango to record the input from the adapter? Any help is greatly appreciated!
-
@emeinig first off for simplicity's sake
The two regexes for both the datasource and datapoint can be(.*)
with the the '\r\n' terminator.
A capture group of 0 for the datasource should pass the entire string in (Although a 1 shouldn't make a difference), then use a capture group of 1 on the datapoint itself.
No point indicator required.Start from that and see what comes in.
Fox
-
Heya Matt,
Thanks for the suggestions. I implemented them and still no joy.
I'm still getting the mysterious
PermissionException
error inma.log
-
@emeinig you're not logged out by any chance are you?
Fox
-
I just double checked and I can confirm I'm logged in as the admin
-
I got it resolved with a workaround. I'm going to post what I did for posterity and to hopefully help anyone who might come across the same issue in the future.
What I ended up doing is creating a scripting data source. The datasource uses Rhino as its scripting engine so you can use some Java in it. With the Java, you can read/write to files and leverage the "Everything is a file" philosophy in *nix systems.
The code:
// import the file reader var FileReader = java.io.FileReader; var BufferedReader = java.io.BufferedReader; // import the writer. We must use OutputStreamWriter to write to device files var OutputStreamWriter = java.io.OutputStreamWriter; var FileOutputStream = java.io.FileOutputStream; // Be careful because this could change on us depending on how many USB devices // are plugged in var serial_port = "/dev/ttyUSB0"; // Initialize a bunch of blank strings to store measurements var max_time_measurements, temp_and_pressure, wind_attrs, solar_and_precip = new String(); // Set up the writer var file = new FileOutputStream(serial_port); var output = new OutputStreamWriter(file); // Set up the streamer var fr = new FileReader(serial_port); var br = new BufferedReader(fr); // Write the measurement command to the serial port and flush to ensure the // buffer is empty for the next command. output.write("0M!\r\n"); output.flush(); // The sensor takes around 3 seconds to return 9 values, so we sleep for 4 // seconds to give it a generous margin RuntimeManager.sleep(4000); // Now we write our data commands to get it all. output.write("0D0!\r\n"); output.flush(); output.write("0D1!\r\n"); output.flush(); output.write("0D2!\r\n"); output.flush(); output.close(); // readLine will read the return values max_time_measurements = br.readLine(); solar_and_precip = br.readLine(); wind_attrs = br.readLine(); temp_and_pressure = br.readLine(); //split the 0D0! result var solar_and_precip_array = solar_and_precip.split("+"); solarRad.set(solar_and_precip_array[1]); precipitation.set(solar_and_precip_array[2]); lightningStrikes.set(solar_and_precip_array[3]); //split the 0D1! result var wind_attrs_array = wind_attrs.split("+"); windSpeed.set(wind_attrs_array[1]); windDirection.set(wind_attrs_array[2]); gustWindSpeed.set(wind_attrs_array[3]); //split the 0D2! result var temp_and_pressure_array = temp_and_pressure.split("+"); temp.set(temp_and_pressure_array[1]); vaporPressure.set(temp_and_pressure_array[2]); atmosphericPressure.set(temp_and_pressure_array[3]);
The code isn't the prettiest or most elegant but it does work. Just make sure you have the necessary variables created as data points and that they're settable and you're all good to go.