Can a BLE Server identify which component is connected to it? - server

I have this project, where I need to create a BLE-Server (ESP32) to exchange data with a Laptop/Smartphone etc.... . The code is written with Arduino IDE, using the ESP32 BLE Arduino library and seems like the following
void Setup() {
BLEDevice::init("MIDI_BOX"); // Name of the BLE_Device
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
MIDI_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_WRITE_NR
);
pCharacteristic->addDescriptor(new BLE2902());
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
};
Having this said, when I want to connect my Laptop or Smartphone to this server. It needs to indetify which kind of device is connected to(Apple, Microsoft,). The manufacturer data seems a good idea for me but I don't how to get this information when there is a connection.
A callback fonction is provided by the BLEServer:
class MyServerCallbacks: public BLEServerCallbacks { //can I here do smth to get manufacturer data ??
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
Can anyone explain to me how it should be done, or are there any better way of thinking ?
Thnx in advance

Related

I want to make a P2P networked (thinking about using mirror) game with unity, with no dedicated server, similar to Terraria and Valheim

I have managed to basically connect with my friend over internet, by forwarding my IP address from my router settings... this is not viable because there are few people willing to do what I did to play games with their friends. So how to actually do UDP hole punching (basically what I did manually to my router) in unity using the mirror networking solution...
A common solution to this problem is WebRTC, which takes care of the hole punching under the hood. Unity maintains this package which implements WebRTC. They also provide a great tutorial on how to use it. The nuts and bolts of it are:
using UnityEngine;
using Unity.WebRTC;
public class MyPlayerScript : MonoBehaviour
{
RTCPeerConnection localConnection, remoteConnection;
RTCDataChannel sendChannel, receiveChannel;
private void Awake()
{
// Initialize WebRTC
WebRTC.Initialize();
// Create local peer
localConnection = new RTCPeerConnection();
sendChannel = localConnection.CreateDataChannel("sendChannel");
channel.OnOpen = handleSendChannelStatusChange;
channel.OnClose = handleSendChannelStatusChange;
// Create remote peer
remoteConnection = new RTCPeerConnection();
remoteConnection.OnDataChannel = ReceiveChannelCallback;
// register comms paths
localConnection.OnIceCandidate = e => {
!string.IsNullOrEmpty(e.candidate)
|| remoteConnection.AddIceCandidate(ref e);
}
remoteConnection.OnIceCandidate = e => {
!string.IsNullOrEmpty(e.candidate)
|| localConnection.AddIceCandidate(ref e);
}
localConnection.OnIceConnectionChange = state => {
Debug.Log(state);
}
}
//handle begin
IEnumerator Call(){
var op1 = localConnection.CreateOffer();
yield return op1;
var op2 = localConnection.SetLocalDescription(ref op1.desc);
yield return op2;
var op3 = remoteConnection.SetRemoteDescription(ref op1.desc);
yield return op3;
var op4 = remoteConnection.CreateAnswer();
yield return op4;
var op5 = remoteConnection.setLocalDescription(op4.desc);
yield return op5;
var op6 = localConnection.setRemoteDescription(op4.desc);
yield return op6;
}
//handle send messages
void SendMessage(string message)
{
sendChannel.Send(message);
}
void SendBinary(byte[] bytes)
{
sendChannel.Send(bytes);
}
//handle receive messages
void ReceiveChannelCallback(RTCDataChannel channel)
{
receiveChannel = channel;
receiveChannel.OnMessage = HandleReceiveMessage;
}
void HandleReceiveMessage(byte[] bytes)
{
var message = System.Text.Encoding.UTF8.GetString(bytes);
Debug.Log(message);
}
//handle end
private void OnDestroy()
{
sendChannel.Close();
receiveChannel.Close();
localConnection.Close();
remoteConnection.Close();
WebRTC.Finalize();
}
}
I have also found a useful way to do this using mirror and the epic free relay for this. Thanks so much for the other answers, it really helped understand better what I needed to search and use!
You can use Photon Bolt or Photon Fusion to let players host a game on their local machine like minecraft, etc. Photon provides relay as well as tries to use STUN to establish direct peer to peer connection to the host via UDP. PUN2 is also a good choice, although I like Photon Bolt/Fusion better - it's less of a simple RPC framework and more programmer oriented. Also, PUN does not do any STUN direct peer connection, it will always be relayed. Photon Bolt and Fusion will first attempt a STUN direct peer connection and then fallback to relay if necessary. It's been around for years and is the best choice.
Sure you can develop a Unity game with Mirror (although without a relay built in) but it's not nearly as easy to setup and use as Photon Bolt/Fusion and they don't provide a relay. As someone mentioned, you might be able to hack something together in some way but yeah - not recommended.
Ugh, yeah don't use WebRTC for a Unity game (or probably anything other than streaming music/video like it was made for to be honest).
Unity's MLAPI is "under development" and their last API was suddenly dropped "deprecated", so I wouldn't use that.

Connection not working from Android to UWP on desktop - ZeroMq (NetMq)

I tried some examples of ZMQ on C++,C# and Python. I am trying to have Request-Reply pattern to connect Android device to PC running UWP with Xamarin forms.
Below is the Requestor code:
public void HelloWorld()
{
var timer = new Timer(60000);
timer.Start();
timer.Elapsed += (sender, args) =>
{
this.Cancel = true;
timer.Stop();
};
// Create
const string endpoint = "tcp://PC_ip:3245";
using (var request = new RequestSocket())
{
request.Bind(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
request.SendFrame("Requester says hello");
var reply = request.ReceiveFrameString();
Debug.WriteLine("Gets reply {0}",reply);
}
}
}
Reply socket code:
public void HelloWorld()
{
var timer = new Timer(60000);
const string endpoint = "tcp://PC_ip:3245";
timer.Start();
timer.Elapsed += (sender, args) =>
{
timer.Stop();
Cancel = true;
};
using (var replierSocket = new ResponseSocket())
{
replierSocket.Connect(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
var replyFromRequester = replierSocket.ReceiveFrameString();
Debug.WriteLine("Got reply {0}", replyFromRequester);
replierSocket.SendFrame("Response socket say hello");
}
}
}
Cancel is boolean
I went through some questions posted on this and added delay and these connection code blocks only trigger after button clicks on app.
While debugging , request.ReceiveFrameString() replierSocket.ReceiveFrameString(); are not even hit.
I am new to network programming , I understand that for REQ/REP pattern the code has to be in particular order which I traced and fixed I believe and turned off firewall on my PC so that firewall wont block my incoming connections from Android device.
PC_ip stands for IPv4 address I got from ipconfig /all for my wifi. I also tried external ip of my machine from sites like whatsmyip.org at ResponseSocket but I still dont get response between devices.
Please let me know what am I doing wrong.
Issue replication repository : GitHub/me/XamZeroMq

Write to HID with Chip Selection with .NET Console App

Hi I am writing a simple console app that needs to write bytes to MCP2210 USB to SPI Master
I found this library over here, seems to do good job with connecting the device and reading the metadata.
I am writing message to the board as below
public static byte[] Talk()
{
var device = DeviceList.Local.GetHidDevices(1240, 222).FirstOrDefault();
if (device == null)
{
Console.WriteLine($"Could not find a device with Vendor Id:1240, Product Id:222 ");
return null;
}
var reportDescriptor = device.GetReportDescriptor();
foreach (var deviceItem in reportDescriptor.DeviceItems)
{
Console.WriteLine("Opening device for 20 seconds...");
if (!device.TryOpen(out var hidStream))
{
Console.WriteLine("Failed to open device.");
continue;
}
Console.WriteLine("Opened device.");
hidStream.ReadTimeout = Timeout.Infinite;
hidStream.Write(new byte[3] {60, 00, 00});
}
Not sure If I am writing it correctly.
While writing I need to do a chip selection as displayed in this other terminal
Any help is greatly appreciated
Here is the MC I am using https://www.microchip.com/wwwproducts/en/MCP2210
I do not see a closing of your stream. This may cause your data to not even being sent (at least not in time).
Consider using blocks with streams.
But with out parameters not possible.

Probe problem when writing a I2C device driver

I am a newbie in writing linux device driver, forgive me if anything stupid a asked and my poor English^^
I am trying to write a driver for a touch panel, which communicate with CPU via I2C.
I tried to add a device driver into linux platform, and the register was success, I mean the driver was loaded, but the probe function didn't fired up!!
Above is partial code of the driver i wrote.
static int i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id * id) {
/* ... */
}
static int i2c_ts_remove(struct i2c_client *client) {
/* ... */
}
static const struct i2c_device_id i2c_ts_id[] = {
{"Capacitive TS", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, i2c_ts_id);
static struct i2c_driver i2c_ts = {
.id_table = i2c_ts_id,
.probe = i2c_ts_probe,
.remove = i1c_ts_remobe,
.driver = {
.name = "i2c_ts",
},
};
static int __init i2c_ts_init(void) {
return i2c_add_driver(&i2c_ts);
}
static int __init i2c_ts_exit(void) {
return i2c_del_driver(&i2c_ts);
}
module_init(i2c_ts_init);
module_exit(i2c_ts_exit);
Above is partial code in platform (/kernel/arch/arm/mach-pxa/saarb.c) used for registering the i2c device.
static struct i2c_board_info i2c_board_info_ts[] = {
{
.type = i2c_ts,
.irq = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO0)),
},
};
static void __init saarb_init(void) {
...
i2c_register_board_info(0, ARRAY_AND_SIZE(i2c_board_info_ts));
...
}
any suggestion and comment will be welcome, thanks^^
So that the linux device/driver model can probe your driver, there must be a device requesting it: this is achieved by comparing the name of the driver ("i2c_ts") and the type of the device in the i2c_board_info struct. In your case I guess the type is not equal to "i2c_ts".
So I would suggest that you use the I2C_BOARD_INFO macro to instantiate your device, as documented in Documentation/i2c/instantiating_devices.
static struct i2c_board_info i2c_board_info_ts[] = {
{
I2C_BOARD_INFO("i2c_ts", 0x12),
.irq = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO0)),
},
};
static void __init saarb_init(void) {
...
i2c_register_board_info(0, ARRAY_AND_SIZE(i2c_board_info_ts));
...
}
You had also not given an address to your device, and I2C_BOARD_INFO needs it. Read the datasheet of your touchscreen to know what that address is.
Finally, as suggested above, be sure that i2c_ts_id is correct. I am not sure it plays a role in the device/module association mechanism in the kernel, but I would say it's far less confusing it they all share the same name.
Probe method will only be called when the device matches the driver name.As you have mentioned your driver name as 'i2c_ts' please check your device tree for the device name.Both should be same.

sending and receiving broadcast messages

Guys I need some help here..
I am doing a project in c# where the data needs to be sent as a datagram and receive data too which is broadcast.
The following is the code:
public void StartUdpListener(Object state)
{
receivedNotification = udpServer.Receive(ref remoteEndPoint);
notificationReceived = Encoding.ASCII.GetString(receivedNotification);
listBox = new StringBuilder(this.listBox1.Text);
listBox.AppendLine(notificationReceived);
if (listBox1.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { this.listBox1.Items.Add(listBox.ToString()); });
}
}
public void StartNotification()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartUdpListener));
hostName = Dns.GetHostName();
hostBuffer = Encoding.ASCII.GetBytes(hostName);
UdpClient newUdpClient = new UdpClient();
newUdpClient.Send(hostBuffer, hostBuffer.Length, notifyIP);
}
Could you guys please tell me if the code is fine because there is no one around with whom i can test the code on lan
Thanks a ton guys.
Why don't you set up your own broadcaster and listener in separate instances.
This is a great article on socket programming in c#