How to use Int value with specific byte length - swift

Need an Integer property 3 bytes length.
The main goal is I have structure:
packet {
header: UInt8
parameters: 3 bytes
reserve: UInt16
}
Which have to be converted to Data 6 bytes in total!
Guys pls help how can I achive this?

Related

Looking for a Better Alternative to String Format for MQTT

I am mqtt-ing a string from a Rasbperry Pi(sitting in a field, supported by LTE internet, costing me 10$/500MB/month) to an MQTT broker. I am using paho-mqtt client in python to do this for me. The string looks something like "MM:DD:YYY HH:MM:SS, X1, X2, X3, , , , X24", and I am sending a new string every 30 seconds. X1 to Xn are floating point numbers 0 to 700 with 2 digit precision. I think this will cost me a lot of internet when I deploy it to 24/7 use. Is my data format good? What other data formats should I look at?
You can represent the Unix time with a 4-byte float. And you can represent a float with an IEEE754 float in 4 bytes. So your time and 24 floats can be packed into 100 bytes with Python struct.pack(). That looks like this:
import struct
import time
import random
# Synthesize some sample data - a time and 24 floats 0..700
data = [time.time()] + [ random.uniform(0, 700) for _ in range(24)]
# Pack as 25 IEEE754 floats of 4 bytes each
payload = struct.pack('!25f', *data)
print(len(payload)) # prints 100 (bytes)
Currently, you seem to be using:
19 bytes for your time and
around 7 bytes for each float including separators
So, that's around 180 bytes as you currently have it.
If you multiplied your floats by 100 and made them integer you could maybe encode as 16-bit unsigned values (i.e. half the space of a 4-byte float) which would go from 0..65535 to represent 0..655 which is close to your data range of 0..700. So that would be 4 bytes for the time, plus 24 samples of 2 bytes each, for a total of 52 bytes.
So, rather than 100, use 65535/700 or 93.62:
# Scale the data to the range 0..65535 and make into integers
smallerData = [data[0]] + [ int(93.62*data[i]) for i in range(1,25)]
payload = struct.pack('!f24H', *smallerData)
print(len(payload)) # prints 52 (bytes)
Obviously all the numbers above exclude MQTT protocol overhead.

How to convert byte position in swift

How would I convert this properly? the value I need is byte number 0-1, has a format of uint16 and its units are in degrees.
print("derived : \(characteristic.value!)")
print(String(bytes: characteristic.value!, encoding: .utf16))
derived : 20 bytes
Optional("\0{Ͽ⌜ƀ")
You just need to get the first two bytes of the Data as UInt16.
var result: UInt16 = 0
_ = withUnsafeMutableBytes(of: &result) {characteristic.value!.copyBytes(to: $0, from: 0...1)}
print("\(result) degrees")
Assuming your format of uint16 is in Little-Endian as well as iOS, which is more often found in BLE characteristics.
(When you get the first value in Data, from: 0...1 is not needed, but you may want some data in other position.)

How to convert UInt8 to bytes Swift 4

How do I convert 4 to 0x04 in Swift 4?
var value: UInt8 = 4 // want to input 4
let bytes = NSData(bytes: &value, length: sizeof(UInt8())) // bytes must = 0x04
If "bytes must = 0x04" it sounds like you want a Data with a single byte with a value of 4, right? The code you have written will produce an NSData with an array of bytes that represents the memory address of value.
If you just want a single byte in your data, you can say Data(bytes: [value]).

Difference between Int and Uint8 swift

What are the differences between the data types Int & UInt8 in swift.
Looks like UInt8 is used for binary data, i need to convert UInt8 to Int is this possible.
That U in UInt stands for unsigned int.
It is not just using for binary data. Uint is used for positive numbers only, like natural numbers.
I recommend you to get to know how negative numbers are understood from a computer.
Int8 is an Integer type which can store positive and negative values.
UInt8 is an unsigned integer which can store only positive values.
You can easily convert UInt8 to Int8 but if you want to convert Int8 to UInt8 then make sure value should be positive.
UInt8 is an 8bit store, while Int not hardly defined or defined by the compiler:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
Int could be 32 or 64 bits
Updated for swift:
Operation Output Range Bytes per Element
uint8 0 to 255 1
Int - 9223372036854775808 to 9223372036854775807 2 or 4
If you want to find the max and min range of Int or UInt8:
let maxIntValue = Int.max
let maxUInt8Value = UInt8.max
let minIntValue = Int.min
let minUInt8Value = UInt8.min
If you want to convert UInt8 to Int, used below simple code:
func convertToInt(unsigned: UInt) -> Int {
let signed = (unsigned <= UInt(Int.max)) ?
Int(unsigned) :
Int(unsigned - UInt(Int.max) - 1) + Int.min
return signed
}

Obj-C Read Little Endian From Binary File? (xcode)

I'm looking for a way to get an int value from a binary file. So lets say i have this file "myfile.dat" where from my PC i stored a lot of stuff...
Now i need to read that file from my IPhone and show the data...
on the "myfile.dat" i have this (binary and all ints are little endian):
0-12: A signature string
13-16: An int number (note that length = 4)
So using NSData i know i can read from pos 13 to pos 16 and get those bytes... i can get the first 0-12 string correctly, but i cannot read pos 13-16 and convert it to an int value in Obj-C.... ;(
I have something like:
unsigned char bytes[length];
[_data getBytes:bytes range:NSMakeRange(offset, length)];
int32_t elem = OSReadLittleInt32(bytes, 0);
Now, im a newbie when it comes to Obj-C and C/C++... all my life i have been working with C# (sad)...
Can anyone help? THANKS IN ADVANCE!
Give this a try:
unsigned long bytes;
[_data getBytes: &bytes length: sizeof(unsigned long)];
NSLog(#"%i", NSSwapLittleLongToHost(bytes));