So i have 2 iOS devices : one is Peripheral and the other Central.
I want that the data would be image.
I have tried with a string value and it is working fine but with image i get this error:"read_user_chunkIDOT:1221: invalid PNG file: no valid iEnd chunk", also i can see that the bytes are different(
Optional(526 bytes)), they are more larger when i get them.
This is the peripheral:
if let img = UIImage(named: "maiden") {
let data = UIImagePNGRepresentation(img)
let base64 = data?.base64EncodedData(options: .lineLength64Characters)
let char = CBMutableCharacteristic(type: CHAR_UUID, properties: [.read], value: base64!, permissions: [.readable])
let myRoei = CBMutableService(type: RX_UUID, primary: true)
myRoei.characteristics = [char]
cameraPeripheralManager.add(myRoei)
cameraPeripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey:[RX_UUID], CBAdvertisementDataLocalNameKey: advertisementData])
}
This is the Central inside didUpdateValueFor characteristic:
print(characteristic.value as Any)
switch characteristic.uuid {
case CHAR_UUID:
let image = UIImage(data: Data(base64Encoded: characteristic.value!, options: .ignoreUnknownCharacters)!)
self.imageView.image = image
_ = bodyLocation(from: characteristic)
case RX_UUID: break
// onHeartRateReceived(bpm)
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
Would like to know where i am wrong.
Thanks in advanced!
So i have managed doing so with this code:
func sendData() {
if sendingEOM {
// send it
let didSend = cameraPeripheralManager?.updateValue(
"EOM".data(using: String.Encoding.utf8)!,
for: char!,
onSubscribedCentrals: nil
)
// Did it send?
if (didSend == true) {
// It did, so mark it as sent
sendingEOM = false
print("Sent: EOM")
}
return
}
// We're not sending an EOM, so we're sending data
// Is there any left to send?
guard sendDataIndex! < (dataToSend?.count)! else {
// No data left. Do nothing
return
}
// There's data left, so send until the callback fails, or we're done.
var didSend = true
while didSend {
// Make the next chunk
// Work out how big it should be
var amountToSend = dataToSend!.count - sendDataIndex!;
// Can't be longer than 20 bytes
if (amountToSend > NOTIFY_MTU) {
amountToSend = NOTIFY_MTU;
}
// Copy out the data we want
let chunk = dataToSend!.withUnsafeBytes{(body: UnsafePointer<UInt8>) in
return Data(
bytes: body + sendDataIndex!,
count: amountToSend
)
}
// Send it
didSend = cameraPeripheralManager!.updateValue(
chunk as Data,
for: char!,
onSubscribedCentrals: nil
)
// If it didn't work, drop out and wait for the callback
if (!didSend) {
return
}
let stringFromData = NSString(
data: chunk as Data,
encoding: String.Encoding.utf8.rawValue
)
print("Sent: \(String(describing: stringFromData))")
// It did send, so update our index
sendDataIndex! += amountToSend;
// Was it the last one?
if (sendDataIndex! >= dataToSend!.count) {
// It was - send an EOM
// Set this so if the send fails, we'll send it next time
sendingEOM = true
// Send it
let eomSent = cameraPeripheralManager!.updateValue(
"EOM".data(using: String.Encoding.utf8)!,
for: char!,
onSubscribedCentrals: nil
)
if (eomSent) {
// It sent, we're all done
sendingEOM = false
print("Sent: EOM")
}
return
}
}
}
The code below is the client side:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print(characteristic.value as Any)
switch characteristic.uuid {
case Constants.CHAR_UUID:
imageView.image = nil
print("Char value: \(String(describing: characteristic.value))")
guard error == nil else {
print("Error discovering services: \(error!.localizedDescription)")
return
}
if let stringFromData = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue){
if (stringFromData.isEqual(to:"EOM")){
countNumberOfImages += 1
imageView.image = UIImage(data: data as Data)
// peripheral.setNotifyValue(false, for: characteristic)
print("Image number: \(countNumberOfImages)")
let end = NSDate() // <<<<<<<<<< end time
print("Total data: \(data.length)")
let start = NSDate() // <<<<<<<<<< Start time
data.setData(NSData() as Data)
//totalData.setData(NSData() as Data)
// centralManager?.cancelPeripheralConnection(peripheral)
} else {
// Otherwise, just add the data on to what we already have
data.append(characteristic.value!)
totalData.append(characteristic.value!)
count += 1
// print("Times: +\(count)")
// Log it
print("Received: \(data.length)")
}
} else {
data.append(characteristic.value!)
totalData.append(characteristic.value!)
count += 1
// print("Times: +\(count)")
// Log it
print("Received: \(data.length)")
}
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
Very useful code that helps you break the data into chunks and deliver the last chunk with a string to notify the central device that the transfer finished.