Linux serial communication with unusual port names - mono

I'm trying to do some simple stuff with serial ports in Linux. Specifically:
Platform - BeagleBone Black
OS - Angstrom Linux
Mono version 2.10.8.1 (Arm)
The board implements it's six serial ports as ttyO0 through ttyO5 instead of ttyS0.
It actually has ttyS0 through ttyS3.
When I enumerate the ports it finds the ttyS0 etc but not the ttyO0 etc. Unfortunately it is the ttyO0 etc ports that actually have the real serial ports. Is there any way to make Mono able to use these?
Thanks!
Phil

Figured it out myself.
Simple really. They are specifically scanning for port names starting with /dev/ttyS:
public static string [] GetPortNames ()
{
int p = (int) Environment.OSVersion.Platform;
List<string> serial_ports = new List<string>();
// Are we on Unix?
if (p == 4 || p == 128 || p == 6) {
string[] ttys = Directory.GetFiles("/dev/", "tty*");
foreach (string dev in ttys) {
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
serial_ports.Add(dev);

Related

System detection (Windows, Mac OS X or Linux)

i try to develop an app that accesses a COM Port. To select a matching COM Port it would be good to recognize the system automatically.
Is there a way to read the system (Windoews, Linux or MAC) as a string or something similar?
Later I would like to select a Virtual Com port using the USB VID or PID.
It would be great if you could give me one or two or even three ... advice.
I am currently start working with Mono and would be glad about something help ;)
thx Thommy
I have found a solution and have created a few lines of code:
/// <summary>
/// Get Execution Platform / OS
/// return value
/// 0: nicht erkannt/Error
/// 1: Windows
/// 2: MacOSX
/// 2: Unix (Linux)
/// </summary>
static public int DetectingExecutionPlatform()
{
OperatingSystem os = Environment.OSVersion;
PlatformID pid = os.Platform;
switch (pid)
{
case PlatformID.Win32NT:
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
return 1;
case PlatformID.MacOSX:
return 2;
case PlatformID.Unix:
return 3;
default:
return 0;
}
}
Unfortunately, OS X (macOS 10.12.3 Sierra) is displayed as UNIX :|
It would be great if someone could test the code and present me the result. Or who knows a solution is also welcome ;)
thx and cya Thommy

Why can't local Windows 7 Pro machine read its own WMI values?

As part of a larger .Net 4.0 program I have a piece that queries the WMI for a list of network adapters and from that creates a list<> of physical adapters with MAC addresses.
It works on the machines I've tried it on, but when sent to the client, the list is empty. If they run IPCONFIG /ALL at a command prompt the MACs are listed.
My first thought is that there is a group policy in place preventing the enumeration, but everything I've found so far points to group policies that affects remote access through the firewall.
I've tried it locally as both a standard user and administration user, both provide the same list.
The empty query does not generate an exception.
I could ask them to go to the machines and check individual permissions, but since this seems to be a group issue that seems to be the wrong direction. What am I missing?
public static List<WmiNetworkInterfaceItem> QueryphysicalNetworkInterfaces()
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_NetworkAdapter");
List<WmiNetworkInterfaceItem> result = new List<WmiNetworkInterfaceItem>();
foreach (ManagementObject queryObj in searcher.Get()) {
if (queryObj["PhysicalAdapter"].Equals(true)) {
if (queryObj["AdapterTypeId"] != null) {
if (queryObj["AdapterTypeId"].ToString().Equals("0")) {
WmiNetworkInterfaceItem wmiNetworkInterfaceItem = new WmiNetworkInterfaceItem();
wmiNetworkInterfaceItem.Name = ManagementObjectPropertyString(queryObj["Name"]);
wmiNetworkInterfaceItem.MacAddress = ManagementObjectPropertyString(queryObj["MACAddress"]);
wmiNetworkInterfaceItem.PhysicalAdapter = queryObj["PhysicalAdapter"].Equals(true);
wmiNetworkInterfaceItem.AdapterType = ManagementObjectPropertyString(queryObj["AdapterType"]);
wmiNetworkInterfaceItem.AdapterTypeId = -1;
int.TryParse(ManagementObjectPropertyString(queryObj["AdapterTypeId"]), out wmiNetworkInterfaceItem.AdapterTypeId);
wmiNetworkInterfaceItem.Description = ManagementObjectPropertyString(queryObj["Description"]);
wmiNetworkInterfaceItem.PermanentAddress = ManagementObjectPropertyString(queryObj["PermanentAddress"]);
result.Add(wmiNetworkInterfaceItem);
}
}
}
}
return result;
}
Using the WBEMTest utility included with Windows as suggested by user atp_09 in comments, I was able to have the customer query his machine. Using this query exactly one adapter was returned in both standard and administrative user accounts indicating there was nothing in the machine preventing this from working.
SELECT * FROM Win32_NetworkAdapter where PhysicalAdapter = true
Upon further review there was an error in how I later dealt with the list with a single response.

Can't communicate with Epson POS printer

I'm implementing the EPSON ePOS iOS SDK for an EPSON thermal printer TM-T20.
The printer is connected on USB port of an Airport Express with IP 192.168.0.10.
I follow the instructions of EPSON documentation (https://download.epson-biz.com/modules/pos/index.php?page=single_soft&cid=3248&scat=50&pcat=3 in the zip file) and here's my code :
EposBuilder *builder = [[EposBuilder alloc] initWithPrinterModel:#"TM-T20" Lang:EPOS_OC_MODEL_ANK];
if (builder != nil)
{
int errorStatus = EPOS_OC_SUCCESS;
errorStatus = [builder addText: #"Hello,\t"];
errorStatus = [builder addText: #"World!\n"];
errorStatus = [builder addCut: EPOS_OC_CUT_FEED];
EposPrint *printer = [[EposPrint alloc] init];
if (printer != nil)
{
errorStatus = [printer openPrinter:EPOS_OC_DEVTYPE_TCP DeviceName:#"192.168.0.10"];
}
}
Unfortunately, the "errorStatus" has a "2" value, which is an "opening error".
Then I was telling myself, that I have to pass by the Bonjour protocol, but the same.
It's been 3 days I'm struggling with that. I'm about to be crazy.
Thanks for your help
I hope you've been able to solve this already, but here's a couple of things to think about. First, in ePOS-Print_DK_iOS... manual that I'm looking at, the TM-T20 is not listed as a valid printer type for initWithPrinterModel. The valid values it lists are: TM-T88V, TM-T70, TM-P60, and TM-U220. Maybe try the T70? Or maybe it's not compatible with the ios sdk?
Another thing to try is to see if you can access the web-based config utility for the printer. Go to
http://192.168.0.10
(I'm assuming yours has one, I'm using a TM-U220B.) If you can't reach the config web utility, you probably can't reach the printer.
There's probably a way to dump the ip config of the printer. (On mine, I hold in the "stupid-little-button" on the ethernet interface for 3 seconds.
It's also possible that it won't work with the USB -- the airport might not include that in the IP network. I don't know too much about that.

Detecting the platform of a Windows Store App

Is there a possibility to ask at runtime if a Windows Store app (compiled for ARM and x86/64) is executed currently on an ARM-device or more specific on a Microsoft Surface Tablet from within c# or is it necessary to compile two Versions of the same app to behave different on different plattforms?
This can be done via the following code (according to this SO post):-
[DllImport("kernel32.dll")]
internal static extern void GetNativeSystemInfo(ref SystemInfo lpSystemInfo);
internal static bool IsArmBased()
{
var sysInfo = new SystemInfo();
GetNativeSystemInfo(ref sysInfo);
return sysInfo.wProcessorArchitecture == ProcessorArchitectureArm; //ushort 5
}
This does pass the WACK test, test I wouldn't count on it being around forever. Think very hard about why you need this information (is it just for stats, or are you changing the behaviour of your app, if so why!?)
using Windows.ApplicationModel;
Package package = Package.Current;
PackageId packageId = package.Id;
String arch = String.Format("{0}", packageId.Architecture);
This will return "X86" or "ARM", depending on the underlying hardware.

Connecting to a UDP data stream with Mathematica

I have an app on my iPhone called iSeismometer which reads the iPhone's accelerometers and acts as a server which streams this data via UDP (I can set the IP address and port number). The question is how to read this data stream with Mathematica? Apparently, Dreeves has been looking into this 12 years ago, so I imagine something must have happened in the meantime.
Update
I got two great answers so far; one from WReach and one from Mark McClure. Both are using JLink to get at the data. This seems like a fine approach. However, I was reminded of some work I did on the WII balance board. Using a few free programs (GlovePIE and PPJoy) I got this bluetooth peripheral to appear as a joystick to Windows, and therefore also to Mathematica (via ControllerState). Of course, bluetooth and UDP are quite different, but could something along the same lines be made to work too?
JLink is definitely the way to go. I prefer to keep my Java code and my Mathematica code separate by compiling a Java programwhich I then call from Mathematica. I set up a Notebook and companion Java program that you can grab here:
http://facstaff.unca.edu/mcmcclur/UDPFiles.tar.gz
Here is the essential Mathematica code:
Needs["JLink`"];
InstallJava[];
AddToClassPath[NotebookDirectory[]];
udpReader = JavaNew["myClient"];
i = 0;
While[True && i++ < 100,
Print[udpReader#udpReadOne[10552]]]
The updReader class is defined by the following Java code.
// A simple UDP client to read from iseismometer:
// http://www.iseismometer.com/
// You can run this from the command line via "java myClient"
// to check that your iseismometer setup is correct or you can
// call the the udpReadOne method from another program.
import java.io.*;
import java.net.*;
import java.util.*;
public class myClient {
public static void main() throws IOException {
DatagramSocket socket = new DatagramSocket(10552);
byte[] buffer = new byte[500];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while(true) {
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println(received);
}
}
public static String udpReadOne(int port) throws IOException {
DatagramSocket socket = new DatagramSocket(port);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
socket.close();
return received;
}
}
Note that you can use the main method of the myClient class to check that your setup is working without Mathematica, essentially taking one potential issue out of the loop.
Assuming the set-up discussed in a blog entry on the iSeismometer web site, a couple of options come to mind.
Import
The first option would be to use an external program to capture the packets, and then use Import to bring in the results, e.g.
Import["!someexternalprog", "Lines"]
Alas, the Python program mentioned in the blog post will not work well here since it runs in an endless loop that must be manually terminated. The Import approach would only work if that program were modified to stop after a fixed number of packets or a time limit or something.
JLink
An alternate approach can be implemented without leaving the comfy Mathematica environment by using JLink. Well, perhaps it is a stretch to say that we are staying within Mathematica since a fair amount of funny-looking Java code is mixed in with the Mathematica code. Nevertheless, it does illustrate the utility of the built-in Java distribution that ships with every copy of Mathematica:
Needs["JLink`"]
LoadJavaClass["java.util.Arrays"];
ClearAll#ListenToISeismometer
ListenToISeismometer[port_] :=
JavaBlock#Module[{socket, packet, listen, record = Null, listening = True}
, packet = JavaNew["java.net.DatagramPacket", JavaNew["[B", 1024], 1024]
; listen[] :=
If[$Failed =!= Quiet[socket#receive[packet], Java::excptn]
, record =
JavaNew[
"java.lang.String"
, java`util`Arrays`copyOfRange ## packet /# {getData[], getOffset[], getLength[]}
]#toString[] // Sow
]
; Row[{Button["Stop", listening = False], Dynamic[record]}, " "] // PrintTemporary
; AbortProtect[
socket = JavaNew["java.net.DatagramSocket", port]
; socket#setSoTimeout[1000]
; Reap[While[listening, listen[]]; socket#close[]][[2, 1]]
]
]
Some shortcuts have been taken with respect to exception handling, packet decoding and the like in order to keep this example at a manageable length.
ListenToISeismometer needs to be given the UDP port number to listen upon. Let's use the same port as in the blog post, 10552:
In[33]:= data = ListenToISeismometer[10552];
The function will listen to all UDP events on that port until told to stop. A button is presented for this purpose, with each packet flashing by along side as received.
When the button is pressed, the function returns a list of the packets received:
In[34]:= data // Column
Out[34]= 1,83575.099,0.029,0.044,0.094
1,83575.781,0.056,0.033,0.099
1,83575.924,0.047,0.054,0.094
1,83575.613,0.096,0.092,0.057
1,83575.748,0.073,0.049,0.061
1,83575.577,0.008,0.089,0.020
...
JLink makes this possible, but there is no escaping the fact that the use of JLink requires a working knowledge of Java.