I have this C# script on Unity to scan available serial ports to connect to Neurosky. However, this is a manual detection, this just works on computers whose Starting port of ThinkGear Connector is COM9.
void setupNeuro() {
tgHandleId = ThinkGear.TG_GetNewConnectionId();
tgConnectionStatus = ThinkGear.TG_Connect(tgHandleId,
"\\\\.\\COM9",
ThinkGear.BAUD_9600,
ThinkGear.STREAM_PACKETS);
}
How to edit this C# script to automatically detect a right port from COM1 to COMxx ?
This isn't a Unity problem as much as it is a C# one. The ThinkGear docs mention that users should implement port scanning, but I don't recall there being any implementation provided, although the suggestion of storing the previous port is provided.
Unfortunately, there are no truly elegant ways to implement this, but there are ways.
The best you can do is looping through the ports until you get one that doesn't timeout, but this means each check needs to take at least 2 seconds. And to make matters worse, the only method you have to get connected Serial Ports from .NET in Unity isn't guaranteed to be up to date either. This means you might end up enumerating over a ton of serial ports in a really slow manner.
To minimize search times you should search in this order:
Last port that was used (Store this in PlayerPrefs)
All ports returned by SerialPort.GetPortNames. There won't be many, but unfortunately, there's no guarantee they all exist, since, as the docs say, SerialPort.GetPortNames checks a registry value that is not always up to date.
Ports 0-10 if you haven't already checked them.
Ports 10 - 256, but see below. At this point you'll have to at least give the user a chance to enter the port themselves, or give them a warning about how long the next step will take.
I wouldn't recommend going this far (does up to 8 minutes of searching sound reasonable?). You'll already have spent up to 20 seconds scanning the first 10 ports. It might be worth it to
Show users how to find the right port themselves
Write a small external program for each platform that uses lower level methods to display the right port for the user to enter.
Access those lower level methods from a OS-specific library and access it from Unity to limit your search to valid ports. This is the choice I'd go with.
Checking a port goes something like this (the lambda is needed because of the use of a coroutine):
IEnumerable AttemptHeadsetConnection(int portNumber,Action<int,int> headsetConnectedCallback, Action attemptCompletedCallback)
{
var connectionString = string.Format("\\\\.\\COM{0}",portNumber);//That string literal should be elsewhere
return AttemptHeadsetConnection(connectionString, headsetConnectedCallback, attemptCompletedCallback);
}
IEnumerable AttemptHeadsetConnection(string connectionString,Action<int,int> headsetConnectedCallback,Action attemptCompletedCallback)
{
connectionID = ThinkGear.TG_GetNewConnectionId();
connectionStatus = ThinkGear.TG_Connect(connectionID ,
connectionString,
ThinkGear.BAUD_9600,
ThinkGear.STREAM_PACKETS);
if(connectStatus >= 0)
{
yield return new WaitForSeconds(2f); //Give the headset at least 2 seconds to respond with valid data
int receivedPackets = ThinkGear.TG_ReadPackets(handleID, -1);//Read all the packets with -1
if(receivedPackets > 0)
{
headsetConnectedCallback(connectionID,connectionStatus);
}
else
{
ThinkGear.TG_FreeConnection(handleID);
}
}
attemptCompletedCallback();
}
And use that with something like:
foreach(var serialPort in SerialPort.GetPortNames())
{
var connectionCoroutine = AttemptHeadsetConnection(serialPort,onFoundHeadset,onAttemptCompleted);
StartCoroutine(connectionCoroutine);
}
Note about the code: It's not elegant, and it might not even compile (although it doesn't do anything that's impossible). Take it as very convincing psuedo-code and use it as your base.
loop thru the known ports substituting the COM number into the connect string until you either run out of ports (nothing connected) or find one that is...
Related
My goal is to get data (pulse) from the fitness bracelet Torntisc T1 using my application and independently process data from the bracelet.
To implement I use Xamarin and found a Bluetooth LE plugin for Xamarin plugin to connect to the device and receive data from it. However, all the characteristics obtained are called "Unknown characteristic" and in values of 0 bytes. Although it has 5 services, each of which has 3 characteristics. The only name of characteristics in 1 service is other: "Device Name", "Appearance", "Peripheral Preferred Connection Parameters". However, the value (value) is everywhere 0 bytes. How to get characteristics? How to get a pulse?
To the bracelet there is an application H Band 2.0, which shows a fairly large number of settings for the bracelet, the question arises where is all this?
Native app H Band 2.0. Attempt of decompile here. I found the classes responsible for the connection in the following directory: sources\no\nordicsemi\android\dfu. I see what has been done via BluetoothGatt. Unfortunately I am not an expert in java and android, unfamiliar with this library. I didn't find any methods or anything related to the "pulse", but a large number of magic parsing characteristics: parse (characteristic)
foreach (var TestService in Services)
{
var characteristics = await TestService.GetCharacteristicsAsync();
foreach (var Characteristic in characteristics)
{
var properties = Characteristic.Properties;
var name = Characteristic.Name;
var serv = Characteristic.Service;
var value = Characteristic.Value;
var stringValue = value.ToString();
string result = "";
if (value.Length != 0)
result = System.Text.Encoding.UTF8.GetString(value, 0, value.Length - 1);
}
}
To start with you can use the following app to get a better overview of the services and characteristics you are working with, without having to code calls to get the values you need.
Having said that you will need documentation to be able to communicate with the device, what I mean is what data you send, what are acceptable responses how they map to meaningful data etc. The core of BLE is the low energy bit which means exchange as little data as possible ex. mapping integers to enum values which you do not know without the documentation, you can work your way back from decompiled source but it will be orders of magnitude more difficult.
One more thing is that BLE is notoriously unreliable (you will understand if you run into gatt 133 errros on samsungs :), so most implementations also have a sort of added network layer to handle drops and graceful degradation, as well as sending larger peaces of data, this is custom developed per app/device and you also need extensive documentation for this to implement it, which is no trivial matter.
The library you've chosen is quite good and wraps most things you need quite well but it does not handle the instability so you have to take care of that part yourself.
Cheers :)
I'm developing an application by TAPI technology in C#.
Suppose that I want to make a call to an organization that has a central device. I want when the target machine answers the phone line, my app dials the second number that is an internal number to that organization. I don't know how to dial the second number.
For example I want to call +1234567890 and when the phone line is answered, I want to dial 101 that is an internal number. My app dial's the first part of number perfectly, but i don't know how to code the second part.
numberList = "001234567890#101".Split('#');
tapiManager = new TapiManager(ProjectName);
tapiManager.Initialize();
lineName = (tapiManager != null && tapiManager.Lines.Length > 0 ? tapiManager.Lines[0].Name : string.Empty);
tapiline = tapiManager.GetLineByName(lineName, true);
if (tapiline == null)
tapiline = tapiManager.GetLineByName(lineName, true);
if (!tapiline.IsOpen)
tapiline.Open(MediaModes.DataModem);
makeCallParams = new MakeCallParams();
makeCallParams.DialPause = 2000;
tapiCall = tapiline.MakeCall(numberList[0], null, makeCallParams);
As you see the last line of my code dials the first number, but I can't find a way to dial the second part.
Any ideas about how I can do that?
This very much depends on what this central device is and how it handles your call, so I'll give a few examples:
An older (think analogue) PBX/Appliance will likely accept any digits after it has accepted the call. This you can do by including pauses in your number (usually "." or "," or "p") so "001234567890,,,,,101" (warning: not all TAPI drivers will support this). How many pauses really depends on the speed this central device picks up, too few it will cut of a part of the number, too much and it might hangup.
An IVR or PBX trunk that is specifically configured for this kind of setup should simply accept the full number in the original call, strip off the root number "001234567890" and dial "101" itself (strip out the "#").
An IVR/Voicemail or some other system that play's a message like "Which extension do you wish to call?" usually only accept digits after the message starts or end (barge-in allowed or not). Detecting voice is notoriously difficult, your best bet here is just to guess how long the message is, wait and then put the "101" on the line. (i don't know the lib you are using but the function is probably called GenerateDigits)
so I have a kinda strange problem. I'm using LAN for the communication with a microcontroller. Everything was working perfect. Meaning: I can send and receive data. For receiving data I'm using a simple method, which is Thread.sleep(1) in a for loop in which I keep checking client.GetStream().DataAvailable for true while client is a TcpClient
Now, with one process I have to send and receive to the microcontroller with a higher Baud rate. I was using 9600 for all other operations and everythingwas fine. Now with 115200 client.GetStream().DataAvailableseems to always have the value false.
What could be the problem?
PS: Another way to communicate with the microcontroller (all chosen by user) is serial communication. This is still working fine with the higher Baud rate.
Here is a code snippet:
using (client = new TcpClient(IP_String, LAN_Port))`
{
client.SendTimeout = 200;
client.ReceiveTimeout = 200;
stream = client.GetStream();
.
.
bool OK = false;
stream.Write(ToSend, 0, ToSend.Length);
for (int j = 0; j < 1000; j++)
{
if (stream.DataAvailable)
{
OK = true;
break;
}
Thread.Sleep(1);
}
.
.
}
EDIT:
While monitoring the communication with a listing device I realized that the bits actually arrive and that the device actually answers. The one and only problem seem that the DataAvailable flag is not being raised. I should probably find another way to check data availability. Any ideas?
I've been trying to think of things I've seen that act this way...
I've seen serial chips that say they'll do 115,200, but actually won't. See what happens if you drop the baud rate one notch. Either way you'll learn something.
Some microcontrollers "bit-bang" the serial port by having the CPU raise and lower the data pin and essentially go through the bits, banging 1 or 0 onto the serial pin. When a byte comes in, they read it, and do the same thing.
This does save money (no serial chip) but it is an absolute hellish nightmare to actually get working reliably. 115,200 may push a bit-banger too hard.
This might be a subtle microcontroller problem. Say you have a receiving serial chip which asserts a pin when a byte has come in, usually something like DRQ* for "Data Request" (the * in DRQ* means a 0-volt is "we have a byte" condition) (c'mon, people, a * isn't always a pointer:-). Well, DRQ* requests an interrupt, the firmware & CPU interrupt, it reads the serial chip's byte, and stashes it into some handy memory buffer. Then it returns from interrupt.
A problem can emerge if you're getting data very fast. Let's assume data has come in, serial chip got a byte ("#1" in this example), asserted DRQ*, we interrupted, the firmware grabs and stashes byte #1, and returns from interrupt. All well and good. But think what happens if another byte comes winging in while that first interrupt is still running. The serial chip now has byte #2 in it, so it again asserts the already-asserted DRQ* pin. The interrupt of the first byte completes. What happens?
You hang.
This is because it's the -edge- of DRQ*, physically going from 5V to 0V, that actually causes the CPU interrupt. On the second byte, DRQ* started at 0 and was set to 0. So DRQ* is (still) asserted, but there's no -edge- to tell the interrupt hardware/CPU that another byte is waiting. And now, of course, all the rest of the incoming data is also dropped.
See why it gets worse at higher speeds? The interrupt routine is fielding data more and more quickly, and typically doing circular I/O buffer calculations within the interrupt handler, and it must be fast and efficient, because fast input can push the interrupt handler to where a full new byte comes in before the interrupt finishes.
This is why it's a good idea to check DRQ* during the interrupt handler to see if another byte (#2) is already waiting (if so, just read it in, to clear the serial chip's DRQ*, and stash the byte in memory right then), or use "level triggering" for interrupts, not "edge triggering". Edge triggering definitely has good uses, but you need to watch out for this.
I hope this is helpful. It sure took me long enough to figure it out the first time. Now I take great care on stuff like this.
Good luck, let me know how it goes.
thanks,
Dave Small
I want to iterate UDP port from 5000 to 50xx
How can I check if a specific port is already open or free to use?
I use this code but it always returns false:
public bool PortIsUsed(int myport)
{
bool alreadyinuse = (from p in System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners() where p.Port == myport select p).Count() == 1;
return alreadyinuse;
}
Normally when asking for a shared resource such as UDP port numbers, asking "is this available right now?" is not productive. Whichever answer you get may become incorrect in the next microsecond, as another application could change something that invalidates the answer.
What you can do is ask the OS to listen on a specific port ("acquire" the resource). The OS will either say yes, and here's a handle or whatever, or no, some other process is using that particular port. Either way, you get an answer that you can definitively act on. (Specifically, if you get no for an answer, try a different port.)
If I have a port that I need to read from quite a lot, and the returning amount of data varies from one line to many lines, what is the best way to read / sift through what I am reading?
After some research I found out what I was supposed to do.
string Xposition;
Xposition = "";
threeAxisPort.ReadExisting();
threeAxisPort.WriteLine("rx");
Thread.Sleep(50);
Xposition = threeAxisPort.ReadExisting();
threeAxisPort.WriteLine("end");
What I ended up doing was clearing the port of everything usign a ReadExisting function, then waited 50 ms to not flood the port, and did another ReadExisting command. With the additional 50ms wait time there was no leftover from the motors, and the returning block of text was exactly what I needed, however, I will still be thinking up of a more dynamic way to handle that string, because in a worst case scenario the read existing will pick up something I won't want.