I'm trying to establish a communication between two windows 10 devices:
Raspberry PI 2 B + Bluetooth dongle
Surface pro
Server at raspberry pi:
private readonly Guid _rfcommChatServiceUuid = Guid.Parse("34B1CF4D-1069-4AD6-89B6-E161D79BE4D8");
private async void CreateServer()
{
_provider = await RfcommServiceProvider.CreateAsync(RfcommServiceId.FromUuid(_rfcommChatServiceUuid));
_listener = new StreamSocketListener();
_listener.ConnectionReceived += OnConnectionReceived;
await _listener.BindServiceNameAsync(_provider.ServiceId.AsString(),SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
InitializeServiceSdpAttributes(_provider);
_provider.StartAdvertising(_listener);
}
const uint SERVICE_VERSION_ATTRIBUTE_ID = 0x0300;
const byte SERVICE_VERSION_ATTRIBUTE_TYPE = 0x0A; // UINT32
const uint SERVICE_VERSION = 200;
void InitializeServiceSdpAttributes(RfcommServiceProvider provider)
{
var writer = new DataWriter();
writer.WriteByte(SERVICE_VERSION_ATTRIBUTE_TYPE);
writer.WriteUInt32(SERVICE_VERSION);
var data = writer.DetachBuffer();
provider.SdpRawAttributes.Add(SERVICE_VERSION_ATTRIBUTE_ID, data);
}
async void OnConnectionReceived(
StreamSocketListener listener,
StreamSocketListenerConnectionReceivedEventArgs args)
{
_provider.StopAdvertising();
_listener.Dispose();
_listener = null;
_socket = args.Socket;
The client at surface:
var services = await DeviceInformation.FindAllAsync(
RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(_rfcommChatServiceUuid)));
The services collection is empty.
What is wrong with that?
Thanks
I think it is worth trying to hard code the address in client side. There is a sample C code of RFCOMM connections for both server and client.
The Bluetooth RFCOMM chat sample for Windows(universal) is here.
Related
I am using the sample from Microsoft. When an advertisement is received I am calling
BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
and then
device.GattServices()
but that always returns an empty list. Why is this happening? I have found no answer whatsoever.
If you want this to work by using advertisement watcher, you need to target the windows 10 creators update(10.0;Build 15063) and use the latest SDK, otherwise you will have to pair the device first.
To get the GattServices, first check if the device is not null.
Then use:
var serviceResult = await bluetoothLeDevice.GetGattServicesAsync();
if (serviceResult.Status == GattCommunicationStatus.Success)
{
//Do something with servivicResult list
}
But there is a catch; It can be that serviceResult.Status returns success, but not all or no services have been found yet.
My solution is to put it in a loop with a short delay and try it a few times until serviceResult count stays the same.
I wanted to put more explanation in my comment, but something went wrong and cannot edit my comment so I will add it as an answer.
I had exactly the same problem. for some reason you have to initialize your BLEdevice as null.
private BluetoothLEDevice device = null;
Also to prevent that you advertisementWatcher is setting your device over and over, use an if statement to set it only when the divice is null,
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
}
or if you want to set multiple devices than add them to a collection and make sure each device is only added once.
This is my working code :
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;
short rssi = eventArgs.RawSignalStrengthInDBm;
string localName = eventArgs.Advertisement.LocalName;
string manufacturerDataString = "";
var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
if (manufacturerSections.Count > 0)
{
// Only print the first one of the list
var manufacturerData = manufacturerSections[0];
var data = new byte[manufacturerData.Data.Length];
using (var reader = DataReader.FromBuffer(manufacturerData.Data))
{
reader.ReadBytes(data);
}
manufacturerDataString = string.Format("0x{0}: {1}",
manufacturerData.CompanyId.ToString("X"),
BitConverter.ToString(data));
}
string res = string.Format("type={0}, rssi={1}, name={2}, manufacturerData=[{3}]",
advertisementType.ToString(),
rssi.ToString(),
localName,
manufacturerDataString);
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
textBoxWatcher.Text = res;
});
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
if (device != null)
{
var deviceInfo = device.DeviceInformation;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (device.Name != string.Empty)
{
//ResultCollection is a observable observable collection of blueutooth devices
// to bind to a listvieuw,it is not needed!
ResultCollection.Add(new BleDevice(device));
if (deviceInfo.Name == "HMSoft")
{
if (ResultCollection[0] is BleDevice bleDevice)
{
BleDeviceId = bleDevice.Id;
SelectedBleDeviceName = bleDevice.Name;
}
Connect();
}
}
});
}
}
I've been trying to send JSON data from arduino mega by using ESP8266 as a wifi shield, and I've used node.js as a socket server. The problem is it seems that a server didn't receive any data. here is my code
#include <ArduinoJson.h>
#include "SoftwareSerial.h"
String ssid ="ssid";
String password="pwd";
//SoftwareSerial esp(22,23);// RX, TX
String data;
String server = "server ip";
byte objlength;
String url = "";
String temp,hum,weight;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
//String uri = "yourURI";
void reset() {
Serial2.println("AT+RST");
delay(1000);
if(Serial2.find("OK") ) Serial.println("Module Reset");
}
void connectWifi() {
String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";
Serial2.println(cmd);
delay(4000);
if(Serial2.find("OK")) {
Serial.println("Connected!");
Serial2.println("AT+CIPSTATUS");
delay(300);
while(Serial2.available()){Serial.print(Serial2.read());}
}
else {
connectWifi();
Serial.println("Cannot connect to wifi"); }
}
void setup() {
delay(5000);
// put your setup code here, to run once:
Serial2.begin(115200);
Serial.begin(115200);
reset();
connectWifi();
}
void loop() {
temp = 25.60;
hum = 65.3;
weight = 65.3;
root["weight"] = weight;
root["light"] = temp;
root["humid"] = hum;
objlength = root.measureLength();
senddata();
delay(10000);
}
void senddata()
{
int objlength = root.measureLength();
Serial2.println("AT+CIPSTART=\"TCP\",\"" + server + "\",1336");//start a TCP connection.
delay(500);
if( Serial2.find("OK")) {
Serial.println("TCP connection ready");
}
else
{
Serial.println("can't establish TCP connection");
}
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
Serial2.println(sendCmd);
delay(200);
Serial2.println(objlength);
delay(500);
if(Serial2.find(">"))
{
Serial.println("Sending..");
root.printTo(Serial2);
root.printTo(Serial);
//Serial.println(postRequest);
delay(2000);
if( Serial2.find("SEND OK"))
{
Serial.println("Packet sent");
delay(200);
while (Serial2.available()) {
String tmpResp = Serial2.readString();
Serial.println(tmpResp);
}
// close the connection
}
//delay(1000);
Serial2.print("+++");
delay(1200);
Serial2.println("AT+CIPCLOSE");
delay(50);
Serial.println("Closed");
}
}
Here's my node.js
var net = require('net');
var server = net.createServer(function(socket){
socket.write('SEND OK');
//
socket.pipe(socket);
socket.on('data',function(data){
//if(typeof data != 'string'){
var jsontest = JSON.parse(data);
console.log('Received: ' + data);
console.log(jsontest.weight);
console.log(jsontest.light);
console.log(jsontest.humid);
//}
});
socket.on('listening',function(){
console.log(listen);
});
});
/*server.getConnections(function(err,count){
console.log(count);
});*/
server.listen(1336, '10.42.0.1');
I think that esp8266 can establish a connection with a server , but I don't know why the data won't show. Maybe it's about esp8266 respond time?
screenshot
As you can see from this screenshot, I run node.js server and arduino ,but data won't show on server side. Due to this,I'm not sure where are the problems that cause this.
I'm not an expert. I'm just learning how to do it but i'd say you are not giving enough time through connections. You are relying on delays rather than timeouts while waiting for a true response. There is a difference.
Add much more time or change your strategy by using serial.available() and read in a loop that last a prudential amount of time, and exit when you got data.
Sorry no pasting some code, but i hope you got the idea.
Also i'm facing a power problem. 3,3v pin in arduino uno could be weak in clone boards. But i dont think that's the case.
I must access some data from IIS by connecting my IIS to a virtual machine to avoid any further configuration.
The code is running well but after I sideload my app, it seems that my app can't reach my data anymore. For example, I've got a folder called Video in my shared folder and I just changed:
static string adresse ="http://localhost"
into
static string adresse = "http://172.16.1.113";
the app can still run well when I am connected wireless to the network but when I use a device connected with fixed internet I got a message saying it can't connect to the server
public static async Task<List<Uri>> GetMedia()
{
try
{
List<Uri> target = new List<Uri>();
HtmlDocument document = new HtmlDocument();
var httpClient = new HttpClient();
var urlVideos = adresse + "/Videos";
var response = await httpClient.GetAsync(urlVideos);
var result = await response.Content.ReadAsStringAsync();
string htmlString = result;
document.LoadHtml(htmlString);
var collection = document.DocumentNode.DescendantsAndSelf();
foreach (HtmlNode link in collection)
{
if (link.Attributes.Contains("href") && !string.IsNullOrEmpty(link.Attributes["href"].Value.Trim().Trim('/')))
{
target.Add(new Uri(adresse + "" + link.Attributes["href"].Value));
}
}
return target;
}
catch (Exception)
{
string errors = "Proxy.getMedia" + iLine.ToString();
App.ProxyErrors = errors;
throw;
}
}
Any suggestions?
I found a solution I just had to go to app.manifest then capabilities
end enable private networks(Client and Server)
I can't seem to find the property for the MediaCapture class that allows me to detect the front camera and switch to it if available. Here is my current setup of the device, it all works as expected on Windows (front cam) and Phone (rear cam). None of the Microsoft samples show the front camera being used in Universal or WP 8.1 (WinRT/Jupiter).
mediaCaptureManager = new MediaCapture();
await mediaCaptureManager.InitializeAsync();
if (mediaCaptureManager.MediaCaptureSettings.VideoDeviceId != "" && mediaCaptureManager.MediaCaptureSettings.AudioDeviceId != "")
{
StartStopRecordingButton.IsEnabled = true;
TakePhotoButton.IsEnabled = true;
ShowStatusMessage("device initialized successfully!");
mediaCaptureManager.VideoDeviceController.PrimaryUse = CaptureUse.Video;
mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
mediaCaptureManager.SetRecordRotation(VideoRotation.Clockwise90Degrees);
mediaCaptureManager.RecordLimitationExceeded += RecordLimitationExceeded;
mediaCaptureManager.Failed += Failed;
}
There is a sample on the Microsoft github page that is relevant, although they target Windows 10. Still, the APIs should work on 8/8.1.
UniversalCameraSample: This one does capture photos, and supports portrait and landscape orientations. Here is the relevant part:
private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
{
// Get available devices for capturing pictures
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
// Get the desired camera by panel
DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
// If there is no device mounted on the desired panel, return the first device found
return desiredDevice ?? allVideoDevices.FirstOrDefault();
}
And you can use it like so:
// Attempt to get the front camera if one is available, but use any camera device if not
var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Front);
if (cameraDevice == null)
{
Debug.WriteLine("No camera device found!");
return;
}
// Create MediaCapture and its settings
_mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
// Initialize MediaCapture
try
{
await _mediaCapture.InitializeAsync(settings);
_isInitialized = true;
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("The app was denied access to the camera");
}
catch (Exception ex)
{
Debug.WriteLine("Exception when initializing MediaCapture with {0}: {1}", cameraDevice.Id, ex.ToString());
}
Have a closer look at the sample to see how to get all the details. Or, to have a walkthrough, you can watch the camera session from the recent //build/ conference, which includes a little bit of a walkthrough through some camera samples.
Here is how to get the device's available cameras and set the front one for the stream:
mediaCaptureManager = new MediaCapture();
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var deviceInfo = devices[0]; //grab first result
foreach (var device in devices)
{
if (device.Name.ToLowerInvariant().Contains("front"))
{
deviceInfo = frontCamera = device;
hasFrontCamera = true;
}
if (device.Name.ToLowerInvariant().Contains("back"))
{
rearCamera = device;
}
}
var mediaSettings = new MediaCaptureInitializationSettings
{
MediaCategory = MediaCategory.Communications,
StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo,
VideoDeviceId = deviceInfo.Id
};
await mediaCaptureManager.InitializeAsync(mediaSettings);
You'll need to consider rotation because front and rear cameras on different devices have different rotations, but this will initialize your MediaCapture properly
I'm trying to create an app that can use the camera for Windows Phone 8.1, using the Windows RT/XAML development model.
When I try to call either of the capture methods off of the MediaCapture class I get an ArgumentException with the message "The parameter is incorrect." Here is my code
private async Task Initialize()
{
if (!DesignMode.DesignModeEnabled)
{
await _mediaCaptureMgr.InitializeAsync();
ViewFinder.Source = _mediaCaptureMgr;
await _mediaCaptureMgr.StartPreviewAsync();
}
}
private async void ViewFinder_OnTapped(object sender, TappedRoutedEventArgs e)
{
ImageEncodingProperties imageProperties = ImageEncodingProperties.CreateJpeg();
var stream = new InMemoryRandomAccessStream();
await _mediaCaptureMgr.CapturePhotoToStreamAsync(imageProperties, stream);
_bitmap = new WriteableBitmap((int) ViewFinder.ActualWidth, (int) ViewFinder.ActualHeight);
stream.Seek(0);
await _bitmap.SetSourceAsync(stream);
PreviewImage.Source = _bitmap;
PreviewElements.Visibility = Visibility.Visible;
ViewFinder.Visibility = Visibility.Collapsed;
Buttons.Visibility = Visibility.Visible;
Message.Visibility = Visibility.Collapsed;
stream.Seek(0);
var buffer = new global::Windows.Storage.Streams.Buffer((uint) stream.Size);
stream.ReadAsync(buffer, (uint) stream.Size, InputStreamOptions.None);
DataContext = buffer.ToArray();
if (PhotoCaptured != null)
PhotoCaptured(this, null);
}
The initialize method is called on page load, and the viewfinder_ontapped is called when they tap the CaptureElement I have in the xaml. The error is thrown on
await _mediaCaptureMgr.CapturePhotoToStreamAsync(imageProperties, stream);
What's really bizarre is that I downloaded the latest source for the winrt xaml toolkit http://winrtxamltoolkit.codeplex.com/ and tried their sample camera app, which uses similar code. It throws the same error on MediaCapture.CapturePhotoToStorageFileAsync(). Can anyone help me identify why?