I am a BLE newbie. I am using my Raspberry Pi 3, running Windows 10 Iot Core, to send some advertisement packets.
When sending only the Manufacturer Data, it works perfectly fine. But when I try to send data in Data Section, it gives me the following error.
The data is invalid. Invalid advertisement payload detected
Here is the code
Using only Manufacturer Data
private void StartPublish()
{
string data = "SHASHWAT";
DataWriter writer = new DataWriter();
writer.WriteInt32(data.Length);
writer.WriteString(data);
var adv = new BluetoothLEAdvertisement();
var manufacturerData = new BluetoothLEManufacturerData(
0x0006, writer.DetachBuffer());
adv.ManufacturerData.Add(manufacturerData);
var publisher = new BluetoothLEAdvertisementPublisher(adv);
publisher.Start();
}
Using Data Section along with Manufacturer Data
private void StartPublishWithDataSection()
{
string data = "SHASHWAT";
DataWriter writer = new DataWriter();
writer.WriteInt32(data.Length);
writer.WriteString(data);
var adv = new BluetoothLEAdvertisement();
var manufacturerData = new BluetoothLEManufacturerData(
0x0006, writer.DetachBuffer());
adv.ManufacturerData.Add(manufacturerData);
DataWriter writer2 = new DataWriter();
writer2.WriteString("Hello Shashwat");
var dataSection = new BluetoothLEAdvertisementDataSection();
dataSection.Data = writer2.DetachBuffer();
adv.DataSections.Add(dataSection);
var publisher = new BluetoothLEAdvertisementPublisher(adv);
publisher.Start();
}
This throws invalid data exception.
Please let me know if I am doing something wrong.
Any help would be appreciated.
The reason of this exception is advertisement payload length exceeds the limitation(official state this value is ~20 bytes). You can check here.
Based on my tests, the maximum length of the advertisement payload is 25 bytes including BluetoothLEManufacturerData and BluetoothLEAdvertisementDataSection.
Related
A client has a page which when called starts a long running process and intermittently spits out its progress as it goes
In the format
[dd/MM/yyyy hh:mm:ss] - Process Started
[dd/MM/yyyy hh:mm:ss] - CSV Imported
[dd/MM/yyyy hh:mm:ss] - Process 10% complete
Then 30 seconds later it might write out :
[dd/MM/yyyy hh:mm:ss] - User x Created
[dd/MM/yyyy hh:mm:ss] - User y Created
[dd/MM/yyyy hh:mm:ss] - Process 20% complete
etc... it takes 10-20 minutes to run, we dont have access to the code for this page.
What I have been asked to do is to call this page from one of the other applications, consume the output and give a realtime update on our dashboard.
My first thought was was to use an http client call .GetStreamAsync() and have a loop reading the stream intermittently and reporting back on the last thing that was written out.
This was my first attempt :
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var requestUri = "http://localhost:64501/Page1.aspx";
var stream = httpClient.GetStreamAsync(requestUri).Result;
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
var currentLine = reader.ReadLine();
Thread.Sleep(1000);
}
}
}
However
var currentLine = reader.ReadLine();
Appears to block and wait for the response to complete before returning anything..
I need to be able to read the stream as it comes in.. Is this possible?
The problem lies in ReadLine, the server may be not sending lines (something logic as it seems to be prepared to be sent to a web page where newlines are ignored) so you need to read chuncks of data and convert those to strings:
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var requestUri = "http://localhost:64501/Page1.aspx";
var stream = httpClient.GetStreamAsync(requestUri).Result;
string read = "";
byte[] buffer = new byte[1024];
while(!stream.EndOfStream)
{
int readed = stream.Read(buffer, 0, 1024);
read += Encoding.UTF8.GetString(buffer, 0, readed);
//Do whatever you need to do with the string.
}
}
I'm having problem with the encode of speech input for Amazon Lex.
If i assign InputStream as null, it works, i receive the default voice answer from Lex : "How can i help you"
var amazonLexClient = new AmazonLexClient("APPID", "APPSECRET", Amazon.RegionEndpoint.USEast1);
var amazonPostRequest = new Amazon.Lex.Model.PostContentRequest();
var amazonPostResponse = new Amazon.Lex.Model.PostContentResponse();
amazonPostRequest.BotAlias = "BookTrip";
amazonPostRequest.BotName = "BookTrip";
amazonPostRequest.ContentType = "audio/l16; rate=16000; channels=1";
amazonPostRequest.UserId = "user";
amazonPostRequest.InputStream = null;
amazonPostResponse = await amazonLexClient.PostContentAsync(amazonPostRequest);
If i try to send a recorded voice "How are you" using the encode (required by Lex : 16KHz, 8bits, 1 channel) below
var amazonLexClient = new AmazonLexClient("APPID", "APPSECRET", Amazon.RegionEndpoint.USEast1);
var amazonPostRequest = new Amazon.Lex.Model.PostContentRequest();
var amazonPostResponse = new Amazon.Lex.Model.PostContentResponse();
amazonPostRequest.BotAlias = "BookTrip";
amazonPostRequest.BotName = "BookTrip";
amazonPostRequest.ContentType = "audio/l16; rate=16000; channels=1";
amazonPostRequest.UserId = "user";
amazonPostRequest.InputStream = new MemoryStream();
WaveFormat target = new WaveFormat(16000, 8, 1);
WaveStream streamIn = new WaveFileReader("F:\\Whatever.wav");
WaveFormatConversionStream str = new WaveFormatConversionStream(target, streamIn);
WaveFileWriter.WriteWavFileToStream(amazonPostRequest.InputStream, str);
amazonPostResponse = await amazonLexClient.PostContentAsync(amazonPostRequest);
Then it doesn't work, after about 20~25s Lex server will return null.
Amazon.Runtime.AmazonUnmarshallingException: 'Error unmarshalling response back from AWS.'
NullReferenceException: Object reference not set to an instance of an object.
Can anyone tell me how to encode a wav file to make it work with Amazon Lex?
Btw im using Visual Studio 2017, C# with NAudio library.
Amazon Lex expects the audio to be in PCM or Opus format (read this documentation for more details). You can refer this AI blog post from Amazon to get more information on how to PCM encode your wav audio.
There seems to be some kind of problem inside the AWSSDk for c# - what's happened is that the Lex service has returned a plain-text error message, and the SDK is trying to parse it as JSON. Sometimes you can dig into the exception details and find that raw response, or just use Fiddler.
I am having issues with the attachment in an email. After every few days, user don't find the expected attachment in there email. This seems to be happening for around 10-20 mins and then it corrected itself meaning that the later email will contain the attachments. I am not sure what could be the reason behind this. This is how my code looks like
Model
public class EmailAttachment
{
public string FileName { get; set; }
public byte[] FileContent { get; set; }
}
Code trigger to send an Email
var emailAttachment= new EmailAttachment();
emailAttachment.FileContent = CreatePDFFile();
emailAttachment.FileName = "file.pdf";
EmailGeneratedCertificate(emailAttachment);
Email Preparation Code
public void EmailGeneratedCertificate(EmailAttachment file)
{
//file.FileContent is a byte array
var ms = new MemoryStream(file.FileContent);
ms.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var from = "xx#x.com";
var fromTargetName = "XXX";
var recepient="xx2#x.com"
var subject = "Attachment";
var body="<strong>Please find attachment.</strong>"
var attachment = new Attachment(ms, contentType);
attachment.ContentDisposition.FileName = file.FileName;
var attachments = new List<Attachment>();
attachments.Add(attachment);
_mailService.Send(recepient, null, subject, body, attachments);
}
Another thing I wanted to point out, I have two websites running within a different APP POOL and both have the same email sending code like above and when this issue occur, it seems to be happening on both websites at same time for 10-15 mins and then corrected itself. Please suggest.
In your question you don't write all the code of CreatePDFFile() that IMHO is the cause of the strange behavior so I can only guess from the code you post.
I see 2 main problem:
private byte[] ReadFile(string path): you are swallowing any exception and if there are some it returns an empty byte array so no attachment.
MemoryStream in EmailGeneratedCertificate(EmailAttachment file): you are not disposing the stream and this could case some unexpected behavior
I am working on Passenger information system PIS(Train).So trains send their location to my server PIS using socket on port 8080 .So i should get their locations and show them to passengers . The message that comes from the trains has a template that i should follow that. As you can see here :
So as you can see here we have 6 variables .every integer is 4 byte. The first variable is(4 byte) message source and etc.
In my server i have to detect these variable but i don't know how can i detect them from the message .
static void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client:" + socketForClient.RemoteEndPoint + " now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
while (true)
{
TimeTableRepository objTimeTableRepository = new TimeTableRepository();
SensorRepository objSensorRepository = new SensorRepository();
ArrivalTimeRepository objArrivalTimeRepository=new ArrivalTimeRepository();
TrainRepository objTrainRepository = new TrainRepository();
// OnlineTrainRepository ObjOnlineTrainrepository = new OnlineTrainRepository();
//-----
string theString = streamReader.ReadLine();
}
}
}
Here is my listener to port 8080 and theString is the message that is send by trains.My problem is how can i detect this parameters (Message source,message destination and etc) from theString?I mean i need the value of them to store in database .
best regards
Looks like you don't need to detect anything and definitely should not be slapping this in a string to try and parse.
You already know you are getting a bunch of integers back. You even know what order they are in. Use a BinaryReader to get you your numbers and proceed from there. Once you load your reader up, it should be as simple as calling BinaryReader.ReadInt32() to read the message's numbers one after another.
I must also highly recommend you to look into using statements for your streams.
using (var reader = new BinaryReader(networkStream))
{
var messageSource = reader.ReadInt32();
var messageDestination = reader.ReadInt32();
... and so on ...
}
I have sent data as byte using TcpClient and I wanted to send my own class instead bytes of data.
By bytes of data, what I meant is that I am sending the data converted into bytes like this:
using (MemoryStream bufferStream = new MemoryStream())
{
using (BinaryWriter bufferData = new BinaryWriter(bufferStream))
{
// Simple PONG Action
bufferData.Write((byte)10);
}
_logger.Info("Received PING request, Sending PONG");
return bufferStream.ToArray();
}
And instead I would like to send it like this, without having to declare its size or w/e
public class MyCommunicationData
{
public ActionType Action { get; set; }
public Profile User { get; set; }
...
}
Normally, when I send my data as bytes the first 5 bytes I use to indicate the action and the message size.
But if I migrate to serialize all the data as a single class, do I still need to send what action and size it is or using serialized messages the client and server would know what to read etc or is there a way to do so I can send it without having to specify things out of the serialization object ?
Not sure if this matters here, I am using AsyncCallback to read and write to the network stream:
_networkStream = _client.tcpClient.GetStream();
_callbackRead = new AsyncCallback(_OnReadComplete);
_callbackWrite = new AsyncCallback(_OnWriteComplete);
Let me know if you need me to post any other functions.
If you use a text based serializer(for ex, Json), you can utilize StreamReader's ReadLine and StreamWriter's WriteLine (created from tcpClient.GetStream).
Your code would be something like
writer.WriteLine(JsonConvert.SerializeObject(commData))
and to get the data on the other end
var myobj = JsonConvert.DeserializeObject<MyCommunicationData>(reader.ReadLine())
--EDIT--
//**Server**
Task.Factory.StartNew(() =>
{
var reader = new StreamReader(tcpClient.GetStream());
var writer = new StreamReader(tcpClient.GetStream());
while (true)
{
var myobj = JsonConvert.DeserializeObject<MyCommunicationData>(reader.ReadLine());
//do work with obj
//write response to client
writer.WriteLine(JsonConvert.SerializeObject(commData));
}
},
TaskCreationOptions.LongRunning);