Contenidos
Servidor en Kotlin
Importar librerías
1 2 3 4 |
io.ktor:ktor-server-netty:1.6.7 io.ktor:ktor-gson:1.6.7 org.slf4j:slf4j-simple:2.0.0-alpha1 org.slf4j:slf4j-simple:1.7.32 |
Código del servidor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import io.ktor.application.* import io.ktor.http.* import io.ktor.request.* import io.ktor.response.* import io.ktor.routing.* import io.ktor.server.engine.* import io.ktor.server.netty.* import java.io.File fun main() { val server = embeddedServer(Netty, port = 6000) { routing { post("/send-message") { val receivedMessage = call.receiveText() println("Mensaje recibido: $receivedMessage") // Escribe los valores en un archivo writeToFile(receivedMessage) call.respond(HttpStatusCode.OK, "Mensaje recibido: $receivedMessage") } } } server.start(wait = true) } // Función para escribir en un archivo fun writeToFile(message: String) { val file = File("valores.txt") // Nombre del archivo donde se almacenarán los valores file.appendText("$message\n") // Agrega el nuevo valor al archivo (con un salto de línea) } |
Cliente en Swift para el Apple Watch que envía la fuerza (tres botones, uno para guardar la fuerza máxima junto con el texto en un fichero, otro para enviar todos los registros de fuerzas al servidor y el último para borrar el fichero con los valores almacenados)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
import SwiftUI import CoreMotion @main struct SensorApp: App { var body: some Scene { WindowGroup { SensorView() } } } struct SensorView: View { @State private var accelerationText = "Total Acceleration: 0.00 m/s²" @State private var forceText = "Force: 0.00 N" @State private var massText = "" @State private var additionalText = "" @State private var previousMass: Float = 0.0 let motionManager = CMMotionManager() let gravity = 9.81 var body: some View { VStack { Text(accelerationText) Text(forceText) HStack { VStack { TextField("Enter Mass", text: $massText) .padding() .background(Color.gray.opacity(0.2)) .cornerRadius(8) TextField("Enter Additional Text", text: $additionalText) .padding() .background(Color.gray.opacity(0.2)) .cornerRadius(8) } VStack { Button(action: { guard let mass = Float(massText) else { print("Enter a valid value for mass.") return } let totalAccelerationMS2 = calculateTotalAcceleration() let force = calculateForce(acceleration: totalAccelerationMS2, mass: mass) saveForceToFile("\(additionalText)-\(forceText)\n") }) { Text("Save Force to File") .padding() .foregroundColor(.white) .background(Color.blue) .cornerRadius(8) } Button(action: { sendFileContentToServer() }) { Text("Send File Content to Server") .padding() .foregroundColor(.white) .background(Color.blue) .cornerRadius(8) } Button(action: { deleteFile() createFileIfNeeded() }) { Text("Delete File") .padding() .foregroundColor(.white) .background(Color.red) .cornerRadius(8) } } } } .onAppear { startAccelerometer() } .onDisappear { stopAccelerometer() } } func startAccelerometer() { if motionManager.isAccelerometerAvailable { motionManager.accelerometerUpdateInterval = 0.1 motionManager.startAccelerometerUpdates(to: OperationQueue.main) { [self] data, error in guard let acceleration = data?.acceleration else { return } let totalAccelerationG = sqrt(pow(acceleration.x, 2) + pow(acceleration.y, 2) + pow(acceleration.z, 2)) let totalAccelerationMS2 = totalAccelerationG * gravity accelerationText = String(format: "Total Acceleration: %.2f m/s²", totalAccelerationMS2) guard let mass = Float(massText) else { return } if mass != previousMass { forceText = "Force: 0.00 N" previousMass = mass } let force = calculateForce(acceleration: totalAccelerationMS2, mass: mass) if force > Float(forceText.components(separatedBy: " ")[1]) ?? 0 { forceText = String(format: "Force: %.2f N", force) } } } } func stopAccelerometer() { motionManager.stopAccelerometerUpdates() } func calculateForce(acceleration: Double, mass: Float) -> Float { return Float(acceleration * Double(mass)) } func sendForceToServer(_ forceValue: String) { let messageToSend = forceValue if let url = URL(string: "http://192.168.1.55:6000/send-message") { var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/text", forHTTPHeaderField: "Content-Type") let data = messageToSend.data(using: .utf8) request.httpBody = data let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error.localizedDescription)") } else if let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) { print("Force message sent successfully to the server") } else { print("Error sending force message to the server") } } task.resume() } else { print("Invalid URL") } } func calculateTotalAcceleration() -> Double { guard let data = motionManager.accelerometerData else { return 0 } let acceleration = data.acceleration let totalAccelerationG = sqrt(pow(acceleration.x, 2) + pow(acceleration.y, 2) + pow(acceleration.z, 2)) let totalAccelerationMS2 = totalAccelerationG * gravity return totalAccelerationMS2 } func saveForceToFile(_ forceValue: String) { let fileName = "ForceValue.txt" let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectory.appendingPathComponent(fileName) do { let fileHandle = try FileHandle(forWritingTo: fileURL) fileHandle.seekToEndOfFile() fileHandle.write(forceValue.data(using: .utf8)!) fileHandle.closeFile() print("Force value added to file: \(fileURL.path)") } catch { print("Error adding force value to file: \(error.localizedDescription)") } } func sendFileContentToServer() { let fileName = "ForceValue.txt" let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectory.appendingPathComponent(fileName) do { let fileContent = try String(contentsOf: fileURL) sendForceToServer(fileContent) } catch { print("Error reading file content: \(error.localizedDescription)") } } func deleteFile() { let fileName = "ForceValue.txt" let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectory.appendingPathComponent(fileName) do { try FileManager.default.removeItem(at: fileURL) print("File deleted successfully.") } catch { print("Error deleting file: \(error.localizedDescription)") } } func createFileIfNeeded() { let fileName = "ForceValue.txt" let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectory.appendingPathComponent(fileName) if !FileManager.default.fileExists(atPath: fileURL.path) { FileManager.default.createFile(atPath: fileURL.path, contents: nil, attributes: nil) print("File created: \(fileURL.path)") } else { print("File already exists.") } } } |