Skip to content

Commit

Permalink
Implemented and tested custom controls.
Browse files Browse the repository at this point in the history
Closes #15
  • Loading branch information
gdombiak committed Aug 28, 2018
1 parent 44e8084 commit a12cdaf
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 11 deletions.
10 changes: 5 additions & 5 deletions OctoPod/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -854,21 +854,21 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZCe-kf-ukt">
<rect key="frame" x="16" y="12" width="279" height="21"/>
<rect key="frame" x="16" y="12" width="157" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="qWC-Kz-qjC">
<rect key="frame" x="303" y="6" width="56" height="30"/>
<rect key="frame" x="181" y="6" width="178" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="56" id="a0U-tT-Dj7"/>
<constraint firstAttribute="width" constant="178" id="a0U-tT-Dj7"/>
</constraints>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<connections>
<action selector="valueChanged:" destination="vCt-Do-JlF" eventType="editingDidEnd" id="a3p-dM-UaI"/>
<action selector="valueChanged:" destination="vCt-Do-JlF" eventType="editingChanged" id="feT-Dq-Rmf"/>
</connections>
</textField>
</subviews>
Expand Down Expand Up @@ -909,7 +909,7 @@
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" spellCheckingType="no" keyboardType="numberPad"/>
<connections>
<action selector="valueChanged:" destination="oit-r3-Yvc" eventType="editingDidEnd" id="nUj-cP-5jE"/>
<action selector="valueChanged:" destination="oit-r3-Yvc" eventType="editingDidEnd" id="aCT-lh-WTB"/>
</connections>
</textField>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="e1d-k0-68j">
Expand Down
18 changes: 17 additions & 1 deletion OctoPod/Model/Commands/Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ class Command: ExecuteControl {
}

func executePayload() -> NSDictionary {
return [:]
let result = NSMutableDictionary()
if let commandsArray = commands {
result["commands"] = commandsArray
} else if let singleCommand = command {
result["commands"] = [singleCommand]
}

var paramsDict: NSMutableDictionary?
if let input = _input {
paramsDict = NSMutableDictionary()
for controlInput in input {
let entry: (key: String, value: Any) = controlInput.executePayload()
paramsDict?[entry.key] = entry.value
}
result["parameters"] = paramsDict!
}
return result
}
}
10 changes: 10 additions & 0 deletions OctoPod/Model/Commands/ControlInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ class ControlInput {
self.parameter = parameter
self.hasSlider = false // Assume false until proven otherwise
}

func executePayload() -> (key: String, value: Any) {
if hasSlider {
if let intValue = value as? Int {
return (parameter, intValue)
}
return (parameter, value as! Float)
}
return (parameter, value as! String)
}
}
14 changes: 13 additions & 1 deletion OctoPod/Model/Commands/Script.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ class Script: ExecuteControl {
}

func executePayload() -> NSDictionary {
return [:]
let result = NSMutableDictionary()
result["script"] = script

var paramsDict: NSMutableDictionary?
if let input = _input {
paramsDict = NSMutableDictionary()
for controlInput in input {
let entry: (key: String, value: Any) = controlInput.executePayload()
paramsDict?[entry.key] = entry.value
}
result["parameters"] = paramsDict!
}
return result
}
}
19 changes: 16 additions & 3 deletions OctoPod/OctoPrint/OctoPrintClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,12 @@ class OctoPrintClient: WebSocketClientDelegate {
}
}

func executeCustomControl() {

func executeCustomControl(control: NSDictionary, callback: @escaping (Bool, Error?, HTTPURLResponse) -> Void) {
if let client = httpClient {
client.post("/api/printer/command", json: control, expected: 204) { (result: NSObject?, error: Error?, response: HTTPURLResponse) in
callback(response.statusCode == 204, error, response)
}
}
}

// MARK: - PSU Control Plugin operations
Expand Down Expand Up @@ -1044,7 +1048,10 @@ class OctoPrintClient: WebSocketClientDelegate {
} else if let gcodeCommands = json["commands"] as? NSArray {
var newCommands: Array<String> = Array()
for case let gcodeCommand as String in gcodeCommands {
newCommands.append(gcodeCommand)
if !gcodeCommand.isEmpty {
// Ignore empty commands
newCommands.append(gcodeCommand)
}
}
command.commands = newCommands
} else {
Expand Down Expand Up @@ -1076,16 +1083,22 @@ class OctoPrintClient: WebSocketClientDelegate {
controlInput.hasSlider = true
if let sliderMax = slider["max"] as? String {
controlInput.slider_max = sliderMax
} else if let sliderMax = slider["max"] as? NSNumber {
controlInput.slider_max = sliderMax.stringValue
} else {
controlInput.slider_max = "255"
}
if let sliderMin = slider["min"] as? String {
controlInput.slider_min = sliderMin
} else if let sliderMin = slider["min"] as? NSNumber {
controlInput.slider_min = sliderMin.stringValue
} else {
controlInput.slider_min = "0"
}
if let sliderStep = slider["step"] as? String {
controlInput.slider_step = sliderStep
} else if let sliderStep = slider["step"] as? NSNumber {
controlInput.slider_step = sliderStep.stringValue
} else {
controlInput.slider_step = "1"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,18 @@ class ExecuteControlViewController: ThemedDynamicUITableViewController {
cell.inputLabel?.text = controlInput.name
cell.inputLabel?.textColor = Theme.currentTheme().labelColor()

if let text = controlInput.defaultValue as? String {
cell.inputValueField.text = text
}

return cell
}
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 44
}

// MARK: - Notifications

func valueUpdated(row: Int, value: AnyObject) {
Expand All @@ -94,7 +102,20 @@ class ExecuteControlViewController: ThemedDynamicUITableViewController {

@objc func execute() {
let executeBlock = {
self.octoprintClient.executeCustomControl()
let json = self.control.executePayload()
self.octoprintClient.executeCustomControl(control: json, callback: { (requested: Bool, error: Error?, response: HTTPURLResponse) in
if !requested {
// Handle error
NSLog("Error requesting to execute command \(json). HTTP status code \(response.statusCode)")
if response.statusCode == 409 {
self.showAlert("Alert", message: "Command not executed. Printer not operational")
} else if response.statusCode == 404 {
self.showAlert("Alert", message: "Command not executed. Script not found")
} else {
self.showAlert("Alert", message: "Failed to request to execute command")
}
}
})
}

if let confirmation = control.confirm() {
Expand All @@ -121,6 +142,19 @@ class ExecuteControlViewController: ThemedDynamicUITableViewController {
})
}

fileprivate func showAlert(_ title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: { (UIAlertAction) -> Void in
// Nothing to do here
}))
// We are not always on the main thread so present dialog on main thread to prevent crashes
DispatchQueue.main.async {
self.present(alert, animated: true) { () -> Void in
// Nothing to do here
}
}
}

fileprivate func showConfirm(message: String, yes: @escaping (UIAlertAction) -> Void, no: @escaping (UIAlertAction) -> Void) {
let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: yes))
Expand Down

0 comments on commit a12cdaf

Please sign in to comment.