First release to App Store
This commit is contained in:
27
pocloud/Cells/DeviceChannelTableCell.swift
Normal file
27
pocloud/Cells/DeviceChannelTableCell.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// DeviceChannelTableCell.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/19/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class DeviceChannelTableCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var valueLabel: UILabel!
|
||||
@IBOutlet weak var nameLabel: UILabel!
|
||||
@IBOutlet weak var timestampLabel: UILabel!
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
}
|
||||
@@ -140,6 +140,11 @@ class DeviceListViewController: UITableViewController {
|
||||
let destinationVC = segue.destination as! DeviceDetailViewController
|
||||
destinationVC.thisDevice = selectedDevice!
|
||||
}
|
||||
|
||||
if segue.identifier == "openMaxWaterSystem" {
|
||||
let destinationVC = segue.destination as! MaxWaterSystemViewController
|
||||
destinationVC.thisDevice = selectedDevice!
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
@@ -156,12 +161,14 @@ class DeviceListViewController: UITableViewController {
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let uniqueDeviceTypes = getUniqueDeviceTypeNames()
|
||||
let deviceTypesWithDevices = devices?.filter("ANY parentDeviceType.vanityName == %@", uniqueDeviceTypes[indexPath.section]).sorted(byKeyPath: "vanityName")
|
||||
// let deviceTypesWithDevices = deviceTypes?.filter(deviceTypeFilter)
|
||||
// if let thisSection = deviceTypesWithDevices?[indexPath.section] {
|
||||
// selectedDevice = thisSection.devices[indexPath.row]
|
||||
selectedDevice = deviceTypesWithDevices?[indexPath.row]
|
||||
selectedDevice = deviceTypesWithDevices?[indexPath.row]
|
||||
switch (selectedDevice?.parentDeviceType.first?.name){
|
||||
case "advvfdipp":
|
||||
performSegue(withIdentifier: "openMaxWaterSystem", sender: self)
|
||||
|
||||
default:
|
||||
performSegue(withIdentifier: "openDeviceDetailView", sender: self)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
143
pocloud/Controller/Devices/BaseDeviceViewController.swift
Normal file
143
pocloud/Controller/Devices/BaseDeviceViewController.swift
Normal file
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// BaseDeviceViewController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/11/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RealmSwift
|
||||
import FirebaseDatabase
|
||||
import SVProgressHUD
|
||||
import PromiseKit
|
||||
|
||||
class BaseDeviceViewController: UIViewController {
|
||||
let realm = try! Realm()
|
||||
var ref: DatabaseReference!
|
||||
let baseURL = (UIApplication.shared.delegate as! AppDelegate).baseURL
|
||||
let user = (UIApplication.shared.delegate as! AppDelegate).user
|
||||
|
||||
var thisDevice : Device?
|
||||
var deviceTypes : Results<DeviceType>?
|
||||
var selectedChannel : Channel?
|
||||
|
||||
var channelLookup : [String : Int] = [:]
|
||||
var values : [String : MeshifyValue] = [:]
|
||||
var updatedChannelNames : [String] = [String]()
|
||||
var changedChannelNames : [String] = [String]()
|
||||
let numFormatter = NumberFormatter()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
ref = Database.database().reference()
|
||||
|
||||
numFormatter.minimumFractionDigits = 0
|
||||
numFormatter.maximumFractionDigits = 3
|
||||
numFormatter.minimumIntegerDigits = 1
|
||||
|
||||
initializeData()
|
||||
}
|
||||
|
||||
func initializeData() {
|
||||
let macAddress = String((thisDevice?.macAddress.replacingOccurrences(of: ":", with: "").uppercased().dropLast(4))!)
|
||||
let deviceTypeName = (thisDevice?.parentDeviceType.first?.name)!
|
||||
SVProgressHUD.show()
|
||||
firstly {
|
||||
loadData()
|
||||
}.then { _ in
|
||||
getChannels(deviceTypeId: self.thisDevice!.deviceTypeId, baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
}.then { _ in
|
||||
getChannelValues(deviceId: self.thisDevice!.id, baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
}.done { (valueDict) in
|
||||
self.values = valueDict
|
||||
self.updateGauges()
|
||||
self.updateChartData()
|
||||
SVProgressHUD.dismiss()
|
||||
if let dev = self.thisDevice {
|
||||
for chanIndex in 0..<dev.values.count {
|
||||
let chanName = dev.values[chanIndex].name
|
||||
self.channelLookup[chanName] = chanIndex
|
||||
}
|
||||
}
|
||||
self.getFirebaseDeviceValues(deviceMacAddress: macAddress, deviceTypeName: deviceTypeName)
|
||||
}.catch { error in
|
||||
SVProgressHUD.showError(withStatus: "\(error)")
|
||||
print("Error fetching data in DeviceDetailViewController: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
Database.database().reference().removeAllObservers()
|
||||
}
|
||||
|
||||
func getFirebaseDeviceValues(deviceMacAddress : String, deviceTypeName : String) {
|
||||
Database.database().reference().child("devices")
|
||||
.child(deviceMacAddress)
|
||||
.child(deviceTypeName)
|
||||
.child("channels")
|
||||
.observe(.childChanged) { snapshot in
|
||||
let value = snapshot.value as! NSDictionary
|
||||
let chanVal = MeshifyValue()
|
||||
|
||||
if let name = value["name"] as? String {
|
||||
chanVal.name = name
|
||||
}
|
||||
|
||||
if let timestamp = value["timestamp"] as? String {
|
||||
chanVal.timestamp = Int(Double(timestamp)!)
|
||||
}
|
||||
|
||||
if let readValue = value["value"] as? String {
|
||||
chanVal.value = readValue
|
||||
}
|
||||
|
||||
let prevChanValue = self.values[chanVal.name]?.value
|
||||
if prevChanValue != chanVal.value {
|
||||
self.changedChannelNames.append(chanVal.name)
|
||||
} else {
|
||||
self.updatedChannelNames.append(chanVal.name)
|
||||
}
|
||||
self.values[chanVal.name] = chanVal
|
||||
self.updateGauges()
|
||||
self.updateChartData()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func updateGauges(){
|
||||
return
|
||||
}
|
||||
|
||||
func updateChartData(){
|
||||
return
|
||||
}
|
||||
|
||||
func tryRound(value : String, places numberOfPlaces: Int) -> String {
|
||||
if let doubledValue = Double(value) {
|
||||
if let formattedString = numFormatter.string(from: NSNumber(value: doubledValue)) {
|
||||
return formattedString
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if segue.identifier == "goToChannelView" {
|
||||
let destinationVC = segue.destination as! ChannelDetailViewController
|
||||
destinationVC.thisDevice = thisDevice!
|
||||
destinationVC.thisChannel = selectedChannel!
|
||||
}
|
||||
}
|
||||
|
||||
func loadData() -> Promise<Void> {
|
||||
return Promise { promise in
|
||||
deviceTypes = realm.objects(DeviceType.self)
|
||||
thisDevice = realm.objects(Device.self).filter("id == %d", thisDevice!.id).first!
|
||||
promise.fulfill(())
|
||||
}
|
||||
}
|
||||
}
|
||||
138
pocloud/Controller/Devices/MaxWaterSystemViewController.swift
Normal file
138
pocloud/Controller/Devices/MaxWaterSystemViewController.swift
Normal file
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// MaxWaterSystemViewController.swift
|
||||
// pocloud
|
||||
//
|
||||
// Created by Patrick McDonagh on 6/11/18.
|
||||
// Copyright © 2018 patrickjmcd. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SVProgressHUD
|
||||
import PromiseKit
|
||||
import ChameleonFramework
|
||||
|
||||
class MaxWaterSystemViewController: BaseDeviceViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
@IBOutlet weak var startButton: UIButton!
|
||||
@IBOutlet weak var stopButton: UIButton!
|
||||
@IBOutlet weak var resetFaultsButton: UIButton!
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
let channelLabels : [String] = ["Status", "Fluid Level", "Flow Rate", "Intake Pressure", "Intake Temperature", "Motor Frequency", "Motor Current", "Tubing Pressure"]
|
||||
let channelNames : [String] = ["wellstatus", "fluidlevel", "flowrate", "intakepressure", "intaketemperature", "vfdfrequency", "vfdcurrent", "tubingpressure"]
|
||||
let formatter = DateFormatter()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||||
|
||||
self.title = thisDevice?.vanityName
|
||||
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
|
||||
tableView.estimatedRowHeight = 80
|
||||
tableView.rowHeight = UITableViewAutomaticDimension
|
||||
|
||||
startButton.backgroundColor = UIColor.flatWhiteColorDark()
|
||||
startButton.setTitleColor(UIColor.flatForestGreen(), for: .normal)
|
||||
startButton.layer.cornerRadius = 5
|
||||
startButton.layer.borderWidth = 1
|
||||
startButton.layer.borderColor = UIColor.flatForestGreen().cgColor
|
||||
|
||||
stopButton.backgroundColor = UIColor.flatWhiteColorDark()
|
||||
stopButton.setTitleColor(UIColor.flatRed(), for: .normal)
|
||||
stopButton.layer.cornerRadius = 5
|
||||
stopButton.layer.borderWidth = 1
|
||||
stopButton.layer.borderColor = UIColor.flatRed().cgColor
|
||||
|
||||
resetFaultsButton.backgroundColor = UIColor.flatWhiteColorDark()
|
||||
resetFaultsButton.setTitleColor(UIColor.flatBlue(), for: .normal)
|
||||
resetFaultsButton.layer.cornerRadius = 5
|
||||
resetFaultsButton.layer.borderWidth = 1
|
||||
resetFaultsButton.layer.borderColor = UIColor.flatBlue().cgColor
|
||||
|
||||
|
||||
}
|
||||
|
||||
//MARK: - Table View Methods
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return channelLabels.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "deviceChannelCell", for: indexPath) as! DeviceChannelTableCell
|
||||
cell.nameLabel.text = channelLabels[indexPath.row]
|
||||
|
||||
if let meshVal = values[channelNames[indexPath.row]] {
|
||||
cell.valueLabel.text = tryRound(value: meshVal.value, places: 3)
|
||||
cell.timestampLabel.text = formatter.string(from: Date(timeIntervalSince1970: Double(meshVal.timestamp)))
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
selectedChannel = thisDevice?.parentDeviceType.first?.channels[indexPath.row]
|
||||
performSegue(withIdentifier: "goToChannelView", sender: self)
|
||||
}
|
||||
|
||||
override func updateChartData() {
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
//MARK: - Control Button Methods
|
||||
@IBAction func startButtonPressed(_ sender: Any) {
|
||||
let alert = UIAlertController(title: "Start Well", message: "Are you sure you want to start the well?", preferredStyle: .alert)
|
||||
let action = UIAlertAction(title: "Start", style: .default) { (action) in
|
||||
// what will happen once the user clicks the add item button on our UIAlert
|
||||
firstly {
|
||||
setChannelValue(deviceId: (self.thisDevice?.id)!, channelName: "writeplctag", value: "{'tag': 'cmd_Start', 'val': 1}", baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
}.done { _ in
|
||||
self.initializeData()
|
||||
}.catch { error in
|
||||
print("ERROR IN startButtonPressed: \(error)")
|
||||
}
|
||||
|
||||
}
|
||||
alert.addAction(action)
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func resetButtonPressed(_ sender: UIButton) {
|
||||
let alert = UIAlertController(title: "Reset Well", message: "Are you sure you want to reset the well?", preferredStyle: .alert)
|
||||
let action = UIAlertAction(title: "Reset", style: .default) { (action) in
|
||||
// what will happen once the user clicks the add item button on our UIAlert
|
||||
firstly {
|
||||
setChannelValue(deviceId: (self.thisDevice?.id)!, channelName: "writeplctag", value: "{'tag': 'cmd_ResetAlarms', 'val': 1}", baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
}.done { _ in
|
||||
self.initializeData()
|
||||
}.catch { error in
|
||||
print("ERROR IN resetButtonPressed: \(error)")
|
||||
}
|
||||
|
||||
}
|
||||
alert.addAction(action)
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||
present(alert, animated: true, completion: nil)
|
||||
|
||||
}
|
||||
@IBAction func stopButtonPressed(_ sender: Any) {
|
||||
let alert = UIAlertController(title: "Stop Well", message: "Are you sure you want to stop the well?", preferredStyle: .alert)
|
||||
let action = UIAlertAction(title: "Stop", style: .default) { (action) in
|
||||
// what will happen once the user clicks the add item button on our UIAlert
|
||||
firstly {
|
||||
setChannelValue(deviceId: (self.thisDevice?.id)!, channelName: "writeplctag", value: "{'tag': 'cmd_Stop', 'val': 1}", baseURL: self.baseURL, authToken: (self.user?.authToken)!)
|
||||
}.done { _ in
|
||||
self.initializeData()
|
||||
}.catch { error in
|
||||
print("ERROR IN stopButtonPressed: \(error)")
|
||||
}
|
||||
|
||||
}
|
||||
alert.addAction(action)
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,14 @@ class MapDetailViewController: UIViewController, MKMapViewDelegate, UITableViewD
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
selectedDevice = devices?[indexPath.row]
|
||||
performSegue(withIdentifier: "openDeviceDetailView", sender: self)
|
||||
switch (selectedDevice?.parentDeviceType.first?.name){
|
||||
case "advvfdipp":
|
||||
performSegue(withIdentifier: "openMaxWaterSystem", sender: self)
|
||||
|
||||
default:
|
||||
performSegue(withIdentifier: "openDeviceDetailView", sender: self)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -115,6 +122,11 @@ class MapDetailViewController: UIViewController, MKMapViewDelegate, UITableViewD
|
||||
let destinationVC = segue.destination as! DeviceDetailViewController
|
||||
destinationVC.thisDevice = selectedDevice!
|
||||
}
|
||||
|
||||
if segue.identifier == "openMaxWaterSystem" {
|
||||
let destinationVC = segue.destination as! MaxWaterSystemViewController
|
||||
destinationVC.thisDevice = selectedDevice!
|
||||
}
|
||||
}
|
||||
|
||||
func getDevicesAtGateway(){
|
||||
|
||||
@@ -372,10 +372,10 @@ func getAllMeshifyData(baseURL : String, authToken : String) -> Promise<Void>{
|
||||
}
|
||||
|
||||
func writeChannelValue(deviceId: Int, channelName: String, value : String, baseURL : String, authToken : String) -> Promise<Any> {
|
||||
let timestamp: Int = Int(Date().timeIntervalSince1970)
|
||||
// let timestamp: Int = Int(Date().timeIntervalSince1970)
|
||||
var channelJson : JSON = JSON()
|
||||
channelJson["name"].string = channelName
|
||||
channelJson["timestamp"].int = timestamp
|
||||
// channelJson["timestamp"].int = timestamp
|
||||
channelJson["value"].string = value
|
||||
|
||||
var listJson = JSON()
|
||||
@@ -401,6 +401,34 @@ func writeChannelValue(deviceId: Int, channelName: String, value : String, baseU
|
||||
|
||||
}
|
||||
|
||||
func setChannelValue(deviceId: Int, channelName: String, value : String, baseURL : String, authToken : String) -> Promise<Any> {
|
||||
// let timestamp: Int = Int(Date().timeIntervalSince1970)
|
||||
var channelJson : JSON = JSON()
|
||||
channelJson["name"].string = channelName
|
||||
// channelJson["timestamp"].int = timestamp
|
||||
channelJson["value"].string = value
|
||||
|
||||
var listJson = JSON()
|
||||
listJson.arrayObject = [channelJson]
|
||||
|
||||
let url = "\(baseURL)/devices/\(deviceId)/sets?tries=2"
|
||||
let headers : HTTPHeaders = [
|
||||
"Authorization": authToken
|
||||
]
|
||||
|
||||
return Promise { promise in
|
||||
Alamofire.request(url, method: .put, parameters: [:], encoding: listJson.rawString()!, headers: headers)
|
||||
.response { response in
|
||||
if response.response?.statusCode == 200 {
|
||||
promise.fulfill(true)
|
||||
} else {
|
||||
promise.reject(String(response.response!.statusCode) as! Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension String: ParameterEncoding {
|
||||
|
||||
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>9-rc1</string>
|
||||
<string>10</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="cnt" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="16b-fu-GPA" customClass="PillUILabel" customModule="pocloud" customModuleProvider="target">
|
||||
<rect key="frame" x="278.5" y="11.5" width="46.5" height="20.5"/>
|
||||
<rect key="frame" x="278.5" y="8.5" width="46.5" height="26.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.32852089410000002" blue="0.57488495110000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
@@ -294,13 +294,13 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="TeN-MF-HxZ">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
|
||||
<subviews>
|
||||
<mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="UFa-F1-ny6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="215.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="201"/>
|
||||
</mapView>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="tuB-TB-6oT">
|
||||
<rect key="frame" x="0.0" y="215.5" width="375" height="431.5"/>
|
||||
<rect key="frame" x="0.0" y="201" width="375" height="402"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="companyGatewayCell" id="vCb-SM-3BC">
|
||||
@@ -488,12 +488,169 @@
|
||||
<outlet property="mapView" destination="xug-gE-FQz" id="zcG-aP-FLr"/>
|
||||
<outlet property="nameLabel" destination="izu-lT-xWY" id="lfC-J4-u3o"/>
|
||||
<segue destination="eOb-fR-aFg" kind="show" identifier="openDeviceDetailView" id="4nz-VA-pdT"/>
|
||||
<segue destination="Kh2-JZ-Ct9" kind="show" identifier="openMaxWaterSystem" id="X79-lN-WJj"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Rio-1u-3O1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2001" y="-325"/>
|
||||
</scene>
|
||||
<!--Max Water System View Controller-->
|
||||
<scene sceneID="6Zk-sY-e61">
|
||||
<objects>
|
||||
<viewController id="Kh2-JZ-Ct9" customClass="MaxWaterSystemViewController" customModule="pocloud" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="yIs-ci-nnM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IXb-tG-hee">
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="80"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="LvW-UQ-MXT">
|
||||
<rect key="frame" x="8" y="25" width="359" height="30"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7gt-Oj-XNj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="114.5" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<state key="normal" title="Start">
|
||||
<color key="titleColor" red="0.19115509089999999" green="0.63786703349999996" blue="0.26147949700000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="startButtonPressed:" destination="Kh2-JZ-Ct9" eventType="touchUpInside" id="zmb-z0-43Z"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Txg-Ba-9sP">
|
||||
<rect key="frame" x="122.5" y="0.0" width="114" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<state key="normal" title="Reset Faults">
|
||||
<color key="titleColor" red="0.19115509089999999" green="0.63786703349999996" blue="0.26147949700000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="resetButtonPressed:" destination="Kh2-JZ-Ct9" eventType="touchUpInside" id="pp1-pa-dIJ"/>
|
||||
<action selector="startButtonPressed:" destination="Kh2-JZ-Ct9" eventType="touchUpInside" id="IOP-Wu-8gU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1gY-X0-Fpq">
|
||||
<rect key="frame" x="244.5" y="0.0" width="114.5" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<state key="normal" title="Stop">
|
||||
<color key="titleColor" red="0.67455112930000005" green="0.15692374110000001" blue="0.10914970929999999" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="stopButtonPressed:" destination="Kh2-JZ-Ct9" eventType="touchUpInside" id="qq0-20-Dbg"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="1gY-X0-Fpq" firstAttribute="width" secondItem="Txg-Ba-9sP" secondAttribute="width" id="7yP-vW-Rvg"/>
|
||||
<constraint firstItem="1gY-X0-Fpq" firstAttribute="width" secondItem="7gt-Oj-XNj" secondAttribute="width" id="88Q-sI-4Tg"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="80" id="aMc-N0-plk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="LvW-UQ-MXT" secondAttribute="bottom" constant="25" id="b6U-3x-rEv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="LvW-UQ-MXT" secondAttribute="trailing" constant="8" id="bqe-Li-6kh"/>
|
||||
<constraint firstItem="LvW-UQ-MXT" firstAttribute="top" secondItem="IXb-tG-hee" secondAttribute="top" constant="25" id="duv-dy-UfT"/>
|
||||
<constraint firstItem="LvW-UQ-MXT" firstAttribute="leading" secondItem="IXb-tG-hee" secondAttribute="leading" constant="8" id="yeO-sf-ffT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="80" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="eD7-bx-SvD">
|
||||
<rect key="frame" x="0.0" y="144" width="375" height="523"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="deviceChannelCell" id="dUo-d1-EQI" customClass="DeviceChannelTableCell" customModule="pocloud" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="dUo-d1-EQI" id="dAi-UV-jeN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" alignment="bottom" translatesAutoresizingMaskIntoConstraints="NO" id="nXZ-ID-zPe">
|
||||
<rect key="frame" x="8" y="0.0" width="359" height="43"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="2cy-48-y14">
|
||||
<rect key="frame" x="0.0" y="0.0" width="224.5" height="43"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GRm-Zh-qFB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="224.5" height="21.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="18"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Timestamp" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MWr-1t-Ey5">
|
||||
<rect key="frame" x="0.0" y="21.5" width="224.5" height="21.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="13"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="GRm-Zh-qFB" firstAttribute="leading" secondItem="2cy-48-y14" secondAttribute="leading" id="0fq-zC-wbL"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GRm-Zh-qFB" secondAttribute="trailing" id="Kac-un-jbH"/>
|
||||
<constraint firstItem="MWr-1t-Ey5" firstAttribute="leading" secondItem="2cy-48-y14" secondAttribute="leading" id="QWW-zz-ARv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MWr-1t-Ey5" secondAttribute="trailing" id="muZ-q8-gEy"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Value" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7ZM-sO-DrN">
|
||||
<rect key="frame" x="224.5" y="0.0" width="134.5" height="43"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="7ZM-sO-DrN" secondAttribute="bottom" id="66D-kx-uj4"/>
|
||||
<constraint firstItem="2cy-48-y14" firstAttribute="top" secondItem="nXZ-ID-zPe" secondAttribute="top" id="C7D-gL-2Da"/>
|
||||
<constraint firstItem="7ZM-sO-DrN" firstAttribute="width" secondItem="2cy-48-y14" secondAttribute="width" multiplier="3:5" id="GbE-ZZ-KW2"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2cy-48-y14" secondAttribute="bottom" id="JRS-aO-dol"/>
|
||||
<constraint firstItem="7ZM-sO-DrN" firstAttribute="top" secondItem="nXZ-ID-zPe" secondAttribute="top" id="OMD-Om-q0a"/>
|
||||
<constraint firstItem="2cy-48-y14" firstAttribute="leading" secondItem="nXZ-ID-zPe" secondAttribute="leading" id="Rdi-qM-E5h"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7ZM-sO-DrN" secondAttribute="trailing" id="jKQ-Mf-QQC"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="nXZ-ID-zPe" firstAttribute="top" secondItem="dAi-UV-jeN" secondAttribute="top" id="4vc-RU-Cmf"/>
|
||||
<constraint firstItem="nXZ-ID-zPe" firstAttribute="leading" secondItem="dAi-UV-jeN" secondAttribute="leading" constant="8" id="Doy-ty-3Bs"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nXZ-ID-zPe" secondAttribute="trailing" constant="8" id="XDT-nC-tbX"/>
|
||||
<constraint firstAttribute="bottom" secondItem="nXZ-ID-zPe" secondAttribute="bottom" id="YxX-2s-TRy"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="nameLabel" destination="GRm-Zh-qFB" id="FAv-Qp-MtC"/>
|
||||
<outlet property="timestampLabel" destination="MWr-1t-Ey5" id="gsL-WO-Jih"/>
|
||||
<outlet property="valueLabel" destination="7ZM-sO-DrN" id="Zfo-Xr-3Aw"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="IXb-tG-hee" firstAttribute="leading" secondItem="1tQ-UN-8eY" secondAttribute="leading" id="4NC-4R-iPX"/>
|
||||
<constraint firstItem="IXb-tG-hee" firstAttribute="top" secondItem="1tQ-UN-8eY" secondAttribute="top" id="53I-jk-VCB"/>
|
||||
<constraint firstItem="IXb-tG-hee" firstAttribute="trailing" secondItem="1tQ-UN-8eY" secondAttribute="trailing" id="Ibw-N8-rBc"/>
|
||||
<constraint firstItem="eD7-bx-SvD" firstAttribute="trailing" secondItem="1tQ-UN-8eY" secondAttribute="trailing" id="bgZ-et-vyL"/>
|
||||
<constraint firstItem="eD7-bx-SvD" firstAttribute="leading" secondItem="1tQ-UN-8eY" secondAttribute="leading" id="c8L-su-QJV"/>
|
||||
<constraint firstItem="eD7-bx-SvD" firstAttribute="top" secondItem="IXb-tG-hee" secondAttribute="bottom" id="f1S-tf-dZo"/>
|
||||
<constraint firstItem="1tQ-UN-8eY" firstAttribute="bottom" secondItem="eD7-bx-SvD" secondAttribute="bottom" id="qxF-LU-WwW"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="1tQ-UN-8eY"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="resetFaultsButton" destination="Txg-Ba-9sP" id="LFS-LX-DOR"/>
|
||||
<outlet property="startButton" destination="7gt-Oj-XNj" id="sXe-BK-gQu"/>
|
||||
<outlet property="stopButton" destination="1gY-X0-Fpq" id="ztF-bm-Nr0"/>
|
||||
<outlet property="tableView" destination="eD7-bx-SvD" id="Ddx-cc-Vzu"/>
|
||||
<segue destination="peV-M2-goO" kind="show" identifier="goToChannelView" id="dMS-g8-ECB"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ELU-S2-Sf9" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3141.5999999999999" y="-320.68965517241384"/>
|
||||
</scene>
|
||||
<!--Device Detail-->
|
||||
<scene sceneID="q7c-Eh-Thg">
|
||||
<objects>
|
||||
@@ -905,6 +1062,7 @@
|
||||
<connections>
|
||||
<outlet property="searchBar" destination="z2g-Ak-4Pp" id="XeB-mp-w39"/>
|
||||
<segue destination="eOb-fR-aFg" kind="show" identifier="openDeviceDetailView" id="wUb-ND-zk7"/>
|
||||
<segue destination="Kh2-JZ-Ct9" kind="show" identifier="openMaxWaterSystem" id="WBp-6T-fMO"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="uhB-7k-gae" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@@ -934,8 +1092,10 @@
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="9Om-lw-Jgn"/>
|
||||
<segue reference="4nz-VA-pdT"/>
|
||||
<segue reference="dMS-g8-ECB"/>
|
||||
<segue reference="wUb-ND-zk7"/>
|
||||
<segue reference="WBp-6T-fMO"/>
|
||||
<segue reference="bJo-JM-CaN"/>
|
||||
<segue reference="LUR-lb-5qK"/>
|
||||
<segue reference="qTd-vu-ryN"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
</document>
|
||||
|
||||
Reference in New Issue
Block a user