diff --git a/SenzorDataCollectorApp.xcodeproj/project.pbxproj b/SenzorDataCollectorApp.xcodeproj/project.pbxproj index 83fc2645bd86813415bf4462ded5e4bd0f85d000..fc1a32f4d7e8fce98d2672a16a0541fe6c3afc97 100644 --- a/SenzorDataCollectorApp.xcodeproj/project.pbxproj +++ b/SenzorDataCollectorApp.xcodeproj/project.pbxproj @@ -7,9 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 744D73852A02626D00D47BB9 /* NotifyListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 744D73842A02626D00D47BB9 /* NotifyListener.swift */; }; - 745B31922AFBFAEB005AB51F /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745B31912AFBFAEB005AB51F /* NotificationObserver.swift */; }; - 745B31942AFBFEC9005AB51F /* UserNotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 745B31932AFBFEC9005AB51F /* UserNotificationObserver.swift */; }; 746FF1C82B5C0D1C00716162 /* StartingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746FF1C72B5C0D1C00716162 /* StartingView.swift */; }; 746FF1CA2B5C0D4A00716162 /* ServerConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746FF1C92B5C0D4A00716162 /* ServerConnectionView.swift */; }; 746FF1CD2B5D5DE900716162 /* ServerCommunicationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746FF1CC2B5D5DE900716162 /* ServerCommunicationManager.swift */; }; @@ -48,9 +45,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 744D73842A02626D00D47BB9 /* NotifyListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyListener.swift; sourceTree = "<group>"; }; - 745B31912AFBFAEB005AB51F /* NotificationObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationObserver.swift; sourceTree = "<group>"; }; - 745B31932AFBFEC9005AB51F /* UserNotificationObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationObserver.swift; sourceTree = "<group>"; }; 746FF1C72B5C0D1C00716162 /* StartingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartingView.swift; sourceTree = "<group>"; }; 746FF1C92B5C0D4A00716162 /* ServerConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnectionView.swift; sourceTree = "<group>"; }; 746FF1CC2B5D5DE900716162 /* ServerCommunicationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerCommunicationManager.swift; sourceTree = "<group>"; }; @@ -127,9 +121,7 @@ 74D6D60729FD23AE006DBC2D /* ContentView.swift */, 74D6D63829FD4AF5006DBC2D /* ExportToJson.swift */, 74D6D63C29FDA6FA006DBC2D /* FilePicker.swift */, - 745B31912AFBFAEB005AB51F /* NotificationObserver.swift */, 74D6D63A29FD6D45006DBC2D /* NotificationSender.swift */, - 744D73842A02626D00D47BB9 /* NotifyListener.swift */, 74D6D60E29FD23AF006DBC2D /* Persistence.swift */, 74D6D63629FD2756006DBC2D /* Sensors.swift */, 74D6D60529FD23AE006DBC2D /* SensorDataCollectorAppApp.swift */, @@ -138,7 +130,6 @@ 746FF1C92B5C0D4A00716162 /* ServerConnectionView.swift */, 746FF1C72B5C0D1C00716162 /* StartingView.swift */, 74ED5D592B712697006F015E /* Timer.swift */, - 745B31932AFBFEC9005AB51F /* UserNotificationObserver.swift */, 74D6D60929FD23AF006DBC2D /* Assets.xcassets */, 74D6D60B29FD23AF006DBC2D /* Preview Content */, 74D6D61029FD23AF006DBC2D /* SenzorDataCollectorApp.xcdatamodeld */, @@ -303,7 +294,6 @@ files = ( 74D6D63D29FDA6FA006DBC2D /* FilePicker.swift in Sources */, 74D6D63929FD4AF6006DBC2D /* ExportToJson.swift in Sources */, - 744D73852A02626D00D47BB9 /* NotifyListener.swift in Sources */, 74D6D63729FD2756006DBC2D /* Sensors.swift in Sources */, 74D6D60F29FD23AF006DBC2D /* Persistence.swift in Sources */, 74D6D63B29FD6D45006DBC2D /* NotificationSender.swift in Sources */, @@ -314,9 +304,7 @@ 74D6D60629FD23AE006DBC2D /* SensorDataCollectorAppApp.swift in Sources */, 746FF1CD2B5D5DE900716162 /* ServerCommunicationManager.swift in Sources */, 74D6D63529FD2536006DBC2D /* SensorDetailView.swift in Sources */, - 745B31922AFBFAEB005AB51F /* NotificationObserver.swift in Sources */, 746FF1C82B5C0D1C00716162 /* StartingView.swift in Sources */, - 745B31942AFBFEC9005AB51F /* UserNotificationObserver.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -476,10 +464,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SenzorDataCollectorApp/Preview Content\""; - DEVELOPMENT_TEAM = DPLDX294ZP; + DEVELOPMENT_TEAM = QX2PWGX3RS; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SenzorDataCollectorApp/Info.plist; @@ -488,6 +477,7 @@ INFOPLIST_KEY_NSFileProviderDomainUsageDescription = "The app needs it to save files"; INFOPLIST_KEY_NSFileProviderPresenceUsageDescription = "The app needs it to save files"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSLocalNetworkUsageDescription = ""; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "The needs ot use senzor data"; INFOPLIST_KEY_NSMotionUsageDescription = "App mesasures sensors"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -501,8 +491,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "hu.itk.ppke.SenzorDataCollectorApp-"; + PRODUCT_BUNDLE_IDENTIFIER = hu.itk.ppke.senzor; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -514,10 +505,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"SenzorDataCollectorApp/Preview Content\""; - DEVELOPMENT_TEAM = DPLDX294ZP; + DEVELOPMENT_TEAM = QX2PWGX3RS; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SenzorDataCollectorApp/Info.plist; @@ -526,6 +518,7 @@ INFOPLIST_KEY_NSFileProviderDomainUsageDescription = "The app needs it to save files"; INFOPLIST_KEY_NSFileProviderPresenceUsageDescription = "The app needs it to save files"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSLocalNetworkUsageDescription = ""; INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "The needs ot use senzor data"; INFOPLIST_KEY_NSMotionUsageDescription = "App mesasures sensors"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -539,8 +532,9 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "hu.itk.ppke.SenzorDataCollectorApp-"; + PRODUCT_BUNDLE_IDENTIFIER = hu.itk.ppke.senzor; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/Contents.json b/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..08066fe929bf67ceb29d36cbae9c4f1f014102c8 --- /dev/null +++ b/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/Contents.json @@ -0,0 +1,12 @@ +{ + "data" : [ + { + "filename" : "mixkit-correct-answer-tone-2870.wav", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/mixkit-correct-answer-tone-2870.wav b/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/mixkit-correct-answer-tone-2870.wav new file mode 100644 index 0000000000000000000000000000000000000000..88a18e152d96c2c45c4840a70f8f55f19c892dcd Binary files /dev/null and b/SenzorDataCollectorApp/Assets.xcassets/1.mp3.dataset/mixkit-correct-answer-tone-2870.wav differ diff --git a/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/Contents.json b/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..bb05a93db6089e37a1d4226c4f0c1f639fa9b4a8 --- /dev/null +++ b/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/Contents.json @@ -0,0 +1,12 @@ +{ + "data" : [ + { + "filename" : "mixkit-elevator-tone-2863.wav", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/mixkit-elevator-tone-2863.wav b/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/mixkit-elevator-tone-2863.wav new file mode 100644 index 0000000000000000000000000000000000000000..ad7296faa856eec960e5906b6db9145b91376bd5 Binary files /dev/null and b/SenzorDataCollectorApp/Assets.xcassets/2.mp3.dataset/mixkit-elevator-tone-2863.wav differ diff --git a/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/Contents.json b/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..c350c1decf705e960402ff748210b4d470ba7008 --- /dev/null +++ b/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/Contents.json @@ -0,0 +1,12 @@ +{ + "data" : [ + { + "filename" : "WCSC5KW-message-notification.mp3", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/WCSC5KW-message-notification.mp3 b/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/WCSC5KW-message-notification.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..48bfbddaae47b913d0be2f81551798668c9613e9 Binary files /dev/null and b/SenzorDataCollectorApp/Assets.xcassets/3.mp3.dataset/WCSC5KW-message-notification.mp3 differ diff --git a/SenzorDataCollectorApp/ContentView.swift b/SenzorDataCollectorApp/ContentView.swift index a3e055acb9a60ab66dfae983120bb6164b3361c4..4492b244b9ab1fe2a58e2ae66d5a505ac394fc38 100644 --- a/SenzorDataCollectorApp/ContentView.swift +++ b/SenzorDataCollectorApp/ContentView.swift @@ -30,14 +30,17 @@ struct ContentView: View { @State var countdown: Int = 5 @State var timer: Timer? + @State var updateInterval = 1 + let values = [1, 5, 10, 30] + @State var dataColl = false @StateObject var sensor = SensorCollector(activeSensorList: []) @State var fileLocations: [URL] = [] @State var MeasurementID: Int - @ObservedObject var notificationManager = NotificationManager() - var notificationObserver = UserNotificationObserver.shared +// @ObservedObject var notificationManager = NotificationManager() +// var notificationObserver = UserNotificationObserver.shared let activityManager = CMMotionActivityManager() @@ -50,6 +53,16 @@ struct ContentView: View { var body: some View { NavigationView { VStack{ + + Picker("Select Value", selection: $updateInterval) { + ForEach(values, id: \.self) { value in + Text("\(value)") + } + } + .pickerStyle(SegmentedPickerStyle()) + +// Text("Selected Value: \(updateInterval)") + ForEach($sensor.activeSensorsList, id: \.self) { $list in HStack{ Text(list.sensorName) @@ -73,7 +86,7 @@ struct ContentView: View { .padding() .onChange(of: dataColl){value in if value { - sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) + sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter, updateIntervalModifier: Float(updateInterval)) }else{//if we toggled off the toggle: //stop reading from sensors sensor.stopAllRecording(motionManager: motionManager, altimeter: altimeter) @@ -102,9 +115,9 @@ struct ContentView: View { } .padding() - List(notificationManager.notifications, id: \.identifier) { notification in - Text(notification.content.title) - } +// List(notificationManager.notifications, id: \.identifier) { notification in +// Text(notification.content.title) +// } //---------------- - --- select the location of the saved files ------------- Button("Select destination") { @@ -161,12 +174,12 @@ struct ContentView: View { .frame(maxHeight: 200) }.onAppear{ //let notificationObserver = UserNotificationObserver.shared - notificationObserver.startObservingNotifications() - - - notificationManager.requestNotificationPermissions() - notificationManager.observeNotifications() - print("init!") +// notificationObserver.startObservingNotifications() +// +// +// notificationManager.requestNotificationPermissions() +// notificationManager.observeNotifications() +// print("init!") } .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in diff --git a/SenzorDataCollectorApp/ExportToJson.swift b/SenzorDataCollectorApp/ExportToJson.swift index 88a26e9764c58b21caa68d822fbbb514c074cd5f..ea7498d66d3dc8a93b6edddcb3c5a107072275fd 100644 --- a/SenzorDataCollectorApp/ExportToJson.swift +++ b/SenzorDataCollectorApp/ExportToJson.swift @@ -11,7 +11,7 @@ import SwiftUI import Foundation import UniformTypeIdentifiers import UIKit -//calls crate jsonfile to the specific sensor - sensorData - has to be the name of the list where the data is stored +//calls crate json file to the specific sensor - sensorData - has to be the name of the list where the data is stored //called by Sensors -> exportAllSensorToJson func exportToJSON(fileLocations: inout [URL], sensorData: [(timeInMiliSec: Int, (x: Double, y: Double, z: Double))], @@ -24,6 +24,7 @@ func exportToJSON(fileLocations: inout [URL], } //create the json file +//This function was written by ChatGPT (3.5) func createJSONFile(FileName: String, SensorName: String, Data: [(timeInMiliSec: Int, (x: Double, y: Double, z: Double))], fileLocationURL: URL, deviceID: String, manager: ServerCommunicationManager) throws -> URL { let jsonData: [[String: Any]] = Data.map { tuple in return [ @@ -50,10 +51,6 @@ func createJSONFile(FileName: String, SensorName: String, Data: [(timeInMiliSec: fileURL = fileLocationURL.appendingPathComponent("\(FileName).json") try jsonDataObj.write(to: fileURL, options: .atomic) - //Server file sending -// manager.sendMessage(type: "json", filename: FileName, jsonData: jsonString) -// print("Export to Json called manager Json message sent: filename \(FileName), JsonData: \(jsonData)") - do { let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) manager.uploadJsonFile(deviceID: deviceID, jsonData: jsonData, filename: FileName) diff --git a/SenzorDataCollectorApp/FilePicker.swift b/SenzorDataCollectorApp/FilePicker.swift index 55747616a11c48cc179b6a4edd09a29712627a8a..f206377d5374e0e28df460e424e0e8db28813a14 100644 --- a/SenzorDataCollectorApp/FilePicker.swift +++ b/SenzorDataCollectorApp/FilePicker.swift @@ -5,10 +5,8 @@ // Created by Miklósi Máté on 2023. 04. 29.. // - -// THIS IS JUST A PLAYGROUND FILE, TO TEST VIEWS - - +// THIS IS JUST A PLAYGROUND FILE, TO TEST VIEWS +// Written By chatGPT(3.5) import SwiftUI import UIKit diff --git a/SenzorDataCollectorApp/Info.plist b/SenzorDataCollectorApp/Info.plist index 57a546a1b27cb6fb92477a6cc095795a6dcba095..fd4062296392fa9425f636ee3ba6990298b6344d 100644 --- a/SenzorDataCollectorApp/Info.plist +++ b/SenzorDataCollectorApp/Info.plist @@ -12,7 +12,5 @@ <string>processing</string> <string>remote-notification</string> </array> - <key>NSLocalNetworkUsageDescription</key> - <string></string> </dict> </plist> diff --git a/SenzorDataCollectorApp/NotificationObserver.swift b/SenzorDataCollectorApp/NotificationObserver.swift deleted file mode 100644 index 66731645440c7ce0e01d0edf237f50d2afe0c616..0000000000000000000000000000000000000000 --- a/SenzorDataCollectorApp/NotificationObserver.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// NotificationObserver.swift -// SenzorDataCollectorApp -// -// Created by Miklósi Máté on 08/11/2023. -// - -import Foundation - -// -//class NotificationObserver { -// init() { -// NotificationCenter.default.addObserver(self, selector: #selector(handleNotification(_:)), name: nil, object: nil) -// } -// -// deinit { -// NotificationCenter.default.removeObserver(self) -// } -// -// @objc func handleNotification(_ notification: Notification) { -// // Print out notification details to the console -// //print("Received notification: \(notification.name.rawValue)") -// -// if let userInfo = notification.userInfo { -// for (key, value) in userInfo { -// print("\(key): \(value)") -// } -// } -// } -//} -// -//// Usage -//let observer = NotificationObserver() - -// To stop observing notifications (optional) -// observer = nil diff --git a/SenzorDataCollectorApp/NotificationSender.swift b/SenzorDataCollectorApp/NotificationSender.swift index b225e606fefc9e84d38787014b692a1e52c2a155..36cb681c40210eb88f1c797b6d344b872a0b75b2 100644 --- a/SenzorDataCollectorApp/NotificationSender.swift +++ b/SenzorDataCollectorApp/NotificationSender.swift @@ -5,6 +5,8 @@ // Created by Miklósi Máté on 2023. 04. 29.. // // +// The final flow does not use this file, only the prototype (ContentView) +// this class was written by chatGPT import Foundation import UserNotifications diff --git a/SenzorDataCollectorApp/Persistence.swift b/SenzorDataCollectorApp/Persistence.swift index ce4bd174c718397d18c8b1dc12d91966432468c2..5cb55e8f558dda74a8111e6ee538ecabc4dfec58 100644 --- a/SenzorDataCollectorApp/Persistence.swift +++ b/SenzorDataCollectorApp/Persistence.swift @@ -4,6 +4,7 @@ // // Created by Miklósi Máté on 2023. 04. 29.. // +// based on https://www.youtube.com/watch?v=Pd90OTQiOaA&t=1240s import CoreData @@ -20,8 +21,6 @@ struct PersistenceController { do { try viewContext.save() } catch { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } @@ -37,17 +36,6 @@ struct PersistenceController { } container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - - /* - Typical reasons for an error here include: - * The parent directory does not exist, cannot be created, or disallows writing. - * The persistent store is not accessible, due to permissions or data protection when the device is locked. - * The device is out of space. - * The store could not be migrated to the current model version. - Check the error message to determine what the actual problem was. - */ fatalError("Unresolved error \(error), \(error.userInfo)") } }) diff --git a/SenzorDataCollectorApp/SensorDataCollectorAppApp.swift b/SenzorDataCollectorApp/SensorDataCollectorAppApp.swift index bce7f117be0065f6b80429d77d115cb6ec48f597..7f83f7f86524cc71fde4400b706a8be115f7c874 100644 --- a/SenzorDataCollectorApp/SensorDataCollectorAppApp.swift +++ b/SenzorDataCollectorApp/SensorDataCollectorAppApp.swift @@ -18,8 +18,9 @@ struct SensorDataCollectorAppApp: App { var body: some Scene { WindowGroup { - StartingView(customTimer: timer) + StartingView(customTimer: timer) // ContentView(MeasurementID: 1) +// In the prototype only contentView was present .environment(\.managedObjectContext, persistenceController.container.viewContext) .environmentObject(timer) } diff --git a/SenzorDataCollectorApp/SensorDetailView.swift b/SenzorDataCollectorApp/SensorDetailView.swift index bf250815acecda4b152887650fd4165d536d801f..e49d1c9236a91da96849266a762b0b08925196fc 100644 --- a/SenzorDataCollectorApp/SensorDetailView.swift +++ b/SenzorDataCollectorApp/SensorDetailView.swift @@ -1,5 +1,5 @@ // -// SensorDetailVIew.swift +// SensorDetailView.swift // SensorDataCollectorApp // // Created by Miklósi Máté on 2023. 04. 29.. @@ -32,7 +32,7 @@ struct SensorDetailView: View { } } -struct SensorDetailVIew_Previews: PreviewProvider { +struct SensorDetailView_Previews: PreviewProvider { static var previews: some View { SensorDetailView(x: .constant(1),y: .constant(2),z: .constant(2),sensorName: .constant("accelometer")) } diff --git a/SenzorDataCollectorApp/Sensors.swift b/SenzorDataCollectorApp/Sensors.swift index 7031147a39780d640c3535caa6908282fbba522f..2507cc9372951132e385a33ec98a60d5fd5e466e 100644 --- a/SenzorDataCollectorApp/Sensors.swift +++ b/SenzorDataCollectorApp/Sensors.swift @@ -31,9 +31,7 @@ struct MeasuringSensors: Hashable, Identifiable{ enum Sensors: String, CaseIterable { case acc = "Accelerometer" case gyro = "Gyroscope" -// case alt = "Altimeter" case mag = "Magnetometer" -// case light = "Light Sensor" } @@ -41,12 +39,12 @@ enum Sensors: String, CaseIterable { class SensorCollector: ObservableObject { @Published var activeSensorsList: [MeasuringSensors] + //data queue, for temporary storage for the sensor data - until JSON export let accDataQueue = OperationQueue() let gyroDataQueue = OperationQueue() let magDataQueue = OperationQueue() let altDataQueue = OperationQueue() -// let lightDataQueue = OperationQueue() var sensorDataQueues: [OperationQueue] init(activeSensorList: [MeasuringSensors]) { @@ -58,7 +56,6 @@ class SensorCollector: ObservableObject { func initAllActiveSensorsList(){ for sensor in Sensors.allCases { activeSensorsList.append(MeasuringSensors(sensorName: sensor.rawValue, isSensorActive: false)) - //print("i just added \(sensor.rawValue)") } } func clearAllVectors() { @@ -69,11 +66,13 @@ class SensorCollector: ObservableObject { } } - func startAllRecording(motionManager: CMMotionManager, altimeter: CMAltimeter){ + func startAllRecording(motionManager: CMMotionManager, altimeter: CMAltimeter, updateIntervalModifier: Float){ + motionManager.deviceMotionUpdateInterval = TimeInterval(updateIntervalModifier / 50.0) + print("Motion Update Interval: $motionManager.deviceMotionUpdateInterval") + accStartRecording(motionManager: motionManager) gyroStartRecording(motionManager: motionManager) magStartRecording(motionManager: motionManager) -// altStartRecording(altimeter: altimeter) } @@ -81,53 +80,18 @@ class SensorCollector: ObservableObject { motionManager.stopAccelerometerUpdates() motionManager.stopGyroUpdates() motionManager.stopMagnetometerUpdates() -// altimeter.stopRelativeAltitudeUpdates() print("Sensors stopped all recording") for index in 0..<activeSensorsList.count { activeSensorsList[index].isSensorActive = false } } - - - // ------------------------------------------- A L T I T U D E ------------------------------------------- -// func altStartRecording(altimeter: CMAltimeter) { -// if CMAltimeter.isRelativeAltitudeAvailable() { -// -// for index in 0..<activeSensorsList.count { -// if activeSensorsList[index].sensorName == Sensors.alt.rawValue { -// activeSensorsList[index].isSensorActive = true -// } -// } -// -// altimeter.startRelativeAltitudeUpdates(to: altDataQueue) { (altimeterData, error) in -// if let altimeterData = altimeterData { -// let pressure = altimeterData.pressure.doubleValue -// let rel_altitude = altimeterData.relativeAltitude.doubleValue -// let altTimestampedTuple = (Int(Date().timeIntervalSince1970 * 1000), (x: rel_altitude, y: pressure, z: 0.0)) -// -// DispatchQueue.main.async { -// if let index = self.activeSensorsList.firstIndex(where: { $0.sensorName == Sensors.alt.rawValue }) { -// self.activeSensorsList[index].sensorData.append(altTimestampedTuple) -// } -// } -// } else { -// print("Altitude data not available or there was an error: \(error?.localizedDescription ?? "Unknown error")") -// } -// } -// } else { -// print("Altimeter not available on this device.") -// } -// } - - - - +// This function was corrected by ChatGPT // ------------------------------------------- A C C E L E R O M E T E R ------------------------------------------- func accStartRecording(motionManager: CMMotionManager){ //if there is an acc.meter available: if(motionManager.isAccelerometerAvailable){ //set accelerometer update frequency - to the maximum that the device is capable - motionManager.accelerometerUpdateInterval = motionManager.deviceMotionUpdateInterval + motionManager.accelerometerUpdateInterval = (motionManager.deviceMotionUpdateInterval) //start accelerometer update: motionManager.startAccelerometerUpdates(to: accDataQueue){ (accMeterData, error) in @@ -149,22 +113,20 @@ class SensorCollector: ObservableObject { } } // ------------------------------------------- G Y R O S C O P E ------------------------------------------- - + // This function was corrected by ChatGPT func gyroStartRecording(motionManager: CMMotionManager){ //if there is a gyroscope if(motionManager.isGyroAvailable){ - for index in 0..<activeSensorsList.count { if activeSensorsList[index].sensorName == "Gyroscope" { activeSensorsList[index].isSensorActive = true } } //set gyroscope update frequency to the supported maximum - motionManager.gyroUpdateInterval = motionManager.deviceMotionUpdateInterval + motionManager.gyroUpdateInterval = (motionManager.deviceMotionUpdateInterval) //start gyroscope update: motionManager.startGyroUpdates(to: gyroDataQueue){ (gyroData, error) in - //optional binding check, if gyroData is null if let gyroData = gyroData { let gyro = gyroData.rotationRate @@ -184,6 +146,7 @@ class SensorCollector: ObservableObject { } // ------------------------------------------- M A G N E T O M E T E R ------------------------------------------- + // This function was corrected by ChatGPT func magStartRecording(motionManager: CMMotionManager){ for index in 0..<activeSensorsList.count { @@ -191,10 +154,8 @@ class SensorCollector: ObservableObject { activeSensorsList[index].isSensorActive = true } } - - if(motionManager.isMagnetometerAvailable){ - motionManager.magnetometerUpdateInterval = motionManager.deviceMotionUpdateInterval + motionManager.magnetometerUpdateInterval = (motionManager.deviceMotionUpdateInterval) //start magnetometer update: motionManager.startMagnetometerUpdates(to: gyroDataQueue){ (magData, error) in diff --git a/SenzorDataCollectorApp/ServerCommunicationManager.swift b/SenzorDataCollectorApp/ServerCommunicationManager.swift index 39b3732fc2711b26be0c18c618663b0c4a02d292..c6a544ca2605a24b520a390e4b862721847c445a 100644 --- a/SenzorDataCollectorApp/ServerCommunicationManager.swift +++ b/SenzorDataCollectorApp/ServerCommunicationManager.swift @@ -5,6 +5,8 @@ // Created by Miklósi Máté on 21/01/2024. // // ServerCommunicationManager.swift +// This class was mainly written By ChatGPT (3.5) + import Foundation @@ -47,7 +49,7 @@ class ServerCommunicationManager: ObservableObject { task.resume() } - +// -------- MESSAGE SENDING ---------------- func sendMessage(type: String, filename: String="", jsonData: String = "") { guard let port = Int(portNumber), !hostName.isEmpty else { serverResponse = "Invalid Port Number or Host" @@ -76,13 +78,14 @@ class ServerCommunicationManager: ObservableObject { } }.resume() } - + // -------- ------------------- ---------------- RESPONSE HANDLE -------------- ---------------- func handleResponse(_ response: String?, type: String) { guard let response = response else { self.serverResponse = "Empty response" return } do { + // -------- ------------------- AM I OK -------------- ---------------- if type == "am-i-ok" { serverResponse = "init response: \(response)" if let data = response.data(using: .utf8), @@ -100,7 +103,7 @@ class ServerCommunicationManager: ObservableObject { serverResponse = "Invalid JSON format in am-i-ok response" } } - + // -------- ------------------- INIT -------------- ---------------- if type == "init" { serverResponse = "init response: \(response)" if let data = response.data(using: .utf8), @@ -128,7 +131,7 @@ class ServerCommunicationManager: ObservableObject { self.serverResponse = "Error decoding JSON response: \(error.localizedDescription)" } } - + // -------- ------------------- UPDATE SERVER CONFIG -------------- ---------------- private func updateServerConfig(_ config: [String: String]) { if let numberOfMeasurementsStr = config["NumberOfMeasurements"], let numberOfMeasurements = Int(numberOfMeasurementsStr) { @@ -156,7 +159,7 @@ class ServerCommunicationManager: ObservableObject { state = "Init" populateTimerList() } - + // -------- ------------------- POPULATE TIMER LIST -------------- ---------------- func populateTimerList(){ timerIntervalValues.removeAll() for _ in 0..<self.numberOfMeasurements { diff --git a/SenzorDataCollectorApp/ServerConnectionView.swift b/SenzorDataCollectorApp/ServerConnectionView.swift index ff1ca1efe9508dfc72cc6fb72bca1561b677f3ff..c9395d5d8706c75b97fcded8f709c4f65746fda3 100644 --- a/SenzorDataCollectorApp/ServerConnectionView.swift +++ b/SenzorDataCollectorApp/ServerConnectionView.swift @@ -4,6 +4,7 @@ // // Created by Miklósi Máté on 20/01/2024. // +// This view was written (and corrected) by Chat GPT, with many iteration. import Foundation import SwiftUI diff --git a/SenzorDataCollectorApp/StartingView.swift b/SenzorDataCollectorApp/StartingView.swift index 804530ddd0d0e86f031637d089983df5c8401928..dd58778b6807a360a9b7ad4caab5e012fb3f8cd9 100644 --- a/SenzorDataCollectorApp/StartingView.swift +++ b/SenzorDataCollectorApp/StartingView.swift @@ -19,7 +19,7 @@ struct StartingView: View { //----------SERVER CONNECTION SETTINGS AND VARS ----------------------------------------------- @State private var isServerSettingsSheetPresented = false @StateObject private var manager = ServerCommunicationManager() - @State private var iterationCount = 0 + @State private var iterationCount = 1 @State var displayText = "" @State var first_open = true @State private var shouldStartRecording = false @@ -31,6 +31,7 @@ struct StartingView: View { //----------MEASURMENT SETUP AND VARS --------------------------------------------------------- @State var demostart = false + @State var test_sheet = false @State var sensorDetailSheetPresented = false @State var showingFilePicker = false @State var selectedFolder: URL? @@ -39,6 +40,7 @@ struct StartingView: View { @StateObject var sensor = SensorCollector(activeSensorList: []) let motionManager = CMMotionManager() + let altimeter = CMAltimeter() @State var fileLocations: [URL] = [] @@ -62,18 +64,22 @@ struct StartingView: View { setNextMeasurement() }.opacity(debug ? 0 : 1) +// Toggle("data collection:",isOn: $dataColl) +// .padding() +// .onChange(of: dataColl){value in +// if value { +// sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) +// }else{//if we toggled off the toggle: +// //stop reading from sensors +// sensor.stopAllRecording(motionManager: motionManager, altimeter: altimeter) +// } +// } Button("Start Iterations") { setNextMeasurement() - sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) + sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter, updateIntervalModifier: 1) customTimer.startTimer() }.padding().disabled(manager.state != "Ready").opacity(debug ? 0 : 1) -// Button("STOP Iterations") { -// customTimer.stopTimer() -// sensor.stopAllRecording(motionManager: motionManager, altimeter: altimeter) -// -// }.padding().opacity(debug ? 0 : 1) - Text("\(manager.numberOfMeasurements - manager.timerIntervalValues.count >= 0 ? "\(manager.numberOfMeasurements - manager.timerIntervalValues.count)/\(manager.numberOfMeasurements)" : "Not initialised")") .padding() @@ -138,7 +144,7 @@ struct StartingView: View { //----------------------------- DEVICE ID --------------------------------- .navigationBarItems( leading: Button(action: { - sensorDetailSheetPresented = true + first_open = true }) { Text("\(manager.deviceID)") } @@ -218,25 +224,23 @@ struct StartingView: View { .textFieldStyle(RoundedBorderTextFieldStyle()) .padding(.vertical) }.padding().opacity(manager.state == "Ready" ? 0 : 1) + Button("Open test sheet"){ + first_open = false + test_sheet = true + }.padding() + }) + .sheet(isPresented: $test_sheet, content: { + ContentView( + MeasurementID: 1 + ) }) //----------------------------- TIMER REFRESH --------------------------------- .onReceive(timer){ _ in if customTimer.isStarted{ customTimer.updateTimer() print("Timer: \(customTimer.totalSeconds)") - -// if customTimer.totalSeconds == 2 { -// shouldStartRecording = true -// } } } -// .onReceive(Just(shouldStartRecording)) { _ in -// if shouldStartRecording { -// print("Starting measurements") -// sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) -// shouldStartRecording = false -// } -// } //----------------------------- NOTIFICAION HANDELING --------------------------------- .alert("\(manager.numberOfMeasurements - manager.timerIntervalValues.count >= -1 ? "\(manager.numberOfMeasurements - manager.timerIntervalValues.count)/\(manager.numberOfMeasurements)" : "Not initialised") Measurement", isPresented: $customTimer.isFinished) { Button(manager.timerIntervalValues.count == 0 ? "End" : "Next" ,role: .cancel){ @@ -245,10 +249,11 @@ struct StartingView: View { sensor.stopAllRecording(motionManager: motionManager, altimeter: altimeter) saveAllToJson() - setNextMeasurement() if manager.timerIntervalValues.count != 0 { - sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) + setNextMeasurement() + sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter, updateIntervalModifier: 1) customTimer.startTimer() + iterationCount += 1 } } Button("Stop", role: .destructive){ @@ -264,7 +269,7 @@ struct StartingView: View { sensor.stopAllRecording(motionManager: motionManager, altimeter: altimeter) setNextMeasurement() if customTimer.totalSeconds != 0 { - sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter) + sensor.startAllRecording(motionManager: motionManager, altimeter: altimeter, updateIntervalModifier: 1) customTimer.startTimer() } } diff --git a/SenzorDataCollectorApp/Timer.swift b/SenzorDataCollectorApp/Timer.swift index 7238249783672b49ab2ffdeb68362765284388c1..5d36cc3ef7d3630f1e415feef5e39930606250da 100644 --- a/SenzorDataCollectorApp/Timer.swift +++ b/SenzorDataCollectorApp/Timer.swift @@ -3,7 +3,7 @@ // SenzorDataCollectorApp // // Created by Miklósi Máté on 05/02/2024. -// +// Based on https://www.youtube.com/watch?v=Pd90OTQiOaA&t=1240s import SwiftUI class CustomTimer: NSObject,ObservableObject, UNUserNotificationCenterDelegate { @@ -61,7 +61,7 @@ class CustomTimer: NSObject,ObservableObject, UNUserNotificationCenterDelegate { content.title = "Measurement" content.subtitle = "Click OK to stop this measurement" content.sound = UNNotificationSound.default - + let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(staticTotalSeconds), repeats: false)) UNUserNotificationCenter.current().add(request) diff --git a/SenzorDataCollectorApp/UserNotificationObserver.swift b/SenzorDataCollectorApp/UserNotificationObserver.swift index 865458ca60e7b18de2efd5cea7c2d77a83776949..953009aff899f0d1f36381050c8f987123a06dfc 100644 --- a/SenzorDataCollectorApp/UserNotificationObserver.swift +++ b/SenzorDataCollectorApp/UserNotificationObserver.swift @@ -1,59 +1,56 @@ -import Foundation -import UserNotifications - -class UserNotificationObserver: NSObject, UNUserNotificationCenterDelegate { - - static let shared = UserNotificationObserver() - - override init() { - super.init() - UNUserNotificationCenter.current().delegate = self - } - - func startObservingNotifications() { - // Request permission to receive notifications if needed - requestNotificationPermission() - } - - private func requestNotificationPermission() { - let center = UNUserNotificationCenter.current() - center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in - if granted { - // Permission granted, you can now handle notifications - print("hohohasfdhoasdfaohdsfasdf") - // Schedule a test notification (for testing purposes) - let content = UNMutableNotificationContent() - content.title = "Test Notification" - content.body = "This is a test notification." - let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) - let request = UNNotificationRequest(identifier: "testNotification", content: content, trigger: trigger) - center.add(request) { (error) in - if let error = error { - print("Error scheduling test notification: \(error)") - } - } - } else { - // Permission denied, handle this case - } - } - } - - // Implement the notification handling method - func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - let notification = response.notification - print("Received notification: \(notification.request.identifier)") - - // Print additional notification details - if let content = notification.request.content as? UNMutableNotificationContent { - print("Title: \(content.title)") - print("Body: \(content.body)") - - // Print any other relevant notification details here - } - - completionHandler() - } -} - -// Usage: -// You can start observing notifications by calling UserNotificationObserver.shared.startObservingNotifications() +//import Foundation +//import UserNotifications +// +//class UserNotificationObserver: NSObject, UNUserNotificationCenterDelegate { +// +// static let shared = UserNotificationObserver() +// +// override init() { +// super.init() +// UNUserNotificationCenter.current().delegate = self +// } +// +// func startObservingNotifications() { +// // Request permission to receive notifications if needed +// requestNotificationPermission() +// } +// +// private func requestNotificationPermission() { +// let center = UNUserNotificationCenter.current() +// center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in +// if granted { +// // Permission granted, you can now handle notifications +// print("hohohasfdhoasdfaohdsfasdf") +// // Schedule a test notification (for testing purposes) +// let content = UNMutableNotificationContent() +// content.title = "Test Notification" +// content.body = "This is a test notification." +// let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) +// let request = UNNotificationRequest(identifier: "testNotification", content: content, trigger: trigger) +// center.add(request) { (error) in +// if let error = error { +// print("Error scheduling test notification: \(error)") +// } +// } +// } else { +// // Permission denied, handle this case +// } +// } +// } +// +// // Implement the notification handling method +// func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { +// let notification = response.notification +// print("Received notification: \(notification.request.identifier)") +// +// // Print additional notification details +// if let content = notification.request.content as? UNMutableNotificationContent { +// print("Title: \(content.title)") +// print("Body: \(content.body)") +// +// // Print any other relevant notification details here +// } +// +// completionHandler() +// } +//}