I am interested what can I expect from an iPad mini 4. I send 100 bytes from an iot devie to the ipad every 100 ms (over wifi, local network, tcp), and it works most of the times, but I can notice that like every minutes ones/twice the packages gets congested and some of the packeges I got late, and got together not 100 bytes, but 200 bytes. Or 3 or 400 or even 1200 bytes. And my timeframes skips...
So I do not lose any data/messages, only somehow the ipad gets a few packages later, and the packages add up, and got 2-12 messages together.
I have read the following article, and tried to find the problem.
https://forums.developer.apple.com/thread/45210
I have tried with different types of routers, but the problem exists on all devices.
However it would be great to know what are the IOS/ipad limitations, because I think sending 100 bytes every 100ms it is not a big volume of data.
I have used the code from this post:
https://forums.developer.apple.com/thread/84472
The actual testing code is:
import UIKit
extension Stream {
static func streamsToHost(name hostname: String, port: Int) -> (inputStream: InputStream, outputStream: OutputStream) {
var inStream: InputStream? = nil
var outStream: OutputStream? = nil
Stream.getStreamsToHost(withName: hostname, port: port, inputStream: &inStream, outputStream: &outStream)
return (inStream!, outStream!)
}
}
class ViewController: UIViewController, StreamDelegate {
let expected_package_size = 100
let formatter = DateFormatter()
var Timestamp: Double {
return Date().timeIntervalSince1970 * 1000
}
var last_received: Double = 0
var msg_counter:Int32 = 0
var wrong_counter:Int32 = 0
var sampleTextField2 = UITextField(frame: CGRect(x: 20, y: 150, width: 300, height: 40))
var sampleTextField3 = UITextField(frame: CGRect(x: 20, y: 200, width: 900, height: 40))
override func viewDidLoad() {
super.viewDidLoad()
formatter.dateFormat = "HH:mm:ss.SSS"
streamTest()
sampleTextField2.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(sampleTextField2)
sampleTextField3.borderStyle = UITextField.BorderStyle.roundedRect
self.view.addSubview(sampleTextField3)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let streams = self.streams {
self.stop(streams: streams)
}
}
var streams: (inputStream: InputStream, outputStream: OutputStream)? = nil
var ping = Data()
func streamTest() {
if let streams = self.streams {
print("stream stop")
self.stop(streams: streams)
} else {
print("stream start")
self.start(name: "192.168.1.111", port: 3456, tls: false, ping: "Hello Cruel World!\r\n")
}
}
func pingTest() {
if let streams = self.streams {
print("stream ping")
self.ping(streams: streams)
} else {
print("stream ping while not connected")
}
}
func start(name: String, port: Int, tls: Bool, ping: String) {
self.ping = ping.data(using: .utf8)!
let streams = Stream.streamsToHost(name: name, port: port)
self.streams = streams
if tls {
let success = streams.inputStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
precondition(success)
}
for s in [streams.inputStream, streams.outputStream] {
s.schedule(in: .current, forMode: .default)
s.delegate = self
s.open()
}
}
func ping(streams: (inputStream: InputStream, outputStream: OutputStream)) {
let data = self.ping
let dataCount = data.count
let bytesWritten = data.withUnsafeBytes { (p: UnsafePointer<UInt8>) -> Int in
return streams.outputStream.write(p, maxLength: dataCount)
}
if bytesWritten < 0 {
print("stream write error")
} else if bytesWritten < data.count {
print("stream write short %d / %d", bytesWritten, data.count)
} else {
print("stream task write %@", data as NSData)
}
}
func stop(streams: (inputStream: InputStream, outputStream: OutputStream)) {
for s in [streams.inputStream, streams.outputStream] {
s.delegate = nil
s.close()
}
self.streams = nil
}
func stream(_ thisStream: Stream, handle eventCode: Stream.Event) {
guard let streams = self.streams else { fatalError() }
let streamName = thisStream == streams.inputStream ? " input" : "output"
switch eventCode {
case [.openCompleted]:
print("%@ stream did open", streamName as NSString)
break
case [.hasBytesAvailable]:
var temp: Double = Timestamp
var diff: Double = temp - last_received
if (temp - last_received > 180) {
print("timeframe error: ", Int(diff))
}
last_received = temp
var buffer = [UInt8](repeating: 0, count: 2024)
let bytesRead = streams.inputStream.read(&buffer, maxLength: buffer.count)
if bytesRead > 0 {
msg_counter += 1
if (bytesRead != expected_package_size) {
wrong_counter += 1
print("package size error counter: ", wrong_counter, " length: ", bytesRead, " messages: ", bytesRead / 86)
}
let data = NSData(bytes: &buffer, length: bytesRead)
let str = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue)! as String
// sampleTextField2.text = String(msg_counter)
// sampleTextField3.text = String(wrong_counter)
print(formatter.string(from: Date()), " ", str, " ", bytesRead, " ", msg_counter, "\t",wrong_counter,"\t",Int(diff))
}
case [.hasSpaceAvailable]:
print("%@ stream has space", streamName as NSString)
case [.endEncountered]:
print("%@ stream end", streamName)
self.stop(streams: streams)
case [.errorOccurred]:
let error = thisStream.streamError! as NSError
print("%@ stream error %@ / %d", streamName, error.domain, error.code)
self.stop(streams: streams)
default:
fatalError()
}
}
Thanks for any help!