I'm using inTheHand library (32feet.NET).
I have a device with bluetooth enabled and I want to connect with the device to my computer and than send data from the device to computer. I then want to catch that information with my program and process it.
The device will send me 3 variables (all 3 float).
How do I catch that information with bluetooth? I never worked with bluetooth on a computer before.
I tried like this post said:
Pair bluetooth devices to a computer with 32feet .NET Bluetooth library
But don't know what I'm doing, so I can't make it work.
I'm using Visual Studio 2017 and Windows 10. I heard there are problems for Windows 10 and authenticating bluetooth devices.
Thanks for all the help!
UPDATE:
static string domaciaddress = "MY_ADDRESS";
static string tujadress = "DEVICE_ADDRESS";
//reciever
private static BluetoothEndPoint EP = new BluetoothEndPoint(BluetoothAddress.Parse(domaciaddress), BluetoothService.BluetoothBase);
private static BluetoothClient BC = new BluetoothClient(EP);
//sender
private static BluetoothDeviceInfo BTDevice = new BluetoothDeviceInfo(BluetoothAddress.Parse(tujadress));
private static NetworkStream stream = null;
static void neke231(string[] args)
{
string paircode = "paircode";
if (BluetoothSecurity.PairRequest(BTDevice.DeviceAddress, paircode))
{
Console.WriteLine("PairRequest: OK");
if (BTDevice.Authenticated)
{
Console.WriteLine("Authenticated: OK");
BC.SetPin(paircode);
BC.BeginConnect(BTDevice.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(Connect), BTDevice);
}
else
{
Console.WriteLine("Authenticated: No");
}
}
else
{
Console.WriteLine("PairRequest: No");
}
Console.ReadLine();
}
I now connect to my bluetooth like this. But I still don't know how to get those 3 floats that my device sends, and save it here in float, so I can later in program use them.
EDIT:
This code in fact doesn't work exactly... I don't know why, but it won't connect to android phone. When I run program instead of getting what I write into console, I get only BluetoothGetDeviceInfo returned: 0x80070057
Related
first StackOverflow question so hopefully its a decent one.
I'm in the process of making a sensor network using RPi's and Arduino boards. I have done this in the past using Raspbian but now have to do it using Windows IOT.
The Arduino Uno boards are connected to the Raspberry Pi using I2C communication. The problem is that my C# code produces a "Slave address is not recognized" error.
The RPi is configured as a master and the Arduino as a slave. There is no logic voltage converter, but it should work fine in this configuration as per:
https://create.arduino.cc/projecthub/phantom_override/arduino-i2c-ommunication-with-raspi-2-wiot-63d599?ref=user&ref_id=11763&offset=0
Will use a bidirectional voltage converter when I can get my hands on one.
I have tried the following:
1.) I2C connection between Windows IOT and Arduino Nano using C#
2.) Checking the connections between the RPi and the Arduino (SDA to SDA and SCL to SCL
3.) Adding 3.3V pullup resistors
4) Raspberry pi 2 and BMP280 : Slave address was not acknowledged
5.) Changing the slave address of the Arduino
6.) Swapping the both the Arduino and RPi out in case the pins were blown
7.) Digitally writing the Arduino pins low in case they were interfering with the i2c commmunication
Here is the corresponding Arduino Code:
//**********************Libraries**********************
#include <Wire.h>
//*********************Definitions*********************
#define SERIAL Serial
#define SLAVE_ADDRESS 0x40
//********************Global Variables*******************
float humidity, temperature, temp, motion;
byte ReceivedData[4];
byte Response[4];
bool DataReceived;
//Analoge Pin setup
int clockFrequency = 100000;
//***********************************Setup******************************
void setup(){
//digitalWrite(SCL, 0);
//digitalWrite(SDA, 0);
//i2c communication setup
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
//Wire.setClock(clockFrequency);
//Baud rate
Serial.begin(9600);
dht.begin();
}
//*********************************Loop*********************************
void loop()
{
getSensors();
delay(100);
}
void getSensors()
{
//sensors data retrieved
Response[0]=(byte)humidity;
Response[1]=(byte)temperature;
Response[2]=(byte)proximity;
Response[3]=(byte)motion;
}
void sendData()
{
Wire.beginTransmission(SLAVE_ADDRESS);
//Loop to iterate i2c transmissions
for (int i = 0; i <= 3; i++) {
Wire.write((uint8_t *)Response[i], sizeof(Response));
}
Wire.endTransmission();
}
And here is the corresponding C# methods for the RPi
private async Task InitI2C()
{
var settings = new I2cConnectionSettings(0x40); // Arduino address
settings.BusSpeed = I2cBusSpeed.StandardMode;
string aqs = I2cDevice.GetDeviceSelector("I2C1");
var dis = await DeviceInformation.FindAllAsync(aqs);
_device = await I2cDevice.FromIdAsync(dis[0].Id, settings);
}
private async Task GetArduino()
{
try
{
byte[] ReadBuf = new byte[32];
_device.Read(ReadBuf);
//convert buffer into floats here
}
Any help would be greatly appreciated as WIOT resources are quite scarce compared to other IOT OS's.
#MichaelXu-MSFT and #jdweng Thank you for your help. I worked out the problem. The Arduino code had unnecessary wire.beginTransmission and wire.endTransmission statements, which seem to be for sending data from master to slave on i2c, whereas I had a configuration of the master device requesting data from the slave. Just using the wire.write(data, length) length function in the sendData() ISR did the trick. I highly recommend http://www.gammon.com.au/i2c, as he has excellent i2c resources on his site.
The correction is as follows:
void sendData()
{
//Wire.beginTransmission(SLAVE_ADDRESS); remove this statement
Wire.write(Response, sizeof(Response));
//Wire.endTransmission(); remove this statement as well
}
This is small portion of window service code for fetching real-time attendance data from Biometric Device from cloud. Service is working but unable to get data from Device.This service is taking data from device and storing inside project folder making .log files.But when punched the card on device i get nothing.i am confusion on app.config files.There is local host(127.0.0.1:8080) as server in sdk of manufacturer which i got(but they are saying this is cloud based sdk).What should be server list in this case? Please help me.I am totally new in this WebSocketServer.
private void webSocketServer_NewMessageReceived(WebSocketSession session, string message) this method is used for registering new devices but this is not firing when i punched card to device.I am not pasting all codes here within this method.
using SuperWebSocket;
using SuperSocket.SocketBase;
public class WebSocketLoader
{
private static WebSocketServer webSocketServer;
public static Dictionary<string, string> _registeredDevices;
private WebSocketLoader(IWorkItem server)
{
var wsServer = server as WebSocketServer;
webSocketServer = wsServer;
}
public static WebSocketSession GetSessionByID(string sn)
{
if (_registeredDevices.ContainsKey(sn))
{
return webSocketServer.GetAppSessionByID(_registeredDevices[sn]);
}
else
return null;
}
public static void Setup(IWorkItem server)
{
var webSocketLoader = new WebSocketLoader(server);
webSocketLoader.AddNewMessageReceived();
webSocketLoader.AddNewSessionConnected();
webSocketLoader.AddSessionClosed();
_registeredDevices = new Dictionary<string, string>();
_registeredDevices.Clear();
}
public void AddNewMessageReceived()
{
webSocketServer.NewMessageReceived += new SessionHandler<WebSocketSession, string>(webSocketServer_NewMessageReceived);
}
public void AddNewSessionConnected()
{
webSocketServer.NewSessionConnected += new SessionHandler<WebSocketSession>(webSocketServer_NewSessionConnected);
}
private void webSocketServer_NewSessionConnected(WebSocketSession session)
{
Console.WriteLine(webSocketServer.GetAllSessions().Count());
LogHelper.Receive("NewConnected[" + session.RemoteEndPoint + "]");
}
private void webSocketServer_SessionClosed(WebSocketSession session, CloseReason reason)
{
LogHelper.Receive("Closed[" + session.RemoteEndPoint + "],Reason:" + reason);
}
private void webSocketServer_NewMessageReceived(WebSocketSession session, string message)
{
Console.WriteLine(webSocketServer.GetAllSessions().Count());
LogHelper.Receive("MessageReceived[" + session.RemoteEndPoint + "],Message:" + message);
}
}
App.config file contains following line
<RedisConfig WriteServerList="127.0.0.1:8080" ReadServerList="127.0.0.1:8080" MaxWritePoolSize="10000" MaxReadPoolSize="10000" DB="1" AutoStart="true" LocalCacheTime="180" RecordeLog="false">
127.0.0.1 meant for localhost. You need to update a valid IP and PORT in the biometric machine. Then if you use that IP & Port your code may work. Make sure the machine is connected in the same network.
In general, biometric machines can be not be associated with the public IP. Hence, TCP/IP communication with the machines installed in the remote location can not be done through cloud application.
For cloud communication from biometric machine, web api supported biometric machines can be used.
I'm attempting to write a C# library which looks at all available USB serial ports on a Raspberry Pi so that I can enumerate, identify and communicate with a set of Arduinos connected to the Pi via a USB hub.
I am able to make this work on my windows machine (several Arduinos connected to my desktop computer) and have even been able to make it work on my Pi however, I am struggling to understand how to generalize the fix.
If I attempt to run the program by itself on the Pi, I am able to open the serial port and send data however, I cannot receive anything from the Arduinos: I get timeout exceptions. I understand that Mono's implementation of SerialPort is limited and I must use SerialPort.ReadByte() instead of Readline() and the data received events (my solution is based on code from HowToSystemIOPorts). My Serial port enumeration is using a method outlined in another stack exchange response here.
My timeout is currently set to 4 seconds, which is several orders of magnitude longer than I expect to receive the message.
After a lot of googling, I came across mention of using minicom to initialize the serial port here, which to my surprise allowed me to receive data from the Arduino. The biggest drawback is that I need to initialize the port using minicom and leave the process opening each time I boot the Pi. I also can't seem to figure out how to make this work with multiple Arduinos.
Here is what I have tried so far:
Updated the Pi firmware and software to their latest versions
Attempted to use both an Arduino MEGA 2560 R3 and Arduino UNO
Changed the owner of the tty* ports (ttyACM0 and ttyUSB0 in this case) to both my user and group
Successfully configured the port via minicom, left the process running and start the program and read/wrote data. A manual process which only seems to work for one Arduino at a time
Successfully run the program in Windows without fault
Verified the Arduinos are recognized by the Pi running "dmesg | grep tty"
Here is what I hope to solve:
Automatic setup/initialization of the Arduino serial ports. Whether through a shell script run before the main program or within Mono code so that the code below can run as intended.
Here is my connection code:
public bool StartArduinoComms()
{
string[] ports = GetPortNames();
foreach (string port in ports)
{
mLogger.LogMessage(ProsthesisCore.Utility.Logger.LoggerChannels.Arduino, string.Format("Found serial port {0}", port));
}
bool foundCorrectArduino = false;
var idPacket = new ArduinoMessageBase();
idPacket.ID = ArduinoMessageValues.kIdentifyValue;
string jsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(idPacket);
foreach (string port in ports)
{
SerialPort serialPort = new SerialPort(port, kArduinoCommsBaudRate);
serialPort.Parity = Parity.None;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
//Only check unopened ports
if (!serialPort.IsOpen)
{
serialPort.Open();
//Disable telemtry just incase
var toggle = new { ID = ArduinoMessageValues.kTelemetryEnableValue, EN = false };
string disableTelem = Newtonsoft.Json.JsonConvert.SerializeObject(toggle);
serialPort.Write(disableTelem);
//Discard any built up data
serialPort.DiscardInBuffer();
serialPort.Write(jsonOutput);
serialPort.ReadTimeout = kIDTimeoutMilliseconds;
string response = string.Empty;
for (int i = 0; i < kNumRetries; ++i)
{
try
{
//This is guaranteed to timeout if not configured through minicom
response = ReadLine(serialPort);
break;
}
//Catch case where the serial port is unavailable. MOve to next port
catch (TimeoutException)
{
continue;
}
}
if (!string.IsNullOrEmpty(response))
{
//Perform response validation
}
else
{
//Got no response
}
if (!foundCorrectArduino)
{
serialPort.Close();
}
}
}
return foundCorrectArduino;
}
/// <summary>
/// From https://stackoverflow.com/questions/434494/serial-port-rs232-in-mono-for-multiple-platforms
/// </summary>
/// <returns></returns>
private 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 = System.IO.Directory.GetFiles("/dev/", "tty*");
foreach (string dev in ttys)
{
//Arduino MEGAs show up as ttyACM due to their different USB<->RS232 chips
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
{
serial_ports.Add(dev);
}
}
}
else
{
serial_ports.AddRange(SerialPort.GetPortNames());
}
return serial_ports.ToArray();
}
Have a look at stty command. It will let you set/read teminal settings
http://linux.about.com/od/lna_guide/a/gdelna38t01.htm will give a rundown on it's use.
It would be easier to call out to than minicom, and the settings stay on the device.
I have done something like the same as you before.
I had to read and write data through USB Serial adapter, and didnt use minicom.
It may not be god code but i found that inorder to read the data I could create a new thread and have that check for data, my code include a lot of stuff but basicly i did this:
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(this.check_get_data);
and the check_get_data method
public void check_get_data ()
{
byte tmpByte = 0;
while (m_objSerialPort.BytesToRead != 0) {
tmpByte = (byte)m_objSerialPort.ReadByte ();
DoSomethingWithByte(tmpByte);
Thread.Sleep(20);
}
}
this is currently running with two usbserials. dont know if it helps but hope you find your solution
I am trying to connect my computer with android phone to transmit some data. For computer programming language i have chosen c#.
On computer the code looks like this:
var wantedAddress="303926627f06";
var addr = BluetoothAddress.Parse(wantedAddress);
var cli = new BluetoothClient();
cli.Connect(addr, new Guid("{00001101-0000-1000-8000-00805f9b34fb}"));
And on a android phone code looks like:
private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private BluetoothAdapter btAdapter= BluetoothAdapter.getDefaultAdapter();
private BluetoothServerSocket server=btAdapter.listenUsingRfcommWithServiceRecord("App name",uuid);
while(isRunning)
{
try {
BluetoothSocket socket=server.accept();
} catch (IOException e) {
isRunning=false;
e.printStackTrace();
}
}
After trying to connect to the phone i get this error:
SocketException:
The requested address is not valid in its context 303926627F06:0000110100001000800000805f9b34fb
Does anyone know what is wrong?
Thank you for help!
Jure
See error codes at https://32feet.codeplex.com/wikipage?title=Errors So that suggests that the client is not finding the server with the expected UUID running on the target device. Now why...
If you use 32feet.NET SdpBrowser sample and list all the SDP Services "(over L2CAP)" what do you see?
Are you connecting to the correct device address?
We have several devices where I work (mostly Datalogic 4420 Falcon), and someone is always leaving one off the base. The battery runs dry, then they bring them back to get setup all over. (There's supposed to be a way to configure a file on the SD card to reload upon such an error, but it doesn't work very well)
When someone saves changes on the device (using my app that writes data to the SQL Server), the Serial Number is sent along with it so we can track what devices are in use where.
Each device has a Serial Number, and I have to physically (i.e. manually) write that into the Device name field, which I can read. Working code here if anyone wants to know how:
static string deviceId = null;
public static string DeviceName {
get {
if (String.IsNullOrEmpty(deviceId)) {
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Ident", true)) {
try {
deviceId = key.GetValue("Name", "[Unnamed]").ToString();
} catch (Exception e) {
ErrorWrapper("GetDeviceName", e);
deviceId = Dns.GetHostName();
} finally {
key.Flush();
key.Close();
}
}
}
return deviceId;
}
}
I do not like the manual (i.e. Fat Finger prone) Serial Number entry. Is there some call to query the device's Serial Number, or is that vendor specific?
Datamax does make an SDK that is specific to their devices, but we don't want our applications tied down to any one manufacturer (we are already tied down to VS2008).
I'd start by trying to P/Invoke to get the device ID (KerneIoControl with IOCTL_HAL_GET_DEVICEID) and see if it matches the serial number you're after. Here's an example.
I don't know about your Datalogic 4420 Falcon device, but I work with Intermec CK30 & CK60 and I have their itc50.dll file.
Here is snippet:
[DllImport("itc50.dll")]public static extern int ITCGetSerialNumber(StringBuilder Snumber, int buffSize);
StringBuilder hwSN = new StringBuilder(12);
if (ITCGetSerialNumber(hwSN, hwSN.Capacity) >= 0)
{
;
;
}