250 lines
14 KiB
Swift
250 lines
14 KiB
Swift
//
|
|
// FrequencyOperation.swift
|
|
// Logger4
|
|
//
|
|
// Created by Kilian Hofmann on 15.06.17.
|
|
// Copyright © 2017 Kilian Hofmann. All rights reserved.
|
|
//
|
|
|
|
import Cocoa
|
|
|
|
class FrequencyOperation: Operation {
|
|
|
|
// DOCSIS 3.0 Upstream Power Limits as per Specification March 5. 2015
|
|
let upstreamOne = ["qpsk": "62.18", "8qam": "58.21", "16qam": "58.21", "32qam": "57", "64qam": "57", "128qam": "-"]
|
|
let upstreamTwo = ["qpsk": "59.18", "8qam": "55.21", "16qam": "55.21", "32qam": "54", "64qam": "54", "128qam": "-"]
|
|
let upstreamThreeOrFour = ["qpsk": "56.18", "8qam": "52.21", "16qam": "52.21", "32qam": "51", "64qam": "51", "128qam": "-"]
|
|
let modulationAdjust: NSDictionary = ["qpsk": "-1.18", "8qam": "-0.21", "16qam": "-0.21", "32qam" : "0", "64qam": "0", "128qam": "0.05"]
|
|
// XML Parser
|
|
let parser: XMLDictionaryParser = XMLDictionaryParser()
|
|
// Data handling
|
|
var downstream: Data?
|
|
var upstream: Data?
|
|
var upstreamBool: Bool = false
|
|
var downstreamBool: Bool = false
|
|
var dir: NSString = ""
|
|
|
|
override init() {
|
|
|
|
}
|
|
|
|
override func main() {
|
|
// Get date for folder structure
|
|
let time : Date = Date()
|
|
let start: Array<String> = (NSApp.delegate as! AppDelegate).justDate.string(from: time).components(separatedBy: ".")
|
|
// File manager
|
|
let fileManager: FileManager = FileManager.default
|
|
// Make all relevant directories if not present
|
|
pthread_mutex_lock(&((NSApp.delegate as! AppDelegate).lock))
|
|
dir = NSString(format: "~/KDLog/%@.docsisplist2/%@/%@/", start[2], start[1], start[0])
|
|
do {
|
|
try fileManager.createDirectory(atPath: dir.expandingTildeInPath, withIntermediateDirectories: true, attributes: nil)
|
|
}
|
|
catch let error as NSError{
|
|
NSLog("ERROR ON SUBDIRECTORY CREATION: \(error.localizedDescription)")
|
|
}
|
|
pthread_mutex_unlock(&((NSApp.delegate as! AppDelegate).lock))
|
|
// URL Requests
|
|
let requestDownstream: URLRequest = URLRequest.init(url: URL.init(string: UserDefaults.standard.string(forKey: "downstream")!)!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 4)
|
|
let requestUpstream: URLRequest = URLRequest.init(url: URL.init(string: UserDefaults.standard.string(forKey: "upstream")!)!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 4)
|
|
// Tasks
|
|
let taskDownstream: URLSessionDataTask = (NSApp.delegate as! AppDelegate).urlSession.dataTask(with: requestDownstream){data, response, error in
|
|
pthread_mutex_lock(&(NSApp.delegate as! AppDelegate).lock)
|
|
self.downstream = data
|
|
self.downstreamBool = true
|
|
self.handleData(date: time)
|
|
pthread_mutex_unlock(&(NSApp.delegate as! AppDelegate).lock)
|
|
}
|
|
|
|
let taskUpstream: URLSessionDataTask = (NSApp.delegate as! AppDelegate).urlSession.dataTask(with: requestUpstream){data, response, error in
|
|
pthread_mutex_lock(&(NSApp.delegate as! AppDelegate).lock)
|
|
self.upstream = data
|
|
self.upstreamBool = true
|
|
self.handleData(date: time)
|
|
pthread_mutex_unlock(&(NSApp.delegate as! AppDelegate).lock)
|
|
}
|
|
// Start
|
|
taskUpstream.resume()
|
|
taskDownstream.resume()
|
|
}
|
|
|
|
func handleData(date: Date) {
|
|
// Both returned successfully
|
|
if upstream != nil && downstream != nil {
|
|
// Parse data
|
|
upstreamBool = false
|
|
downstreamBool = false
|
|
let dictionaryUpstream: Dictionary? = parser.dictionary(with: upstream)
|
|
let dictionaryDownstream: Dictionary? = parser.dictionary(with: downstream)
|
|
upstream = nil
|
|
downstream = nil
|
|
// Tracking padding adding
|
|
var filesModified: [String] = []
|
|
|
|
// Upstream is valid
|
|
if dictionaryUpstream != nil{
|
|
var entry: String = ""
|
|
var file: NSString = ""
|
|
// Grab channels
|
|
let channels: AnyObject = (dictionaryUpstream!["upstream_channel"]) as AnyObject
|
|
// We have multiple channels
|
|
if channels is [Dictionary<String,AnyObject>] {
|
|
// Simplify
|
|
let channels: [Dictionary<String,AnyObject>] = (channels as! [Dictionary<String,AnyObject>])
|
|
// Step through channels
|
|
for index in 0..<channels.count {
|
|
// Grab channel
|
|
let channel: Dictionary<String,AnyObject> = channels[index]
|
|
// We do not have an error
|
|
if channel["upstream_modulation"] != nil && (channel["frequency"] as! String) != "status_error" {
|
|
// Grab power rating in dBmV
|
|
let powerInt: Double? = Double(channel["power_level"] as! String)
|
|
// We have valid power rating
|
|
if powerInt != nil {
|
|
// Grab modulation data
|
|
let modulation: NSObject = ((channel["upstream_modulation"]!)["modulation"])! as! NSObject
|
|
// Grab power adjustment see DOCSIS 3.0 Specification for more Information)
|
|
var adjust: String = ""
|
|
if modulation.isKind(of: NSArray.self) {
|
|
adjust = modulationAdjust[(((modulation as! NSArray)[0] as! NSDictionary)["mod_type"]!) as! String]! as! String
|
|
} else{
|
|
adjust = modulationAdjust[((modulation as! NSDictionary)["mod_type"]!) as! String]! as! String
|
|
}
|
|
let adjustInt: Double = Double(adjust)!
|
|
// Add timestamp and power to file entry
|
|
entry = "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));\(String(powerInt! + adjustInt));"
|
|
// Add threshold to file entry
|
|
switch channels.count {
|
|
case 2:
|
|
entry += "\(upstreamTwo[modulationAdjust.allKeys(for: adjust)[0] as! String]!)"
|
|
case 3:
|
|
entry += "\(upstreamThreeOrFour[modulationAdjust.allKeys(for: adjust)[0] as! String]!)"
|
|
case 4:
|
|
entry += "\(upstreamThreeOrFour[modulationAdjust.allKeys(for: adjust)[0] as! String]!)"
|
|
default:
|
|
entry += "NaN"
|
|
}
|
|
// Add ranging status
|
|
entry += ";\(channel["ranging_status"] as! String)"
|
|
// Add file name to path
|
|
file = dir.appending("Upstream \(channel["frequency"]!).hex") as NSString
|
|
// Track modification
|
|
filesModified.append("Upstream \(channel["frequency"]!).hex")
|
|
// Write to file
|
|
FileOperations.logUpstream(data: entry, toFrequencyLog: file.expandingTildeInPath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// We have a single channel
|
|
else if channels is Dictionary<String,AnyObject> {
|
|
// Grab channel
|
|
let channel: Dictionary<String,AnyObject> = channels as! Dictionary<String,AnyObject>
|
|
// We do not have an error
|
|
if channel["upstream_modulation"] != nil && channel["frequency"] as! String != "status_error" {
|
|
// Grab power rating in dBmV
|
|
let powerInt: Double? = Double(channel["power_level"] as! String)
|
|
// We have valid power rating
|
|
if powerInt != nil {
|
|
// Grab modulation data
|
|
let modulation: NSObject = ((channel["upstream_modulation"]!)["modulation"])! as! NSObject
|
|
// Grab power adjustment see DOCSIS 3.0 Specification for more Information)
|
|
var adjust: String = ""
|
|
if modulation.isKind(of: NSArray.self) {
|
|
adjust = modulationAdjust[(((modulation as! NSArray)[0] as! NSDictionary)["mod_type"]!) as! String]! as! String
|
|
} else{
|
|
adjust = modulationAdjust[((modulation as! NSDictionary)["mod_type"]!) as! String]! as! String
|
|
}
|
|
let adjustInt: Double = Double(adjust)!
|
|
// Add data to entry
|
|
entry = "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));\(String(powerInt! + adjustInt));\(upstreamOne[modulationAdjust.allKeys(for: adjust)[0] as! String]!);\(channel["ranging_status"] as! String)"
|
|
// Add file name to path
|
|
file = dir.appending("Upstream \(channel["frequency"]!).hex") as NSString
|
|
// Track modifiction
|
|
filesModified.append("Upstream \(channel["frequency"]!).hex")
|
|
// Write to file
|
|
FileOperations.logUpstream(data: entry, toFrequencyLog: file.expandingTildeInPath)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Downstream is valid
|
|
if dictionaryDownstream != nil {
|
|
var entry: String = ""
|
|
var file: NSString = ""
|
|
// Grab channels
|
|
let channels: AnyObject = (dictionaryDownstream!["downstream_channel"]) as AnyObject
|
|
// We have multiple channels
|
|
if channels is [Dictionary<String,AnyObject>] {
|
|
// Simplify
|
|
let channels: [Dictionary<String, AnyObject>] = channels as! [Dictionary<String, AnyObject>]
|
|
// Step through channels
|
|
for index in 0..<channels.count {
|
|
// Grab channel
|
|
let channel: Dictionary<String,AnyObject> = channels[index]
|
|
// We do not have an error
|
|
if channel["frequency"] as! String != "status_error" {
|
|
// Add data to entry
|
|
entry = "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));\(channel["power_level"]!);\(channel["snr"]!)"
|
|
// Add file name to path
|
|
file = dir.appending("Downstream \(channel["frequency"]!).hex") as NSString
|
|
// Tracking modification
|
|
filesModified.append("Downstream \(channel["frequency"]!).hex")
|
|
// Write to file
|
|
FileOperations.logDownstream(data: entry, toFrequencyLog: file.expandingTildeInPath)
|
|
}
|
|
}
|
|
}
|
|
// We have a single channel
|
|
else if channels is Dictionary<String,AnyObject> {
|
|
// Grab channel
|
|
let channel: Dictionary<String,AnyObject> = channels as! Dictionary<String,AnyObject>
|
|
// We do not have an error
|
|
if channel["frequency"] as! String != "status_error" {
|
|
// Add data to entry
|
|
entry = "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));\(channel["power_level"]!);\(channel["snr"]!)\n"
|
|
// Add file name to path
|
|
file = dir.appending("Downstream \(channel["frequency"]!).hex") as NSString
|
|
// Tracking modification
|
|
filesModified.append("Downstream \(channel["frequency"]!).hex")
|
|
// Write to file
|
|
FileOperations.logDownstream(data: entry, toFrequencyLog: file.expandingTildeInPath)
|
|
}
|
|
}
|
|
}
|
|
// Update if not modified
|
|
let fileManager = FileManager.default
|
|
// Get all filenames in directory
|
|
let enumerator:FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: dir.expandingTildeInPath)!
|
|
// Step through files
|
|
for element in enumerator {
|
|
// Check if modified
|
|
if !filesModified.contains(element as! String) && (element as! String).contains(".hex") {
|
|
logDummie(dir: dir, element: element as! String, date: date)
|
|
}
|
|
}
|
|
}
|
|
// Update if both nil (no connection to modem possible)
|
|
else if (upstreamBool && downstreamBool) {
|
|
upstreamBool = false
|
|
downstreamBool = false
|
|
let fileManager = FileManager.default
|
|
// Get all filenames in directory
|
|
let enumerator:FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: dir.expandingTildeInPath)!
|
|
// Step through files
|
|
for element in enumerator {
|
|
logDummie(dir: dir, element: element as! String, date: date)
|
|
}
|
|
}
|
|
}
|
|
|
|
func logDummie(dir: NSString, element: String, date: Date) {
|
|
if element.contains("Upstream") {
|
|
FileOperations.logUpstream(data: "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));-;-;-", toFrequencyLog: (dir.appending(element) as NSString).expandingTildeInPath)
|
|
} else if element.contains("Downstream") {
|
|
FileOperations.logDownstream(data: "\((NSApp.delegate as! AppDelegate).justTime.string(from: date));-;-",
|
|
toFrequencyLog: (dir.appending(element) as NSString).expandingTildeInPath)
|
|
}
|
|
}
|
|
}
|