Skip to content

Commit

Permalink
FEAT: Add Sockets handler for octoprint push events
Browse files Browse the repository at this point in the history
  • Loading branch information
josefdolezal committed May 13, 2017
1 parent 5196391 commit 15b1a17
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
4 changes: 4 additions & 0 deletions OctoPhone.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
D28EC5371E09E65F0089C027 /* FilesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28EC5361E09E65F0089C027 /* FilesViewController.swift */; };
D28EC5391E09E6740089C027 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28EC5381E09E6740089C027 /* SettingsViewController.swift */; };
D2A07F721EC7361400ACAB6A /* WebSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A07F711EC7361400ACAB6A /* WebSocket.swift */; };
D2A07F741EC7398100ACAB6A /* OctoPrintPushEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A07F731EC7398100ACAB6A /* OctoPrintPushEvents.swift */; };
D2A601301DF3870F006B833E /* PrinterListCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6012F1DF3870F006B833E /* PrinterListCollectionViewCell.swift */; };
D2ABD3E21E9B8985003EDDAA /* OPFileSizeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ABD3E11E9B8985003EDDAA /* OPFileSizeFormatter.swift */; };
D2ABD3E41E9B8E30003EDDAA /* OPDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ABD3E31E9B8E30003EDDAA /* OPDateFormatter.swift */; };
Expand Down Expand Up @@ -415,6 +416,7 @@
D28EC5361E09E65F0089C027 /* FilesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilesViewController.swift; sourceTree = "<group>"; };
D28EC5381E09E6740089C027 /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
D2A07F711EC7361400ACAB6A /* WebSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebSocket.swift; sourceTree = "<group>"; };
D2A07F731EC7398100ACAB6A /* OctoPrintPushEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OctoPrintPushEvents.swift; sourceTree = "<group>"; };
D2A6012F1DF3870F006B833E /* PrinterListCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrinterListCollectionViewCell.swift; sourceTree = "<group>"; };
D2A713811DE7069F00BDC0C4 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
D2ABD3E11E9B8985003EDDAA /* OPFileSizeFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OPFileSizeFormatter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -932,6 +934,7 @@
isa = PBXGroup;
children = (
D2A07F711EC7361400ACAB6A /* WebSocket.swift */,
D2A07F731EC7398100ACAB6A /* OctoPrintPushEvents.swift */,
);
path = Sockets;
sourceTree = "<group>";
Expand Down Expand Up @@ -1509,6 +1512,7 @@
D27C97161E63C25D00641A1A /* TokenPlugin.swift in Sources */,
D2072FD41DEDCD6D00E1BBD3 /* Printer.swift in Sources */,
D2688D791E9052DC00290421 /* SlicingProfileCollectionViewCell.swift in Sources */,
D2A07F741EC7398100ACAB6A /* OctoPrintPushEvents.swift in Sources */,
D2FF97241DF0DFC3005CA7B2 /* PrinterListViewController.swift in Sources */,
D24EDCC01E90087900A8437B /* SlicingProfilesViewModel.swift in Sources */,
D2D990B91E6F66C70094DA64 /* CurrentPrintViewModel.swift in Sources */,
Expand Down
97 changes: 97 additions & 0 deletions OctoPhone/Utils/Sockets/OctoPrintPushEvents.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// OctoPrintPushEvents.swift
// OctoPhone
//
// Created by Josef Dolezal on 13/05/2017.
// Copyright © 2017 Josef Dolezal. All rights reserved.
//

import enum Result.NoError
import ReactiveSwift

/// Shorthand for temperatures values
typealias PrinterTemperatures = (bed: Bed, tool: Tool)

/// OctoPrint Push events provider
class OctoPrintPushEvents {

/// URL of connection target
private let url: URL

/// Web sockets connection provider
private let sockets = WebSocket()

init(url: URL) {
// Connects to random printer socket stream
self.url = url.appendingPathComponent("/sockjs/286/sd3d24ew/xhr_streaming")
}

/// Stream of current temperatures of printers,
/// the signal is endless and must be disposed manually
func temperatures() -> SignalProducer<PrinterTemperatures, NoError> {
return currentPrinterState().map { json -> PrinterTemperatures? in

guard
let temperaturesObject = json["temps"] as? [[String: Any]],
let toolObject = temperaturesObject.first?["tool0"] as? [String: Any],
let bedObject = temperaturesObject.first?["bed"] as? [String: Any],
let tool = try? Tool.fromJSON(json: toolObject),
let bed = try? Bed.fromJSON(json: bedObject)
else {
return nil
}

return (bed, tool)
}
.skipNil()
}

/// Reads only current printer state from sockets, filters out all different events
///
/// - Returns: Signal of current printer states
private func currentPrinterState() -> SignalProducer<[String: Any], NoError> {
return connect().map({
return $0["current"] as? [String: Any]
})
.skipNil()
}

/// Creates a generic connection requests and converts response data to valid JSON
///
/// - Returns: Signal with response JSONs
private func connect() -> SignalProducer<[String: Any], NoError> {

let connection = sockets.connect(url: url, withMethod: .post)

return SignalProducer { sink, disposable in

let requestDisposable = connection.startWithValues { data in
guard let response = String(data: data, encoding: .utf8) else { return }

let startIndex = response.index(after: response.startIndex)

// Strip the first character from value
let cleanString = response.substring(from: startIndex)

// Splits OctoPrint outputs into single lines
cleanString.enumerateLines(invoking: { line, _ in
guard
let strippedData = line.data(using: .utf8),
let object = try? JSONSerialization.jsonObject(with: strippedData, options: .allowFragments),
let json = object as? [[String: Any]]
else { return }

// The OctoPrint returns array in which is the key-value object
if let json = json.first {
sink.send(value: json)
}
})
}

disposable.add {
requestDisposable.dispose()
}
}
.filter { $0.count > 0 }
}
}

0 comments on commit 15b1a17

Please sign in to comment.