ORSSerialPort ライブラリを使用しているシリアル経由でデバイスを制御する OSX アプリを作成しています。しかし、コーディングにはいくつかの問題があります。私はコーディングが初めてで、適切にコーディングする方法がわからないため、何かを機能させようとすると問題が発生します。3 つの「クラス」を示し、それらの機能と、遭遇した問題について説明します。
ライブラリデリゲートが接続され、シリアルデバイスとのすべての通信を行うメインクラス (AE20125Controller.swift)
import Cocoa
import ORSSerial
class AE20125Controller:NSObject, ORSSerialPortDelegate {
var buffer = String()
var dataProcessor = DataProcessor()
var availablePorts = ORSSerialPortManager.sharedSerialPortManager().availablePorts
@IBOutlet weak var selectedPort: NSPopUpButton!
@IBOutlet weak var connectButton: NSButton!
@IBOutlet weak var connectedLogo: NSStackView!
var serialPort: ORSSerialPort? {
didSet {
oldValue?.close()
oldValue?.delegate = nil
serialPort?.delegate = self
}
}
//Actions
@IBAction func onOpenOrClose(sender: AnyObject) {
if let port = self.serialPort {
if (port.open) {
closePort(port)
} else {
openPort(port)
}
}
}
//Functions
func sendData(command: String) -> Bool {
if let data = command.dataUsingEncoding(NSUTF8StringEncoding) {
self.serialPort?.sendData(data)
return true
}
return false
}
func closePort(port: ORSSerialPort){
port.close()
self.connectButton.title = "Verbinden"
self.connectedLogo.hidden = true
}
func openPort(port: ORSSerialPort){
port.baudRate = 9600
port.open()
sendData("201:T:0:;") //Gets all settings form the device
self.connectedLogo.hidden = false
self.connectButton.title = "Verbreken"
}
//Delegate
func serialPort(serialPort: ORSSerialPort, didReceiveData data: NSData) {
if let string = NSString(data: data, encoding: NSUTF8StringEncoding) {
var message: String
//Assemble the full data (Data come's in in parts)
buffer.appendContentsOf(string as String)
if(buffer.containsString(dataProcessor.endToken)){
let i = buffer.rangeOfString(dataProcessor.startToken)?.startIndex
let j = buffer.rangeOfString(dataProcessor.endToken)?.endIndex
if((i != nil) && (j != nil)){
message = buffer[Range(start: i!, end: j!)]
buffer.removeRange(Range(start: i!, end: j!))
if(message != "" /*message != "201:U:0:;"*/){
dataProcessor.sortIncomingData(message)
}
}
}
}
}
func serialPortWasRemovedFromSystem(serialPort: ORSSerialPort) {
serialPort.close()
}
}
可能なすべてのメッセージが格納されている Dataprocessor クラスと、送信するデータと現在のすべての設定 (DataProcessor.swift) を組み立てたいフォーム
import Foundation
class DataProcessor {
enum dataType: String {
case frequency = "A"
case waveform = "B"
case mode = "C"
case pllReferenceEnabled = "D"
case pllFactor = "E"
case pllOffset = "F"
case startUpWavefrom = "G"
case startUpFrequency = "H"
case calibrationOffset = "I"
case sweepStartFrequency = "J"
case sweepStopFrequency = "K"
case sweepFrequency = "L"
case modulationType = "M"
case fskFrequency = "N"
case pskPhase = "O"
case modulationSource = "P"
case internalModulationFrequency = "Q"
case sweepMode = "R"
case getSettings = "T"
case keepAlive = "U"
case returnFromSweepMod = "V"
case hardwareRevison = "X"
case firmwareVersion = "Y"
case productID = "Z"
case present1Freq = "1"
case present1Waveform = "2"
case present2Freq = "3"
case present2Waveform = "4"
case present3Freq = "5"
case present3Waveform = "6"
case present4Freq = "7"
case present4Waveform = "8"
case present5Freq = "9"
case present5Waveform = "0"
func getWritable() -> Bool {
switch self {
case .frequency, .waveform, .mode, .pllReferenceEnabled, .pllFactor, .pllOffset, .startUpWavefrom, .startUpFrequency, .calibrationOffset, .sweepStartFrequency, .sweepStopFrequency, .sweepFrequency, .modulationType, .fskFrequency, .pskPhase, .modulationSource, .internalModulationFrequency,.sweepMode, .getSettings, .returnFromSweepMod, .present1Freq, .present1Waveform,.present2Freq,.present2Waveform, .present3Freq, .present3Waveform, .present4Freq, .present4Waveform, .present5Freq, .present5Waveform:
return true
default:
return false
}
}
func getReadable() -> Bool {
switch self {
case .frequency, .waveform, .mode, .pllReferenceEnabled, .pllFactor, .pllOffset, .startUpWavefrom, .startUpFrequency, .calibrationOffset, .sweepStartFrequency, .sweepStopFrequency, .sweepFrequency, .modulationType, .fskFrequency, .pskPhase, .modulationSource, .internalModulationFrequency, .sweepMode, .keepAlive, .hardwareRevison, .firmwareVersion, .productID:
return true
default:
return false
}
}
func getMaxValues() -> Int{
switch self {
case .frequency:
return 10000000
case .waveform:
return 3
case .mode:
return 3
case .pllReferenceEnabled:
return 2
case .pllFactor:
return 9999
case .pllOffset:
return 10000000
case .startUpWavefrom:
return 3
case .startUpFrequency:
return 10000000
case .calibrationOffset:
return 10000
case .sweepStartFrequency:
fallthrough
case .sweepStopFrequency:
return 10000000
case .sweepFrequency:
return 100
case .modulationType:
return 2
case .fskFrequency:
return 10000000
case .pskPhase:
return 3599
case .modulationSource:
return 2
case .internalModulationFrequency:
return 10000
case .sweepMode:
return 2
case .getSettings:
return 0
case .returnFromSweepMod, .present1Freq, .present2Freq, .present3Freq, .present4Freq, .present5Freq:
return 10000000
case .present1Waveform, .present2Waveform, .present3Waveform, .present4Waveform, .present5Waveform:
return 3
default:
return -1
}
}
}
let endToken = ":;"
let startToken = "201:"
var settings:[(dataType):(String)] = [:]
//Methodes
func sortIncomingData(data: String){
let i = data.rangeOfString(startToken)?.endIndex
let j = data.rangeOfString(endToken)?.startIndex
let sortedCode = data.substringWithRange(Range(start: i!, end: i!.advancedBy(1)))
let sortedData = data.substringWithRange(Range(start: i!.advancedBy(2), end: j! ))
settings[dataType(rawValue: sortedCode)!] = sortedData
}
func setData(data: dataType, value: Float){
settings.updateValue(String(value), forKey: data)
AE20125Controller.sendData(...) //<-- Is not working (Ignore the dots)
}
}
GUI でのすべての変更とアクションを処理する menuItems クラス。(MenuItems.swift)
import Cocoa
class MenuItems:NSObject{
@IBOutlet weak var freqView: NSView!
@IBOutlet weak var test: NSTextField!
//Actions
@IBAction func setFreq(sender: AnyObject) {
}
}
AppDelegate には何も含まれていないため省略しましたが、ビューを構築するための設定です (たとえば、ビューの背景を白に変更します)。
クラス間で通信できません。たとえば、DataProcessor クラスの AE20125Controller クラスで sendData メソッドを使用してデータを送信する必要がありますが、それを開始する必要があります。しかし、DataProcessor クラスは AE20125Controller クラスで開始されますか? これは MenuItems クラスにも当てはまります。updateFreq ボタンが押されると、DataProcessor クラスのメソッド setData が呼び出されるはずですが、それを開始する必要があります。
正直なところ、私は自分が何をしているのか、このシステムを適切に機能させる方法がわからないので、すべてを 1 つのファイルにまとめずに、整理しておくことができます。繰り返しますが、私はプログラミングは初めてですが、(自分でそう言うかもしれませんが)プログラミングの知識はある程度あります。私の(くだらない)コードを整理するのを手伝ってください。また、今後これを回避する方法についてのヒントを教えてください。
(良い Advanced Swift OSX プログラミング ガイド/コースを知っている場合は、教えてください。(無料である必要はありません))
前もって感謝します