Simple Controller UI/gRPC working

This commit is contained in:
Piv
2020-05-04 22:40:22 +09:30
parent ac80a24936
commit 9376bd70ed
7 changed files with 167 additions and 19 deletions

View File

@@ -0,0 +1,76 @@
//
// PiLoader.swift
// CarController
//
// Created by Michael Pivato on 4/5/20.
// Copyright © 2020 Michael Pivato. All rights reserved.
//
import Foundation
import SwiftUI
import GRPC
import NIO
class PiLoader: ObservableObject {
// Find a cleaner way to handle these properties
@Published var throttle: Float = 0.5
@Published var steering: Float = 0.5
let port: Int = 50051
var stopped = false
func makeClient(port: Int, group: EventLoopGroup) -> MotorControl_CarControlClient {
let channel = ClientConnection.insecure(group: group)
// TODO: Pass the host in based on the settings.
.connect(host: "10.0.0.55", port: port)
return MotorControl_CarControlClient(channel: channel)
}
func startUpdating() {
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try? group.syncShutdownGracefully()
}
let client = makeClient(port: self.port, group: group)
let options = CallOptions(timeout: .seconds(rounding: 10))
let call = client.stream_vehicle_2d(callOptions: options)
call.response.whenFailure { error in
print("RecordRoute Failed: \(error)")
self.stop()
}
call.status.whenComplete { _ in
print("Finished RecordRoute")
self.stop()
}
call.response.whenSuccess { summary in
print("Finished")
self.stop()
}
DispatchQueue.global(qos: .userInteractive).async{
// Running in background. Do the update thread stuff.
while (!self.stopped){
call.sendMessage(self.createProto(), promise: nil)
Thread.sleep(forTimeInterval: 0.2)
}
}
}
func stop(){
stopped = true
}
func createProto() -> MotorControl_Vehicle2DRequest {
return .with{
$0.throttle = .with{
$0.throttle = self.throttle
}
$0.steering = .with{
$0.steering = self.steering
}
}
}
}

View File

@@ -10,8 +10,9 @@ import Foundation
final class ServerData: ObservableObject{
// TODO: Find a way to save/represent this stuff in iOS settings (user can access via settings app).
// TODO: Find a way to save/represent this stuff in iOS settings/preferences (user can access via settings app).
// Then load the below values ar runtime, from settings.
// Ideally want to be able to open this settings page from within the app as well.
@Published var port: Int = 50051

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
</dict>
</array>
</dict>
</plist>

View File

@@ -10,25 +10,27 @@ import SwiftUI
struct SimpleControllerView: View {
@EnvironmentObject var server: ServerData
@State var throttle: Float = 0.5
@State var steering: Float = 0.5
// Need lazy so that we can initialise with local properties.
@ObservedObject var grpcController: PiLoader = PiLoader()
var body: some View {
HStack{
Slider(value: $throttle, in: 0...1){_ in
self.throttle = 0.5}
Slider(value: $grpcController.throttle, in: 0...1){_ in
self.grpcController.throttle = 0.5
}
.rotationEffect(.degrees(270))
Slider(value: $steering, in: 0...1){
_ in self.steering = 0.5
Slider(value: $grpcController.steering, in: 0...1){_ in
self.grpcController.steering = 0.5
}
}
.onAppear(){
// Start the gRPC updater. Should be in a separate class/struct to be easier to implement for SLAM Controller after.
self.grpcController.startUpdating()
}
.onDisappear(){
// Stop the gRPC updater.
self.grpcController.stop()
}
}
}