C++/WinRT BLE device watcher throws an "illegal state change" error when calling Start() - winapi

I'm using MFC/win32 but I couldn't find a good way to work with BLE devices. So while trying to work with C++?WinRT, I created a BluetoothLEAdvertisementWatcher object and checked that it was created. However when I run start, I get the error. I tried to include the Received and Stopped event handlers from the API documentation, but I'm not quite getting the hang of those so I took them out.
void bleConnect(HWND hWnd)
{
auto watcher = BluetoothLEAdvertisementWatcher(); // create BLE advertisement watcher
watcher.ScanningMode(BluetoothLEScanningMode::Active);
wprintf(L"ble watcher status: %ld\n", watcher.Status());
if (watcher.Status() == BluetoothLEAdvertisementWatcherStatus::Created)
{
watcher.Start(); // this causes the error
}
}
The error is impl::error_illegal_state_change = 0x8000000d : An illegal state change was requested. under the winrt/base.h generated file. I'm not sure what that really means. A little bit of searching that error has made me more confused.
I've tried to replicate something like this, but I haven't gotten anything to work.
I've also attempted to declare the bluetooth capability in my appxmanifest.xml however I'm not sure that had any effects on debugging my project. I use MakeAppx in command line to package my project using a custom manifest.xml, so I'm unsure how to include it while debugging.
I feel like I'm missing something. Thanks in advance.
Edit: Here's the full error, I missed this last time somehow. Microsoft C++ exception: winrt::hresult_illegal_method_call at memory location 0x00EFE6D0. Again, this exception is the Start() function, but I'm not sure what else I can do with this information.
I found another post that may or may not be a solution, I'll be looking into it. So far, I've inserted the handlers from that post and still ran into the same error.

To start the BluetoothLEAdvertisementWatcher, make sure that you register both Received() and Stopped() with handlers. The C++/WinRT docs DO NOT mention this, but you need both. Results may vary because I am working with a desktop app using win32/MFC.
Also as the documents mention, the handlers must have the correct arguments to function correctly. See here for details.
In the case of C++/WinRT, the handlers should look like:
void OnAdvertisementRecieved(winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher const& watcher,
winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs const& args)
{
// handle received BLE advertisement
}
void OnAdvertisementStopped(winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher const& watcher,
winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcherStoppedEventArgs const& args)
{
// this is called when watcher is 'Stopped' (not 'Stopping')
}

Related

Is SmtpClient.SendAsync() really faster than SmtpClient.Send()

I was refactoring some of my code into a service and I was going to roll async all the way through down to my EmailService's Send() method.
I was about to replace Send() with SendAsync() and noticed the extra callback parameter.
Well decided to dig in and read about it a little more in depth here:
https://learn.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.sendasync?view=netcore-3.1#definition
I think this would be useful to set up logging to database on an error:
if (e.Error != null)
{
Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
// TODO: Log error to DB
}
e.Cancel would never happen.
The only thing I would be concerned about is logging errors and message sent.
Because the example console program says message sent even though if I have say a port wrong and the message doesn't go through.
The only time it would report the error is for an ArgumentNullException or InvalidOperationException.
So logging message sent could be erroneous.
But there is no way to check for sure if a message goes since it returns void and not a success bool. I guess this is better than putting the Send() in a try/catch which would be more expensive.
One alternative is to setup the callback to an empty SendCompletedCallback() and just have this:
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Do nothing
}
Then we get the benefit of Async non blocking in our emails and have the infrastructure set up for a callback if we ever need it.
But we are not forced to add any funtionality at the moment.
Am I right in thinking this through here.
I think I am going with this approach.
I found the
SendMailAsync()
method works best.
You don't need a callback or a user token.
Easy to implement and non-blocking.

Handling DisplayInformation::DisplayContentsInvalidated in D3D12

In the VS2019 project template for C++/CX D3D12, the DisplayInformation::DisplayContentsInvalidated event (documented here) is subscribed and when this event fires, the code in the project template attempts to validate the D3D12 device. The criteria being used to validate is whether the default adapter has changed:
// This method is called in the event handler for the DisplayContentsInvalidated event.
void DX::DeviceResources::ValidateDevice()
{
// The D3D Device is no longer valid if the default adapter changed since the device
// was created or if the device has been removed.
// First, get the LUID for the default adapter from when the device was created.
DXGI_ADAPTER_DESC previousDesc;
{
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc));
}
// Next, get the information for the current default adapter.
DXGI_ADAPTER_DESC currentDesc;
{
ComPtr<IDXGIFactory4> currentDxgiFactory;
DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&currentDxgiFactory)));
ComPtr<IDXGIAdapter1> currentDefaultAdapter;
DX::ThrowIfFailed(currentDxgiFactory->EnumAdapters1(0, &currentDefaultAdapter));
DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(&currentDesc));
}
// If the adapter LUIDs don't match, or if the device reports that it has been removed,
// a new D3D device must be created.
if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||
previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||
FAILED(m_d3dDevice->GetDeviceRemovedReason()))
{
m_deviceRemoved = true;
}
}
However, it seems to me that the default adapter may not be the elected adapter, as you can see in this code, because it ensures the adapter can create a D3D12 device before electing it, and this same check does not exist in the validation code above:
// This method acquires the first available hardware adapter that supports Direct3D 12.
// If no such adapter can be found, *ppAdapter will be set to nullptr.
void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)
{
ComPtr<IDXGIAdapter1> adapter;
*ppAdapter = nullptr;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter); adapterIndex++)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
{
// Don't select the Basic Render Driver adapter.
continue;
}
// Check to see if the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
break;
}
}
*ppAdapter = adapter.Detach();
}
Is this unintentionally relying on the default adapter being the elected adapter, or are there wider assumptions we can make based on the default adapter having changed?
What is the real meaning if DisplayInformation::DisplayContentsInvalidated? What is this telling me? Why does this suggest the device is possibly invalid? What are the cases where this event fires andthe device would or would not be invalid?
And since we are also checking for a DeviceRemovedReason here, are there cases where the default adapter doesn't change but the device was removed because of DisplayInformation::DisplayContentsInvalidated?
Do we even really need to handle this at all? What would happen if I just completely ignored this event and kept trying to render? Would I not end up handling whatever problem this event firing is indicating in the documented "device lost scenarios" per this document?
We are still investigating your question and get some information.
With regards to when the DisplayContentInvalidated Event will be triggered, it is typically invoked upon various activities including changing of the primary display or if the display configurations have changed in any other way. This would also include if there were certain types of issues occurring with the graphics, which this event should be able to be utilized to handle such situations.
With regards to the template, we ran some tests on our end and we indeed did see that the project uses the first adapter that it finds that can handle DirectX12 rather than an elected adapter. Upon further tests, we removed that particular check and found that the application does indeed continue to run as expected. The adapter may not be the one that was used to create the device at application startup. So indeed, this check does seem like it can potentially be ignored as indicated. However, having this event in the code might not hurt as it can provide the extra functionality should it be required for any situation.
Any other detailed information would likely be found in our documentation regarding this. However, it seems that the template is meant for demonstrating certain functionalities of DirextX12 and its various API’s so ignoring the DisplayContentInvalidated Event should typically not cause any issues.

Allow-listing IP addresses using `call.cancel()` from within `EventListener.dnsEnd()` in OkHttp

i am overriding the dnsEnd() function in EventListener:
#Override
public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
inetAddressList.forEach(address -> {
logger.debug("checking if url ({}) is in allowlist", address.toString());
if (!allowlist.contains(address)) {
call.cancel();
}
});
}
i know, in the documentation it says not to alter call parameters etc:
"All event methods must execute fast, without external locking, cannot throw exceptions, attempt to mutate the event parameters, or be re-entrant back into the client. Any IO - writing to files or network should be done asynchronously."
but, as i don't care about the call if it is trying to get to an address outside the allowlist, i fail to see the issue with this implementation.
I want to know if anyone has experience with this, and why it may be an issue?
I tested this and it seems to work fine.
This is fine and safe. Probably the strangest consequence of this is the canceled event will be triggered by the thread already processing the DNS event.
But cancelling is not the best way to constrain permitted IP addresses to a list. You can instead implement the Dns interface. Your implementation should delegate to Dns.SYSTEM and them filter its results to your allowlist. That way you don't have to worry about races on cancelation.

Is it possible to add additional information for crashes handled by Xamarin.Insights analytics framework

I have an xamarin.android with xamarin.insights intergrated.
Right now every time I handle error manually (try/catch) I'm adding information about environment (staging/production):
try
{
ExceptionThrowingFunction();
}
catch (Exception exception)
{
exception.Data["Environment"] = "staging";
throw;
}
But this information is missing in case if error handled by xamarin.insights itself (in case of crash).
It is possible to add additional exception data in case of crash?
docs reference I used
From reading the docs page reference that you mentioned, I still get the impression that you have to call the .Report method as well as in:-
Insights.Report(exception, new Dictionary <string, string> {
{"Some additional info", "foobar"}
});
What I believe they are saying in this example:-
try {
ExceptionThrowingFunction();
}
catch (Exception exception) {
exception.Data["AccountType"] = "standard";
throw;
}
Is that you have the ability when any Exception is encountered, to package additional information that you can later send to the Insights server, as the Data property of the Exception is just a Key/Value Dictionary.
So if you had an Exception several layers deep, you can choose to re-throw the Exception with additional information contained within it that you will later send to the Insights server.
At a higher level, you can then take the Exception that was thrown deeper down the call-hierarchy and then call the Insights.Report, with:-
Insights.Report(
{the rethrown exception in your higher up try..catch block},
{rethrown exception}.Data
);
that will then send all the additional Key/Value information previously captured.
From seeing your last part of your question though it looks like you are interested in Insights handling and sending this additional .Data automatically should there be an unhandled exception.
If it is not currently being sent, then perhaps suggest to them that this can be sent also? As it sounds a feasible request for this to automatically be sent as well incase of an unhandled exception.
Update 1:-
Yes - I understand about the unhandled exception scenario now that you are referring to.
I have not dealt with this component directly, so there may be hooks / event handlers or something already defined where you can tap into this, and execute some custom code just prior to this being sent.
If this is not available, then perhaps suggest this to them to include as its a Beta product?
Alternatively, you could still achieve this yourself by capturing the unhandled exceptions just prior to them falling. You'd have to code this however on each platform.
For instance on Windows Phone in the App class there is Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) to which you could then supplement the Exception thrown with this extra .Data.
For Android you could take a look at this post that describes how to catch uncaughtException that will help you in capturing the unhandled exceptions.
Whether just supplementing the Exception in these handlers above is enough all depends on how they've written their hook into this, as to how well it behaves and whether it is executed first, prior to their implementation.
You will have to try and see if it does. If it doesn't behave well, allowing you to supplement extra data prior to the automatic call to Insights, you have another fallback solution, to just do the .Report call manually within these unhandled exception handlers yourself to make this work and supplement the extra .Data to achieve your aim.

Boost calling method from outside of class

Let's see how simple of a question I can ask. I have:
void TCPClient::test(const boost::system::error_code& ErrorCode)
{
// Anything can be here
}
and I would like to call it from another class. I have a global boost::thread_group that creates a thread
clientThreadGroup->create_thread(boost::bind(&TCPClient::test,client, /* this is where I need help */));
but am uncertain on how to call test, if this is even the correct way.
As an explanation for the overall project, I am creating a tcp connection between a client and a server and have a method "send" (in another class) that will be called when data needs to be sent. My current goal is to be able to call test (which currently has async_send in it) and send the information through the socket that is already set up when called. However, I am open to other ideas on how to implement and will probably work on creating a consumer/producer model if this proves to be too difficult.
I can use either for this project, but I will later have to implement listen to be able to receive control packets from the server later, so if there is any advice on which method to use, I would greatly appreciate it.
boost::system::error_code err;
clientThreadGroup->create_thread(boost::bind(&TCPClient::test,client, err));
This works for me. I don't know if it will actually have an error if something goes wrong, so if someone wants to correct me there, I would appreciate it (if just for the experience sake).

Resources