Get CPU usage IOS Swift - ios

I am trying to get overall CPU usage not of a single app. I found some of the resources but they are either written in C or outdated swift. Can anyone help me with this problem? I am trying to conver this https://github.com/beltex/SystemKit/blob/master/SystemKit/System.swift#L12
to swift.
Till now I am able to convert this much
fileprivate func hostCPULoadInfo() -> host_cpu_load_info{
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride;
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT);
var hostInfo = host_cpu_load_info_t.allocate(capacity: 1);
let result = withUnsafeMutablePointer(to: &hostInfo) {$0.withMemoryRebound(to: integer_t.self, capacity: Int(size)){
host_info(mach_host_self(), Int32(HOST_BASIC_INFO), $0, &size)
}
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
#if DEBUG
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)");
}
#endif
return data;
}
public func cpuUsage() -> (system: Double, user: Double, idle : Double, nice: Double){
let load = hostCPULoadInfo();
let usrDiff: Double = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0);
let systDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1);
let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2);
let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3);
let totalTicks = usrDiff + systDiff + idleDiff + niceDiff
print("Total ticks is ", totalTicks);
let sys = systDiff / totalTicks * 100.0
let usr = usrDiff / totalTicks * 100.0
let idle = idleDiff / totalTicks * 100.0
let nice = niceDiff / totalTicks * 100.0
return (sys, usr, idle, nice);
}
But the thing is I am getting an error like this
Error - /Users/administrator/Downloads/Documents/Swift/SystemInfo/RAMInformation.swift: hostCPULoadInfo() - kern_result_t = 5
Does anybody knows what's wrong in the above code? I thing I am doing wrong on conversion of host_statistics.
Can anybody help me?

There are three errors in your code:
The CPU statistics is obtained by calling host_statistics(), not
host_info().
The "flavor" argument must be HOST_CPU_LOAD_INFO, not HOST_BASIC_INFO.
hostInfo contains the pointer to the allocated structure,
so that value must be rebound, not the address of the variable.
Putting it all together:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
let hostInfo = host_cpu_load_info_t.allocate(capacity: 1)
let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
return data
}
(I changed the return type to an optional so that nil can be returned
in the error case).
Alternatively, use a local variable instead of allocating and releasing
the host_cpu_load_info structure:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride/MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
var cpuLoadInfo = host_cpu_load_info()
let result = withUnsafeMutablePointer(to: &cpuLoadInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
return cpuLoadInfo
}

Related

Unwrapping optional value (returned by data.withUnsafeBytes(_:)) sometimes does not work with guard let

I have issue with guard let statement, which behaves strange. Whole code is below. Else block of statement guard let data = readData, let size = sizeOfData else ... in method readActivity(subdata: Data) is wrongly executed even thoug readData and sizeOfData are not nil.
Code
import Foundation
enum ActivityDataReaderError: Error {
case activityIsReadingOtherCentral
case bluetooth(Error?)
case staleData
}
protocol ActivityDataReaderDelegate: class {
func didReadActivity(data: Data)
func didFailToReadActivity(error: ActivityDataReaderError)
}
final class ActivityDataReader {
private var sizeOfData: Int?
private var isOtherDeviceReading: Bool {
// 0xFFFF
return sizeOfData == 65535
}
private var readData: Data?
var isEmpty: Bool {
return sizeOfData == nil
}
weak var delegate: ActivityDataReaderDelegate?
static func timestampValue(_ timestamp: UInt32) -> Data {
var value = timestamp
return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
}
func reset() {
readData = nil
sizeOfData = nil
NSLog("reset() -- \(Thread.current)")
}
func readActivity(data: Data?, error: Error? = nil) {
guard let data = data else {
delegate?.didFailToReadActivity(error: .bluetooth(error))
return
}
let isFirstChunk = readData == nil
if isFirstChunk {
let sizeData = data.subdata(in: 0..<2)
sizeOfData = sizeData.withUnsafeBytes { $0.pointee }
guard !isOtherDeviceReading else {
delegate?.didFailToReadActivity(error: .activityIsReadingOtherCentral)
return
}
NSLog(String("readActivity() Size of data: \(String(describing: sizeOfData))"))
let subdata = data.subdata(in: 2..<data.count)
readActivity(subdata: subdata)
} else {
readActivity(subdata: data)
}
}
private func readActivity(subdata: Data) {
if let lastReadData = readData {
readData = lastReadData + subdata
} else {
readData = subdata
}
guard let data = readData, let size = sizeOfData else {
NSLog("WTF? data:\(String(describing: readData)), "
+ "sizeOfData: \(String(describing: sizeOfData)), "
+ "thread: \(Thread.current)")
assertionFailure("WTF")
return
}
NSLog("subdata: \(String(describing: subdata)), "
+ "totalReadBytes: \(data.count), "
+ "size: \(size)")
if data.count == size {
delegate?.didReadActivity(data: data)
reset()
}
}
}
Test
Test which sometimes passes and sometimes crashes because of assertionFailure("WTF").
class ActivityDataServiceReaderTests: XCTestCase {
var service: ActivityDataReader?
override func setUp() {
super.setUp()
service = ActivityDataReader()
}
override func tearDown() {
service = nil
super.tearDown()
}
func testBufferIsNotEmpty() {
NSLog("testBufferIsNotEmpty thread: \(Thread.current)")
guard let service = service else { fatalError() }
let firstDataBytes = [UInt8.min]
let data1 = Data(bytes: [7, 0] + firstDataBytes)
service.readActivity(data: data1)
XCTAssertFalse(service.isEmpty)
service.reset()
XCTAssertTrue(service.isEmpty)
}
}
Log of console in case of crash
2018-10-25 14:53:30.033573+0200 GuardBug[84042:11188210] WTF? data:Optional(1 bytes), sizeOfData: Optional(7), thread: <NSThread: 0x600003399d00>{number = 1, name = main}
Environment
Xcode10
swift 4.1 with legacy build system
swift 4.2
In my opinion, there is no possible way to execute code in else block in guard let else block of method readActivity(subdata: Data). Everything is running on main thread. Am I misssing something? How is possible sometimes test passes and sometimes crasshes?
Thank you for any help.
Edit:
More narrow problem of guard let + data.withUnsafeBytes:
func testGuardLet() {
let data = Data(bytes: [7, 0, UInt8.min])
let sizeData = data.subdata(in: 0 ..< 2)
let size: Int? = sizeData.withUnsafeBytes { $0.pointee }
guard let unwrappedSize = size else {
NSLog("failure: \(size)")
XCTFail()
return
}
NSLog("success: \(unwrappedSize)")
}
Log:
2018-10-25 16:32:19.497540+0200 GuardBug[90576:11351167] failure: Optional(7)
Thanks to help at: https://forums.swift.org/t/unwrapping-value-with-guard-let-sometimes-does-not-work-with-result-from-data-withunsafebytes-0-pointee/17357 problem was with the line:
let size: Int? = sizeData.withUnsafeBytes { $0.pointee }
Where read data was downcasted to Optional Int (8 bytes long) but sizeData it self was just 2 bytes long. I have no idea how is possible it sometimes worked but solution -- which seems to work properly -- is to use method withUnsafeBytes in fallowing way:
let size = sizeData.withUnsafeBytes { (pointer: UnsafePointer<UInt16>) in pointer.pointee }
Returned value is not optional and has the proper type UInt16 (2 bytes long).
If you check Documentation, there is a warning:
Warning The byte pointer argument should not be stored and used
outside of the lifetime of the call to the closure.
Seems like You should deal with the size inside the closure body
func testGuardLet() {
let data = Data(bytes: [7, 0, UInt8.min])
var sizeData = data.subdata(in: 0 ..< 2)
withUnsafeBytes(of: &sizeData) { bytes in
print(bytes.count)
for byte in bytes {
print(byte)
}
}
let bytes = withUnsafeBytes(of: &sizeData) { bytes in
return bytes // BUGS ☠️☠️☠️
}
}

iOS - Check if mask ip is in valid(in range of the ip)

So i am trying to figure out how to validate the mask ip(in range?) according to the ip.
I cant seem to find the tools in swift as in java :
How can I detect if an IP is in a network?
let ip = "192.168.2.0"
let net = "192.168.1.0"
let pref = 24
func convertIpToInt(_ ipAddress: String) -> Int? {
var result = 0.0
let ipAddressArray = ipAddress.components(separatedBy: ".").compactMap {
Double($0) }
guard ipAddressArray.count == 4 else { return nil }
for (index, element) in ipAddressArray.enumerated() {
result += element * pow(256, Double(3 - index))
}
return Int(result) > 0 ? Int(result) : nil
}
let ipInt = convertIpToInt(ip)
let netInt = convertIpToInt(net)
let brkstInt = netInt! + Int(pow(2, Double(32-pref))) - 1
print(ipInt! >= netInt! && ipInt! <= brkstInt) // false

How to convert data into little endian format?

var val = 1240;
convert into little endian formate swift 3
Ex: 1500 (0x5DC) to 0xDC050000
let value = UInt16(bigEndian: 1500)
print(String(format:"%04X", value.bigEndian)) //05DC
print(String(format:"%04X", value.littleEndian)) //DC05
Make sure you are actually using the bigEndian initializer.
With 32-bit integers:
let value = UInt32(bigEndian: 1500)
print(String(format:"%08X", value.bigEndian)) //000005DC
print(String(format:"%08X", value.littleEndian)) //DC050000
If you want 1500 as an array of bytes in little-endian order:
var value = UInt32(littleEndian: 1500)
let array = withUnsafeBytes(of: &value) { Array($0) }
If you want that as a Data:
let data = Data(array)
Or, if you really wanted that as a hex string:
let string = array.map { String(format: "%02x", $0) }.joined()
let timeDevide = self.setmiliSecond/100
var newTime = UInt32(littleEndian: timeDevide)
let arrayTime = withUnsafeBytes(of: &newTime)
{Array($0)}
let timeDelayValue = [0x0B] + arrayTime
You can do something like
//: Playground - noun: a place where people can play
import UIKit
extension String {
func hexadecimal() -> Data? {
var data = Data(capacity: count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, range: NSRange(location: 0, length: utf16.count)) { match, _, _ in
let byteString = (self as NSString).substring(with: match!.range)
var num = UInt8(byteString, radix: 16)!
data.append(&num, count: 1)
}
guard !data.isEmpty else { return nil }
return data
}
}
func convertInputValue<T: FixedWidthInteger>(_ inputValue: Data) -> T where T: CVarArg {
let stride = MemoryLayout<T>.stride
assert(inputValue.count % (stride / 2) == 0, "invalid pack size")
let fwInt = T.init(littleEndian: inputValue.withUnsafeBytes { $0.pointee })
let valuefwInt = String(format: "%0\(stride)x", fwInt).capitalized
print(valuefwInt)
return fwInt
}
var inputString = "479F"
var inputValue: Data! = inputString.hexadecimal()
let val: UInt16 = convertInputValue(inputValue) //9F47
inputString = "479F8253"
inputValue = inputString.hexadecimal()
let val2: UInt32 = convertInputValue(inputValue) //53829F47

Swift 3 - FTP Upload

I have added the Rebekka touch framework to my Swift 3 project in order to upload files via FTP.
I have used the swift 3 conversion tool in xCode and I'm left with just one error
Value of type 'NSMutableData' has no member 'count'
And here's where it occurs:
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
Full Function:
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advancedBy(offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
Does anybody know the swift 3 equivalent of self.inputData!.count ?
I am using Swift3.
I did the following changes in the source code of Rebekka framework, specifically, the file ResourceListOperation.swift. (Note: advanced(by:..), .length).
fileprivate var inputData: NSMutableData?
var resources: [ResourceItem]?
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.length)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advanced(by: offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
Here is what I used in my application to list the directory after importing RebekkaTouch framework:
var configuration = SessionConfiguration()
configuration.host = "<ip-address:followed-by-port>"
configuration.username = "uname"
configuration.password = "password"
configuration.encoding = String.Encoding.utf8
self.session = Session(configuration: configuration)
self.session.list("/") {
(resources, error) -> Void in
print("List directory with result:\n\(String(describing: resources)), error: \(String(describing: error))\n\n")
}
As suggested in the comments I used .length to get this working, along with some other slight changes as below:
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advancedBy(offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
I then got some errors when tying to use Rebekka touch, the example usage didn't work so I modified slightly as below:
var configuration = SessionConfiguration()
configuration.host = "ftp.somewebsite.co.uk"
configuration.username = "username"
configuration.password = "password"
let URL = filename
let path = "/"+currentJob.ReservationsID+".png"
Session(configuration: configuration).upload(URL, path: path) {
(result, error) -> Void in
print("Upload file with result:\n\(result), error: \(error)\n\n")
}

array element cannot be bridged to Objective-C after migration to Swift 1.2

Yesterday I have switched my IOS Swift project to the new XCode 6.3 and Swift 1.2. I have so far got everything to build nicely, but at one point the app crashes with the error message "fatal error: array element cannot be bridged to Objective-C" at a line that looks like this:
let services = services as! [ServiceObject]
I have read that the error is because I have Objective C objects as members in the Swift Array which is now not automatically bridged to NSArray anymore, so I would have to either make my objects of type ServiceObject non-Obj-C or declare "services" as an NSArray. The strange thing is that ServiceObject is not an Objective-C object. This is the declaration of the class:
class ServiceObject: MonitoringObject {
let serviceDescription: String
let host: HostObject
var duration = 0
var plugin_output = ""
var active_checks_enabled = 0
var display_name = ""
var has_been_checked = 0
var acknowledged = 0
var acknowledgement_type = 0
var scheduled_downtime_depth = 0
var is_flapping = 0
var state = ServiceState.OK
var name: String {
return serviceDescription
}
init(serviceDescription: String, host: HostObject) {
self.host = host
self.serviceDescription = serviceDescription
}
var durationText: String {
if duration == -1 || duration == 0{
return "N/A"
} else if duration > 86400 {
let days = Int(floor(Float(duration) / 86400))
let hours = Int(floor(Float(duration % 86400) / 3600))
return "\(days)d, \(hours)h"
} else if duration > 3600 {
let hours = Int(floor(Float(duration) / 3600))
let minutes = Int(floor(Float(duration) % 3600 / 60))
return "\(hours)h, \(minutes)m"
} else if duration > 60 {
let minutes = Int(floor(Float(duration) / 60))
let seconds = duration % 60
return "\(minutes)m, \(seconds)s"
} else {
return "\(duration)s"
}
}
}
Also, the protocol "MonitoringObject" which ServiceObject conforms to is not Obj-C:
protocol MonitoringObject {
var name: String { get }
}
Does anybody have any clue where the error and the crash come from?
Edit: this is the whole method where the line that fails is contained, to make the context more clear:
private func buildHostServicesIndex(services: [MonitoringObject]) -> [HostServicesEntry] {
//typealias HostServicesEntry = (HostObject, [ServiceObject])
let services = services as! [ServiceObject]
let hosts = services.map {
(service) -> HostObject in
service.host
}
let distinctHosts = Helpers.distinct(hosts)
return distinctHosts.map {
(host) -> HostServicesEntry in
return (host, services.filter {
(service) -> Bool in
service.host == host
})
}
}

Resources