c# Bluetooth LE - write configuration error - ValueChanged never called - c#
So I try to connect my c# WPF program to a BLE device and this is the code to connect to the device:
private async Task ConnectToWatcher(DeviceInformation deviceInfo) {
try {
// get the device
BluetoothLEDevice device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
// get the GATT service
Thread.Sleep(150);
var gattServicesResult = await device.GetGattServicesForUuidAsync(new Guid(RX_SERVICE_UUID));
service = gattServicesResult.Services[0];
// get the GATT characteristic
Thread.Sleep(150);
var gattCharacteristicsResult = await service.GetCharacteristicsForUuidAsync(new Guid(RX_CHAR_UUID));
characteristic = gattCharacteristicsResult.Characteristics[0];
// register for notifications
Thread.Sleep(150);
characteristic.ValueChanged += (sender, args) => {
Debug.WriteLine($"[{device.Name}] Received notification containing {args.CharacteristicValue.Length} bytes");
};
GattWriteResult result =
await characteristic.WriteClientCharacteristicConfigurationDescriptorWithResultAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
Debug.WriteLine($"Characteristics write result: status={result.Status}, protocolError={result.ProtocolError}");
} catch (Exception ex) when ((uint)ex.HResult == 0x800710df) {
Debug.WriteLine("bluetooth error 1");
// ERROR_DEVICE_NOT_AVAILABLE because the Bluetooth radio is not on.
}
}
The line
Debug.WriteLine($"Characteristics write result: status={result.Status}, protocolError={result.ProtocolError}"
creates the output
Characteristics write result: status=protocolError, protocolError=3
I couldn't find anywhere whats that supposed to mean. The effect is the Method characteristic.ValueChanged never gets called.
Do I have to do more to have the characteristic configurated? And has anybody any idea why the method isn't called or what that error message means?
Thanks a bunch.
Apparently, some Windows 10 builds have a COM security bug.
Solution was to register for Windows-Insider-Program and update Windows.
Update:
There are two more solutions to this:
1) Calling CoInitializeSecurity from outside your c#-code (didn't bring it to work)
- or-
2) Writing two new keys into the windows registry. You cann create a file "Bluetooth.reg", which will add those two keys on a doubleklick. This answer from https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-complete-on-10015063?forum=wdk was my solution:
Hi Kamen, I have experienced exactly same issue. You can give a quick try of the following:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID{C6BFD646-3DF0-4DE5-B7AF-5FFFACB844A5}]
"AccessPermission"=hex:01,00,04,80,9c,00,00,00,ac,00,00,00,00,00,00,00,14,00,\
00,00,02,00,88,00,06,00,00,00,00,00,14,00,07,00,00,00,01,01,00,00,00,00,00,\
05,0a,00,00,00,00,00,14,00,03,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00,\
00,00,18,00,07,00,00,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00,00,\
00,18,00,03,00,00,00,01,02,00,00,00,00,00,0f,02,00,00,00,01,00,00,00,00,00,\
14,00,03,00,00,00,01,01,00,00,00,00,00,05,13,00,00,00,00,00,14,00,03,00,00,\
00,01,01,00,00,00,00,00,05,14,00,00,00,01,02,00,00,00,00,00,05,20,00,00,00,\
20,02,00,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\YOURAPP.exe]
"AppID"="{C6BFD646-3DF0-4DE5-B7AF-5FFFACB844A5}"
Copy above content to a text file.
Replace 'YOURAPP.EXE' with your executable name
Optionally replace GUIDs (I have created a new one for you)
Save text file with an extension as .reg
Double click on the file.
You would see a message 'The Keys and values contained in ..... .reg have been successfully added to the registry.'
With this, I don't need to call CoInitializeSecurity from my app.
you need to call CoInitializeSecurity before
more info here. couple of weeks I spent looking for solution :)
https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/
Related
How to determine if the PC has been rebooted since my program's last run?
The title says it all. What is the best way to determine if the PC has been rebooted since my program's last run? Context: C# - Win XP and on A piece of hardware (PCIe board) that I'm configuring requires the settings to only be sent once per power cycle but users may close and open the program multiple times before power cycling the PC. I'm thinking I need some sort of a global reference that my program starts/sets while starting then it can check if said global reference is running/true at each start up and act accordingly. Ideas? Suggestions?
See How to know when was Windows started or shutdown on how to get the last boot time. You can write the boot time to a file. When you start your program you can check if the saved value match the current value or not, and update the file with the new value if needed. See also Getting last reboot time
As user Panagiotis Kanavos commented, an event log entry is written when Windows boots. If you have a look in Event Viewer in the System log, you will find those entries have Event ID == 12, which is accessed in code by using the InstanceId property of an EventLogEntry (the EventID property is deprecated). So you can get all those log entries, sort them, and get the latest one, like this: using System; using System.Diagnostics; using System.Linq; namespace ConsoleApp2 { class Program { static void Main(string[] args) { EventLog systemLog = new EventLog("System"); var bootEntry = systemLog?.Entries.Cast<EventLogEntry>(). Where(x => x.InstanceId == 12). OrderByDescending(x => x.TimeGenerated). FirstOrDefault(); if (bootEntry != null) { Console.WriteLine("Last boot: " + bootEntry.TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss")); } else { Console.WriteLine("Could not open System log or no boot event found."); } Console.ReadLine(); } } } (Tested as working on Windows 10 20H2.) Now, my computer has a fast SSD, and my experience of reading the event logs from an HDD is that that can be sloooooow, so you might want to get the entry in some background task.
It looks possible to look up the boot time in the Windows Event Log. I haven't verified this, but maybe this can work for you. Manually, you can use the Event Viewer to find the PC's boot time. This will get you the information you need to make the programmatics call to get the relevant data. You'd do something like this (not a complete solution): var logs = EventLog.GetEventLogs(); // not sure about this; you may need to change the search below... var log = logs.Single(l => l.LogDisplayName == "Application and Services Log"); // search entries var bootEntries = log.Entries.Where(x => ...); ... This uses these APIs EventLog class EventLog.GetEventLogs() method EventLog.Entries property EventLogEntry class So, it looks like it's possible to drill down to the entry you need, grab out the timestamp and do your various checks. Good luck!
Save the last boot time (e.g. in user.config) and then compare it with the current value. Environment.TickCount64 keeps track of the time since the system started. var storedLastBootTime = LoadBootTimeFromSettings(); var currentTime = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; var lastBootTime = currentTime - Environment.TickCount64; if (lastBootTime > storedLastBootTime) { // A system reboot must have taken place! } SaveBootTimeToSettings(lastBootTime); If the saved value is greater, a restart must have taken place. To handle that you need to save the current time too.
What is the proper way of using the Windows.Media.Miracast namespace?
I am looking into screen casting through Miracast in an application but am unsure of how to use the Windows.Media.Miracast namespace. Limited information exists on the internet due to the short age of the Windows 10 1903 update that the namespace comes as a part of. The only thing I've found so far is this documentation. My question is does anybody know what the proper way of using this namespace is? Any examples or resources found online would be a great help. Cheers.
These three sample projects demonstrate various MiraCast source apis that can be used from UWP applications. Not sure about outside UWP. https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BasicMediaCasting https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/AdvancedCasting https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/Projection I'm personally using code like the following, on Windows IoT Core, to cast my whole screen Scan for devices: miraDeviceWatcher = DeviceInformation.CreateWatcher(CastingDevice.GetDeviceSelector(CastingPlaybackTypes.Video)); miraHandlerAdded = new TypedEventHandler<DeviceWatcher, DeviceInformation>(async (watcher, deviceInfo) => { await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { //Add each discovered device to our listbox CastingDevice addedDevice = await CastingDevice.FromIdAsync(deviceInfo.Id); var disp = new CastingDisplay(addedDevice); //my viewmodel MiraDevices.Add(disp); //ObservableCollection }); }); miraDeviceWatcher.Added += miraHandlerAdded; Connect to selected device: public async Task StartCasting(CastingDisplay castee) { //When a device is selected, first thing we do is stop the watcher so it's search doesn't conflict with streaming if (miraDeviceWatcher.Status != DeviceWatcherStatus.Stopped) { miraDeviceWatcher.Stop(); } //Create a new casting connection to the device that's been selected connection = castee.Device.CreateCastingConnection(); //Register for events connection.ErrorOccurred += Connection_ErrorOccurred; connection.StateChanged += Connection_StateChangedAsync; var image = new Windows.UI.Xaml.Controls.Image(); await connection.RequestStartCastingAsync(image.GetAsCastingSource()); } This Image is just used as a casting source. Once the connection is made, my whole screen is broadcast. The behavior is not documented. Hopefully it won't get 'fixed' in a future update.
Read data via bluetooth using c#
I am using Lecia Disto e7100i which basically measures distance and area using laser. This device has bluetooth and can be paired with windows. I am trying to develop an wpf app that reads the mesaured data using c# There is no sdk that comes along with the device. I have tried to use 32feet.Net but since there is no proper documentation I don't know where to start. Is there any way that I can do to solve my problem?
This is not a full response, instead its more of a guideline on how to resolve your issue: Pair the device with your Computer Run the included software that displays the data somehow Use WireShark to analyze the traffic see if it is a standard protocol type or something custom understand the protocol and reimplement it using c# and BluetoothSockets
To get started, you can try: var client = new BluetoothClient(); // Select the bluetooth device var dlg = new SelectBluetoothDeviceDialog(); DialogResult result = dlg.ShowDialog(this); if (result != DialogResult.OK) { return; } BluetoothDeviceInfo device = dlg.SelectedDevice; BluetoothAddress addr = device.DeviceAddress; Console.WriteLine(device.DeviceName); BluetoothSecurity.PairRequest(addr, "PIN"); // set the pin here or take user input device.SetServiceState(BluetoothService.HumanInterfaceDevice, true); Thread.Sleep(100); // Precautionary if (device.InstalledServices.Length == 0) { // handle appropriately } client.Connect(addr, BluetoothService.HumanInterfaceDevice); Also make sure that Device appears in "Bluetooth devices" in the "Control panel". Device is HID or change code accordingly. Hope it helps. Cheers!
Try this demo project, and the following articles after that one. Try to follow this tutorial Here you can see a direct answer by the mantainer of 32feet, with which you can get in touch Check also this answer
how to get real time log via perforce api similar to p4v log
I am facing issue with perforce api (.net), as i am unable to pull sync logs in real time. - What am I trying to do I am trying to pull real time logs as Sync is triggered using the Perforce.P4.Client.SyncFiles() command. Similar to the P4V GUI Logs, which update when we try to sync any files. - What is happening now As the output is generated only after the command is done execution its not something intended for. Also tried looking into Perforce.P4.P4Server.RunCommand() which does provide detailed report but only after the execution of the command. Looked into this Reason is - I am trying to add a status update to the Tool i am working on which shows which Perforce file is currently being sync'd. Please advise. Thanks in Advance. -Bharath
In the C++ client API (which is what P4V is built on), the client receives an OutputInfo callback (or OutputStat in tagged mode) for each file as it begins syncing. Looking over the .NET documentation I think the equivalents are the P4CallBacks.InfoResultsDelegate and P4CallBacks.TaggedOutputDelegate which handle events like P4Server.InfoResultsReceived etc.
I ended up with the same issue, and I struggled quite a bit to get it to work, so I will share the solution I found: First, you should use the P4Server class instead of the Perforce.P4.Connection. They are two classes doing more or less the same thing, but when I tried using the P4.Connection.TaggedOutputReceived events, I simply got nothing back. So instead I tried with the P4Server.TaggedOutputReceived, and there, finally, I got the TaggedOutput just like I wanted. So, here is a small example: P4Server p4Server = new P4Server(cwdPath); //In my case I use P4Config, so no need to set user or to login, but you can do all that with the p4Server here. p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent; p4Server.ErrorReceived += P4ServerErrorReceived; bool syncSuccess=false; try { P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\..."); P4CommandResult rslt = syncCommand.Run(); syncSuccess=true; //Here you can read the content of the P4CommandResult //But it will only be accessible when the command is finished. } catch (P4Exception ex) //Will be caught only when the command has failed { Console.WriteLine("P4Command failed: " + ex.Message); } And the method to handle the error messages or the taggedOutput: private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data) { Console.WriteLine("P4ServerErrorReceived:" + data); } private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj) { Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]); //Write the synced file name. //Note that I used this only for a 'Sync' command, for other commands, I guess there might not be any Obj["clientFile"], so you should check for that. }
async Pedometer.GetSystemHistoryAsync API for Universal apps crashes
I'm trying to throw together a simple app that uses pedometer data on a Windows 10 phone. I normally live down in kernel-land, and this is my first time using most of the c# async stuff, so I'm wondering if I'm missing a core concept here. My first attempt at getting data out was to simply report the number of recorded steps over the last hour to a textbox in my XAML app. I just created a basic XAML app, dropped a text box in, and added this event handler: private async void Page_Loaded(object sender, RoutedEventArgs e) { var history = await Pedometer.GetSystemHistoryAsync(DateTimeOffset.Now.AddHours(-1), TimeSpan.FromHours(1)); int count = history.Sum(entry => entry.CumulativeSteps); textSteps.Text = count.ToString(); } A breakpoint on the first line triggers, but before it hits the next line I get an unhandled exception. Error code -2147467259, message "Error HRESULT E_FAIL has been returned from a call to a COM component." The top frame of the stack is in my code, but it's just the boilerplate line from App.g.i.cs that triggers a break on an unhandled exception. Below that is mscorlib and the WinRT invoker. I looked through the app capabilities list in the manifest, and didn't find anything that looked like it applied to the pedometer. I'm testing this on a Lumia 950. UPDATE: I just tried calling the API to get the default pedometer sensor: Pedometer p = await Pedometer.GetDefaultAsync(); It turns out that this triggers an access denied exception with the same worthless stack. I'm currently doing more research to see if there is something that needs to be specified in the manifest.
After further experimenting got me an access denied error, I looked into the manifest more. The manifest Microsoft example project for the pedometer declares a device property that I can't find a way to add through the designer view. Adding it to the code worked perfectly. It's saying I've taken 300,000 steps in the last hour, but I'm sure some simple debugging will find the answer there. (The property is called CumulativeSteps, so that's a good hint...) <Capabilities> <DeviceCapability Name="activity" /> </Capabilities>
var currentReadings = await Pedometer.GetSystemHistoryAsync(DateTime.Today); var walklist = new List<PedometerReading>(); var runlist = new List<PedometerReading>(); foreach (var cuurentreading in currentReadings) { if (cuurentreading.StepKind == PedometerStepKind.Walking) { walklist.Add(cuurentreading); } if (cuurentreading.StepKind == PedometerStepKind.Running) { runlist.Add(cuurentreading); } } var item = walklist.Last(); var item1 = walklist.First(); var item2 = runlist.Last(); var item3 = runlist.First(); Steps1.Value += (item.CumulativeSteps - item1.CumulativeSteps); Steps1.Value += (item2.CumulativeSteps - item3.CumulativeSteps);