BLE Advertise data size limit - kotlin

On My Addroid app I'm trying to add some extra data when I try to start ble advertising, and as I've read, advertise data must be <= 31 bytes.
That's how I do it:
var testData = "abcdefghij"
var data = AdvertiseData.Builder().apply {
addServiceData(
ParcelUuid(MY_UUID),
testData.toByteArray(Charsets.UTF_8)
)
}
bleAdvertiser.startAdvertising(
settings.build(),
data.build(),
advertiseCallback
)
In this way everything works well. Now if testData fields become
var testData = "abcdefghijk"
advertising starts to fail due to exceeded advertise data size limit.
If a single char occupies 2 bytes, why if I had a string of 11 characters did I exceed the limit of 30 bytes?

Three flag bytes are automatically added first.
A service data packet contains first one byte that tells how long it is, followed by a one byte packet identifier that says that here comes a service data packet. Then you have the payload of the service uuid (16 bytes) followed by your UTF-8-encoded string of 10 bytes.
That sums up to 31 bytes. If you add a 'k' you get 32 bytes and hence the data becomes too long.

Related

What is the unit for SoftLayer_Virtual_Guest:getBandwidthDataByDate

Do you know what is the unit for SoftLayer_Virtual_Guest:getBandwidthDataByDate?
Bit, byte or Octect?
I found some mismatching between the return value from API and portal.
Thanks.
The method that you are using will return an "average: bandwith usage, but the portal uses another method which returns a "sum" value. So the values will not be the same, but they will nearly.
Another thing to point out is that the API does not return bytes/per second, it returns the bytes used by the interface in a peiod of time. what I can see in your result of the api is that period of time is 5 minutes.
so let's convert the data with that information:
646793.0 bytes in 5 minutes
converting to bytes per second (5 minutes = 300 seconds)
646793.0/300 = 2155.976 bytes/second
converting to bits
2155.976 * 8 = 17247.808
converting to kilo bits (note we are not using 1024 )
17247.808 / 1000 = 17.247 KB/s
As I told you the value is closer, but not the same due to the method used if you are looking the exact value you have to use the getSummaryData method. here an example in java Getting bandWidth data in SL
Regards
If I'm not wrong, it is in bytes per second.
Here I added an example for April's question.
Portal Bandwidth Graph
I got the datas by SoftLayer_Virtual_Guest:getBandwidthDataByDate.
getBandwidthDataByDate's output
It showed that 'counter': 646793.0, if the "unit" is bytes per sec, 646793.0Bps*8/1024 != 16.62Kbps

File (.wav) duration while writing PCM data #16KBps

I am writing some silent PCM data on a file #16KBps. This file is of .wav format. For this I have the following code:
#define DEFAULT_BITRATE 16000
long LibGsmManaged:: addSilence ()
{
char silenceBuf[DEFAULT_BITRATE];
if (fout) {
for (int i = 0; i < DEFAULT_BITRATE; i++) {
silenceBuf[i] = '\0';
}
fwrite(silenceBuf, sizeof(silenceBuf), 1, fout);
}
return ftell(fout);
}
Updated:
Here is how I write the header
void LibGsmManaged::write_wave_header( )
{
if(fout) {
fwrite("RIFF", 4, 1, fout);
total_length_pos = ftell(fout);
write_int32(0);
fwrite("WAVE", 4, 1, fout);
fwrite("fmt ",4, 1, fout);
write_int32(16);
write_int16(1);
write_int16(1);
write_int32(8000);
write_int32(16000);
write_int16(2);
write_int16(16);
fwrite("data",4,1,fout);
data_length_pos = ftell(fout);
write_int32(0);
}
else {
std::cout << "File pointer not correctly initialized";
}
}
void LibGsmManaged::write_int32( int value)
{
if(fout) {
fwrite( (const char*)&value, sizeof(value), 1, fout);
}
else {
std::cout << "File pointer not correctly initialized";
}
}
I run this code on my iOS device using NSTimer with interval 1.0 sec. So AFAIK, if I run this for 60 sec, I should get a file.wav that when played should show 60 sec as its duration (again AFAIK). But in actual test it displays almost double duration i.e. 2 min. (approx). I have also tested that when I change the DEFAULT_BITRATE to 8000, then the file duration is almost correct.
I am unable to identify what is going on here. Am I missing something bad here? I hope my code is not wrong.
What you're trying to do (write your own WAV files) should be totally doable. That's the good news. However, I'm a bit confused about your exact parameters and constraints, as are many others in the comments, which is why they have been trying to flesh out the details.
You want to write raw, uncompressed, silent PCM to a WAV file. Okay. How wide does the PCM data need to be? You are creating an array of chars that you are writing to the file. A char is an 8-bit byte. Is that what you want? If so, then you need to use a silent center point of 0x80 (128). 8-bit PCM in WAV files is unsigned, i.e., 0..255, and 128 is silent.
If you intend to store silent 16-bit data, that will be signed data, so the center point (between -32768 and 32767) is 0. Also, it will be stored in little endian byte format. But since it's silence (all 0s), that doesn't matter.
The title of your question indicates (and the first sentence reiterates) that you want to write data at 16 kbps. Are you sure you want raw 16 kbps audio? That's 16 kiloBITs per second, or 16000 bits per second. Depending on whether you are writing 8- or 16-bit PCM samples, that only allows for 2000 or 1000 Hz audio, which is probably not what you want. Did you mean 16 kHz audio? 16 kHz audio translates to 16000 audio samples per second, which more closely aligns with your code. Then again, your code mentions GSM (LibGsmManaged), so maybe you are looking for 16 kbps audio. But I'll assume we're proceeding along the raw PCM route.
Do you know in advance how many seconds of audio you need to write? That makes this process really easy. As you may have noticed, the WAV header needs length information in a few spots. You either write it in advance (if you know the values) or fill it in later (if you are writing an indeterminate amount).
Let's assume you are writing 2 seconds of raw, monophonic, 16000 Hz, 16-bit PCM to a WAV file. The center point is 0x0000.
WAV writing process:
Write 'RIFF'
Write 32-bit file size, which will be 36 (header size - first 8 bytes) + 64000 (see step 12 about that number)
Write 'WAVEfmt ' (with space)
Write 32-bit format header size (16)
Write 16-bit audio format (1 indicating raw PCM audio)
Write 16-bit channel count (1 because it's monophonic)
Write 32-bit sample rate (number of audio sample per second = 16000)
Write 32-bit byte rate (number of bytes per second = 32000)
Write 16-bit block alignment (2 bytes per sample * 1 channel = 2)
Write 16-bit bits per sample (16)
Write 'data'
Write 32-bit length of audio payload data (16000 samples/second * 2 bytes/sample * 2 seconds = 64000 bytes)
Write 64000 bytes, all 0 values
If you need to write a dynamic amount of audio data, leave the length field from steps 2 and 12 as 0, then seek back after you're done writing and fill those in. I'm not convinced that your original code was writing the length fields correctly. Some playback software might ignore those, others might not, so you could have gotten varying results.
Hope that helps! If you know Python, here's another question I answered which describes how to write a WAV file using Python's struct library (I referred to that code fragment a lot while writing the steps above).

How do I limit BitConverter.GetBytes() to return only a certain amount of bytes using VB.NET?

I do:
Dim BytArr() as Byte = BitConverter.GetBytes(1234)
Since, by default, they are 32 bits, it returns 4 byte elements.
I want to be able to control it to return only like two bytes. Maybe only three bytes. Are there any built-in functions to control it?
I don't want to rely on using shifting >> 8 >> 16 >> 24 >> 32, etc..
I also don't want to rely on type casting the data in GetBytes() to a specific datatype.
It is not that GetBytes defaults to 32 bits, it is that GetBytes returns an array of the size required to hold the data type. If you pass a Long then you will get a 8 elements in your array.
The best way to control this is indeed casting the data you pass in. Otherwise you could truncate some of the number.
That being said, you could do something like this:
Dim BytArr() as Byte = Array.Resize(BitConverter.GetBytes(1234), 2)
But if the value you passed in exceeded what could be stored in 2 bytes (in this case) then you will have some very broken code.

How can I write a signed byte to a serial port in VB

I need to be able to write signed bytes to a serial port using
SerialPort.Write() method, except that method only takes byte[] arrays of unsigned bytes, how would i write a signed byte to the serial port?
For what I'm working on the particular command takes values from -1700 to 1700.
thanks
nightmares
The serial communication channel has no concept of signed or unsigned, only a concept of 1's and 0's on the wire. It is your operating system (and ultimately your CPU architecture) that assigns a numeric value to those 1's and 0's, on both the sending and receiving side.
The value range you state cannot be represented in a byte (per my comment and your reply). You need to understand what bit pattern the receiving device expects for a given number (is the other device big endian or little endian?), and then you can send an appropriate sequence of byte[] to represent the number you want to transmit.
If both devices have the same endianness, you can setup an array of short then copy to an array of byte like this:
short[] sdata = new short[] { 1, -1 };
byte[] bdata = new byte[sdata.Length * 2];
Buffer.BlockCopy(sdata, 0, bdata, 0, bdata.Length);
However, be sure and test for a range of values. Especially if you are dealing with embedded devices, numeric encoding may not be exactly as on an Intel PC.

Minecraft Server To Client protocol - 18 byte packet on login request

I'm working with the Minecraft Server To Client protocol documentation for a server I am making.
It says the packet is 18+ bytes, but I can't seem to figure out what each byte is for.
Entity ID = int = 4 bytes
Map Seed = long = 8 bytes
Dimension = byte = 1 byte ?
strings are variables sizes, hence why it says "Total Size: 18 bytes + length of strings"
Sorry I can't be more specific, more detail is needed
It also says that strings are a short (2 byte) length followed by the string.
Understanding what values go in each of those fields is a much more complicated issue, and i doubt anyone here can help with that.