BluetoothLEAdvertisementWatcher not returning Service data UUIDs - bluetooth-lowenergy

I am writing a UWP application, I am using the BluetoothLEAdvertisementWatcher method to capture advertising from BLE devices around. This all works fine and I can build a list of devices by capturing the BluetoothLEAdvertisementReceivedEventArgs..... like below
private async void LockerAdv_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
ServiceUuidsFound += args.Advertisement.ServiceUuids.Count;
Adverts.Add(args);
However, I want to capture the ServiceData UUIDs carried in the advertising data (in our case 0x180f for the battery service data and 0xb991 for our own service data).
If I capture the advertising and examine the Advertisement.ServiceUuids.Count as shown above the count is always zero even though I know there are two ServiceData UUIDs present and Apps like the Nordic nRF app finds them and displays them.
Also, if I use the debugger to stop execution and examine the Advertisement.ServiceUuids then they appear not to have been captured and are certainly not accessible as can be seen below:
Link to screenshot.
I have tried using
ScanningMode = BluetoothLEScanningMode.Active;
and
ScanningMode = BluetoothLEScanningMode.Passive;
and it makes no difference.
Ultimately what I want is to be able to extract the ServiceData from the advertising data as it contains useful data for our application but if Windows won't even report the existence of the UUIDs then I am certain I can't get the data associated with it!!
So, what I need to know is it me doing something wrong? is it a limitation of Windows 10 (I am using the very latest version)? or is it perhaps an issue with the Dell Optiflex I am using?
Any help would be gratefully received

You are doing noting wrong. The debugger and watch just don't let you dig down deeper and show no native view.
Put the items you need in a list first and after that you can find out if the lists contain the items and even other collections with more items.
below is an example that shows you how. I think it does not cover all items, thats up to you:
private async void OnAdvertisementReceivedAsync(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
//we have to stop the watcher to get the data from one advertising device only.
var device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
if (device != null)
/* Check all advertisement items for null!
* Not all of them are present!
* Null check is not done in this example!*/
{
var TimeStamp = eventArgs.Timestamp.DateTime;
var LocalName = eventArgs.Advertisement.LocalName;
var Name = device.Name;
var BleAdress = eventArgs.BluetoothAddress;//ulong
var Rssi = eventArgs.RawSignalStrengthInDBm.ToString();
var ConnectionStatus = device.ConnectionStatus;
var Access = device.DeviceAccessInformation.CurrentStatus;
/* Shows advertising flags:
LimitedDiscoverableMode = 1,
GeneralDiscoverableMode = 2,
ClassicNotSupported = 4,
DualModeControllerCapable = 8,
DualModeHostCapable = 16.
*/
var flags = eventArgs.Advertisement.Flags.ToString();
var AdvNumberOfDataSections = eventArgs.Advertisement.DataSections.Count;
/*AdvDataSections contains the advertisement data */
List<BluetoothLEAdvertisementDataSection> AdvDataSections = new List<BluetoothLEAdvertisementDataSection>();
foreach (var item in eventArgs.Advertisement.DataSections)
{
AdvDataSections.Add(item);
}
List<BluetoothLEManufacturerData> AdvManufacturerData = new List<BluetoothLEManufacturerData>();
foreach (var item in eventArgs.Advertisement.ManufacturerData)
{
AdvManufacturerData.Add(item);
}
List<GattDeviceService> ServicesList = new List<GattDeviceService>();
var services = await device.GetGattServicesAsync(BluetoothCacheMode.Uncached);
if (services != null)
{
foreach (var item in services.Services)
{
ServicesList.Add(item);
}
}
}
/* Start the watcher again to get other devices or missing services or data */
}

Related

Confluent Batch Consumer. Consumer not working if Time out is specified

I am trying to consume a max of 1000 messages from kafka at a time. (I am doing this because i need to batch insert into MSSQL.) I was under the impression that kafka keeps an internal queue which fetches messages from the brokers and when i use the consumer.consume() method it just checks if there are any messages in the internal queue and returns if it finds something. otherwise it just blocks until the internal queue is updated or until timeout.
I tried to use the solution suggested here: https://github.com/confluentinc/confluent-kafka-dotnet/issues/1164#issuecomment-610308425
but when i specify TimeSpan.Zero (or any other timespan up to 1000ms) the consumer never consumes any messages. but if i remove the timeout it does consume messages but then i am unable to exit the loop if there are no more messages left to be read.
I also saw an other question on stackoverflow which suggested to read the offset of the last message sent to kafka and then read messages until i reach that offset and then break from the loop. but currently i only have one consumer and 6 partitions for a topic. I haven't tried it yet but i think managing offsets for each of the partition might make the code messy.
Can someone please tell me what to do?
static List<RealTime> getBatch()
{
var config = new ConsumerConfig
{
BootstrapServers = ConfigurationManager.AppSettings["BootstrapServers"],
GroupId = ConfigurationManager.AppSettings["ConsumerGroupID"],
AutoOffsetReset = AutoOffsetReset.Earliest,
};
List<RealTime> results = new List<RealTime>();
List<string> malformedJson = new List<string>();
using (var consumer = new ConsumerBuilder<Ignore, string>(config).Build())
{
consumer.Subscribe("RealTimeTopic");
int count = 0;
while (count < batchSize)
{
var consumerResult = consumer.Consume(1000);
if (consumerResult?.Message is null)
{
break;
}
Console.WriteLine("read");
try
{
RealTime item = JsonSerializer.Deserialize<RealTime>(consumerResult.Message.Value);
results.Add(item);
count += 1;
}
catch(Exception e)
{
Console.WriteLine("malformed");
malformedJson.Add(consumerResult.Message.Value);
}
}
consumer.Close();
};
Console.WriteLine(malformedJson.Count);
return results;
}
I found a workaround.
For some reason the consumer first needs to be called without a timeout. That means it will wait for a message until it gets at least one. after that using consume with timeout zero fetches all the rest of the messages one by one from the internal queue. this seems to work out for the best.
I had a similar problem, updating the Confluent.Kafka and lidrdkafka libraries from version 1.8.2 to 2.0.2 helped

How to correlate two AppInsights resources that communicate through NServiceBus?

Currently, I have dozens of .NET services hosted on various machines that show up as Resources on my AppInsights Application Map, which also shows their dependencies with respect to each other, based on the HTTP requests they make.
However, the relationships between services that communicate through NServiceBus (RabbitMQ) are not shown. Now, I am able to show the messages that are either sent or handled by a service via calls to TelemetryClient.TrackXXX(), but not connect Resources on the map using this information.
I have even gone so far as to attach the parent operation ID from the NSB message sender to the message itself, and assign it to the telemetry object in the receiver, but there is still no line drawn between the services in the Application Map.
To reiterate, this is what I'm getting in the Application Map:
(NSB Message Sender) --> (Message sent/handled)
And this is what I want:
(NSB Sender) --> (Receiver)
The services in question are .NET Core 3.1.
I cannot provide the code, as this is for my work, but any help would be greatly appreciated. I've searched everywhere, and even sources that seemed like they would help, didn't.
(not signed in, posting from work)
Alright, I finally got it. My approach to correlate AppInsights resources using their NSB communication is to mimic HTTP telemetry correlation.
Below is an extension method I wrote for AppInsights' TelemetryClient. I made a subclass named RbmqMessage:NServiceBus.IMessage, given my applications use RBMQ, and gave it the following properties for the sake of correlation (all set in the service that sends the message) :
parentId: equal to DependencyTelemetry.Id
opId: value is the same in the sender's DependencyTelemetry and the receiver's RequestTelemetry. Equal to telemetry.context.operation.id
startTime: DateTime.Now was good enough for my purposes
The code in the service that sends the NSB message:
public static RbmqMessage TrackRbmq(this TelemetryClient client, RbmqMessage message)
{
var msg = message;
// I ran into some issues with Reflection
var classNameIdx = message.ToString().LastIndexOf('.') + 1;
var messageClassName = message.ToString().Substring(classNameIdx);
var telemetry = new DependencyTelemetry
{
Type = "RabbitMQ",
Data = "SEND "+messageClassName,
Name = "SEND "+messageClassName,
Timestamp = DateTime.Now,
Target = "RECEIVE "+messageClassName //matches name in the service receiving this message
};
client.TrackDependency(telemetry);
msg.parentId = telemetry.Id;
msg.opId = telemetry.Context.Operation.Id; //this wont have a value until TrackDependency is called
msg.startTime = telemetry.Timestamp;
return msg;
}
The code where you send the NSB message:
var msg = new MyMessage(); //make your existing messages inherit RbmqMessage
var correlatedMessage = _telemetryClient.TrackRbmq(msg);
MessageSession.Publish(correlatedMessage); //or however the NSB message goes out in your application
The extension method in the NServiceBus message-receiving service:
public static void TrackRbmq(this TelemetryClient client, RbmqMessage message)
{
var classnameIdx = message.ToString().LastIndexOf('.')+1;
var telemetry = new RequestTelemetry
{
Timestamp = DateTime.Now,
Name = "RECEIVE "+message.ToString().Substring(classNameIdx)
};
telemetry.Context.Operation.ParentId = message.parentId;
telemetry.Context.Operation.Id = message.opId;
telemetry.Duration = message.startTime - telemetry.Timestamp;
client.TrackRequest(telemetry);
}
And finally, just track and send the message:
var msg = new MyMessage();
_telemetryClient.TrackRbmq(msg);
MessagePipeline.Send(msg); //or however its sent in your app
I hope this saves someone the trouble I went through.

Is this a bad structure for a proto file

Have run into huge difficulties while trying to make a gRPC app with mulitple services and have been unable to find the cause of my issues. Starting to think it may be in the structure of the proto code.
message Room {
enum Location {
Unknown = 0;
Hallway = 1;
MaleWC = 2;
FemaleWC = 3;
Office = 4;
Kitchen = 5;
ConferenceRoom = 6;
}
Location room = 1;
int32 capacity = 2;
int32 population = 3;
bool light = 4;
bool lock = 5;
}
service lightandtempcontrol {
// create a name for the rpc first -> then specify type of message to send to server
// to turn a light on upon somebody entering a room
rpc LightsOn(targetLight) returns (emptyMessage) {}; // Unary*
// to turn a light off upon someone entering the room
rpc LightsOff(targetLight) returns (lightReceipt) {};
//to regulate temperature dependent on the temperature outside
rpc OutsideTemp(stream outTemp) returns (stream indoorTemp){}; // Bidirectional*
//to get a complete
rpc Usage(usageRequest) returns (stream lightUsage) {}; // Server streaming example
}
Basically, I am trying to create a Room class that I can use with multiple services, getting and setting fields across those services but everytime I try to base code off of one of these I am getting undesired results, mostly because the values I want to change or compare are not working at all. Is the issue in the structure of my proto. is it possible to use this Room message inside other services outside of lightandtempcontrol?

How to get the Guids and mobilephone from a Party List?

I'm making a windows service that triggers on the create message of a custom activity SMS. These program will send the actual sms using a third party sms service provider.
Therefore I need to get the mobilephone numbers for every contact/lead/user/account in the "To" field of the SMS activity. This is a field of type: Party List.
In addition I have another field ("new_msisdn") which I use it if "to" field be empty.(In this field user will type phone numbers directly)
I'm currently using the following code:
EntityCollection results = CrmService.RetrieveMultiple(query);
string msisdn;
string newmessage;
Entity entity;
int encode;
bool flash;
res = new Message[results.Entities.Count];
if (results != null && results.Entities.Count > 0)
{
try
{
for (int i = 0; i < results.Entities.Count; i++)
{
entity = results.Entities[i];
msisdn = (string)entity["new_msisdn"];
// I have to add an condition here to check if "to" is not empty , then get mobilephones.
newmessage = (string)entity["new_message"];
encode = ((OptionSetValue)entity["new_messagetype"]).Value;
flash = (bool)entity["new_flashsms"];
res[i] = new Message();
res[i].crmId = entity.Id;
res[i].senderNumber = msisdn;
res[i].sendDate = DateTime.Now;
res[i].message = newmessage;
if (encode == 1)
res[i].encoding = 1;
else
res[i].encoding = 2;
if (flash)
res[i].flash = 2;
else res[i].flash = 1;
}
}
I have no ideas to do this. By the way, I use CRM 2015.
Try to use something like below.
if(entity.Attributes.Contains("to"))
{
EntityCollection to=(EntityCollection)entitiy["to"];
foreach(Entity toEntity in to.Entities)
{
//You will get each to field record here.
//Use that information to get the mobile numbers of respective users.
Guid Id=toEntity.Id;
//Below code mostly will return string.empty.
//You may have to query CRM to get mobile number for respective contacts.
string mobileNumber=toEntity.Attributes.Contains("mobilenumber")?toEntity["mobilenumber"].ToString():string.Empty;
}
}
Hope I have addressed your query. Please let us know if you have any further questions on the same.
Also its a best practice to check whether attribute is already available in the entity object or not before using a particular attribute.

Oracle query fired off, then never returns

I have this problem in my ASP.NET application where I'm seeing some of my Oracle queries fired off to the server then not returning. Ever. It happens in several places in my app and I can't explain it. Here's one specific scenario where I'm seeing this behavior:
During application start-up I am pre-fetching data asynchronously into the application state (the choice was made to use app state instead of cache b/c the data never changes during the lifetime of the app).
Action<string, object> AddApplicationState = (string name, object data) =>
{
Application.Lock();
Application.Add(name, data);
Application.UnLock();
};
Func<DataTable> GetFullNames = () => Database.GetAllNames();
Func<DataTable> GetProvinceNames = () => Database.GetProvinceNames();
Func<DataTable> GetTribeNames = () => Database.GetTribeNames();
GetFullNames.BeginInvoke(result => AddApplicationState("AllNames", GetFullNames.EndInvoke(result)), null);
GetProvinceNames.BeginInvoke(result => AddApplicationState("ProvinceNames", GetProvinceNames.EndInvoke(result)), null);
GetTribeNames.BeginInvoke(result => AddApplicationState("TribeNames", GetTribeNames.EndInvoke(result)), null);
The second two return just fine, but the first either never returns or returns after about 10 minutes. After firing up Oracle SQL Developer I go to the 'monitor sessions' tool and can see a single session for the query. It looks like it has completed, b/c the wait time is (null) and the session is inactive. Here's the ADO.NET code used to query the database:
public static DataTable GetAllNames()
{
using (OracleConnection oraconn = GetConnection())
{
using (OracleCommand oracmd = GetCommand(oraconn))
{
var sql = new StringBuilder();
sql.AppendLine("SELECT NAME_ID, NATIVE_NAME, NVL(FREQUENCY,0) \"FREQUENCY\", CULTURE_ID,");
sql.AppendLine("ENGLISH_NAME, REGEXP_REPLACE(ENGLISH_NAME, '[^A-Za-z]', null) \"ENGLISH_NAME_STRIPPED\"");
sql.AppendLine("FROM NAMES");
oracmd.CommandText = sql.ToString();
var orada = new OracleDataAdapter(oracmd);
var dtAllNames = new DataTable();
orada.Fill(dtAllNames);
return dtAllNames;
}
}
}
public static DataTable GetTribeNames()
{
using (OracleConnection oraconn = GetConnection())
{
using (OracleCommand oracmd = GetCommand(oraconn))
{
var sql = new StringBuilder();
sql.AppendLine("SELECT DISTINCT NAME_ID, English_Name \"TRIBE_NAME_ENGLISH\",");
sql.AppendLine("REGEXP_REPLACE(English_Name, '[^A-Za-z]',null) \"TRIBE_ENGLISH_NAME_STRIPPED\",");
sql.AppendLine("NATIVE_NAME \"TRIBE_NATIVE_NAME\"");
sql.AppendLine("FROM NAMES");
sql.AppendLine("WHERE NAME_ID IN ");
sql.AppendLine("(SELECT NAME_ID_TRIBE FROM TRIBES UNION SELECT NAME_ID_FAMILY FROM TRIBES)");
sql.AppendLine("ORDER BY English_Name");
oracmd.CommandText = sql.ToString();
var orada = new OracleDataAdapter(oracmd);
var dt = new DataTable();
orada.Fill(dt);
return dt;
}
}
}
public static DataTable GetProvinceNames()
{
using (OracleConnection oraconn = GetConnection())
{
using (OracleCommand oracmd = GetCommand(oraconn))
{
oracmd.CommandText = "SELECT DISTINCT PROVINCE_ID, PROVINCE_NAME_NATIVE, PROVINCE_NAME_ENGLISH FROM PROVINCES";
var orada = new OracleDataAdapter(oracmd);
var dtRC = new DataTable();
orada.Fill(dtRC);
return dtRC;
}
}
}
As you can see, the ADO.NET code is pretty standard (and boring!) stuff. When run in SQL Developer, the queries return less than a second. The first query returns x rows, the second x rows, and the third x rows. But this problem of queries being fired off then never returning happens often and I can't seem to track down the issue. Anyone have any thoughts?
And finally, since I realize it could be something completely unrelated to code, I am running the app locally (from Visual Studio) on a Windows XP SP3 machine and connecting via VPN to a remote Oracle 10g Enterprise instance running on Windows 2003 Server. Locally, I have installed Oracle Data Access Components v11.1.0.6.20.
Thanks!
Are you watching your output window for any exceptions? I don't see any catch blocks in your code.
Oracle's ODP.net has almost exactly the same syntax as ADO, but performs better in many situations. If you're only using Oracle, it might be worth a look.
Is there a reason to use StringBuilder? A single string variable will perform better and makes code easier to read.
It seems that the queries were actually returning, just taking a very long time due to poor query performance, low bandwidth, and the enormous amount of rows being returned. The VS debugger seems to give up after a few seconds for these long-running queries. However, if I let it sit for a few minutes my breakpoints would get hit and things would work as expected.
Thanks for the replies / comments!

Resources