From 3c2bb10f0736e04bec8e21907bef9b889e75d328 Mon Sep 17 00:00:00 2001 From: suntao Date: Tue, 30 Mar 2021 14:23:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0ant+=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/{Cyp/Prefab.meta => Editor.meta} | 2 +- Assets/Editor/MyBuildPostprocessor.cs | 21 + Assets/Editor/MyBuildPostprocessor.cs.meta | 11 + Assets/Plugins/ANT_NET.dll | Bin 0 -> 97792 bytes Assets/Plugins/ANT_NET.dll.meta | 33 + .../Plugins/DSI_CP210xManufacturing_3_1.dll | Bin 0 -> 69632 bytes .../DSI_CP210xManufacturing_3_1.dll.meta | 27 + Assets/Plugins/DSI_SiUSBXp_3_1.dll | Bin 0 -> 90112 bytes Assets/Plugins/DSI_SiUSBXp_3_1.dll.meta | 27 + Assets/Resources/Images/Edit.png | Bin 0 -> 1871 bytes Assets/Resources/Images/Edit.png.meta | 104 + Assets/Resources/Images/bg-1.png | Bin 0 -> 2198 bytes Assets/Resources/Images/bg-1.png.meta | 104 + Assets/Resources/Images/input-bg1.png | Bin 0 -> 1767 bytes Assets/Resources/Images/input-bg1.png.meta | 104 + Assets/Resources/Images/input-bg2.png | Bin 0 -> 2446 bytes Assets/Resources/Images/input-bg2.png.meta | 104 + .../Resources/UI/Control/PFUIDropdown.prefab | 1081 ++++++ .../UI/Control/PFUIDropdown.prefab.meta | 7 + .../UI/Control/PFUIInputField.prefab | 313 ++ .../UI/Control/PFUIInputField.prefab.meta | 7 + .../{PfText.prefab => PFUIText.prefab} | 0 ...fText.prefab.meta => PFUIText.prefab.meta} | 0 .../UI/Control/PfPrimaryButton.prefab | 83 +- .../UI/Prefab/Item.meta} | 2 +- .../UI/Prefab/Panel/DevicePanel.prefab | 380 +- .../UI/Prefab/Panel/EditUserPanel.prefab | 3139 +++++++++++++++++ .../UI/Prefab/Panel/EditUserPanel.prefab.meta | 7 + .../UI/Prefab/Panel/RoutesPanel.prefab | 791 +++++ .../UI/Prefab/Panel/RoutesPanel.prefab.meta | 7 + .../UI/Prefab/Panel/UserInfoPanel.prefab | 123 +- Assets/Scenes/MainScene.unity | 254 +- Assets/Scripts/Apis/ApiBase.cs | 1 + .../Devices.meta} | 2 +- Assets/Scripts/Devices/Ant.meta | 8 + Assets/Scripts/Devices/Ant/ANTMessage.cs | 17 + Assets/Scripts/Devices/Ant/ANTMessage.cs.meta | 11 + .../Scripts/Devices/Ant/AbstractAntDevice.cs | 252 ++ .../Devices/Ant/AbstractAntDevice.cs.meta | 11 + Assets/Scripts/Devices/Ant/AirDensity.cs | 103 + Assets/Scripts/Devices/Ant/AirDensity.cs.meta | 11 + Assets/Scripts/Devices/Ant/AntConnector.cs | 523 +++ .../Scripts/Devices/Ant/AntConnector.cs.meta | 11 + Assets/Scripts/Devices/Ant/DataSourceBase.cs | 145 + .../Devices/Ant/DataSourceBase.cs.meta | 11 + Assets/Scripts/Devices/Ant/DeviceState.cs | 17 + .../Scripts/Devices/Ant/DeviceState.cs.meta | 11 + Assets/Scripts/Devices/Ant/FitDevice.cs | 471 +++ Assets/Scripts/Devices/Ant/FitDevice.cs.meta | 11 + .../Scripts/Devices/Ant/ICalibrationPage.cs | 18 + .../Devices/Ant/ICalibrationPage.cs.meta | 11 + Assets/Scripts/Devices/Ant/Interfaces.meta | 8 + .../Devices/Ant/Interfaces/ICadenceDevice.cs | 13 + .../Ant/Interfaces/ICadenceDevice.cs.meta | 11 + .../Ant/Interfaces/IHeartRateDevice.cs | 13 + .../Ant/Interfaces/IHeartRateDevice.cs.meta | 11 + .../Devices/Ant/Interfaces/IPowerDevice.cs | 13 + .../Ant/Interfaces/IPowerDevice.cs.meta | 11 + .../Ant/Interfaces/IRequiresRiderWeight.cs | 13 + .../Interfaces/IRequiresRiderWeight.cs.meta | 11 + .../Devices/Ant/Interfaces/ISpeedDevice.cs | 16 + .../Ant/Interfaces/ISpeedDevice.cs.meta | 11 + .../Ant/ManufacturerDataPageContent.cs | 24 + .../Ant/ManufacturerDataPageContent.cs.meta | 11 + Assets/Scripts/Devices/Ant/Messages.meta | 8 + .../Devices/Ant/Messages/BaseMessage.cs | 19 + .../Devices/Ant/Messages/BaseMessage.cs.meta | 11 + .../Devices/Ant/Messages/FecCalibrate.cs | 30 + .../Devices/Ant/Messages/FecCalibrate.cs.meta | 11 + .../Devices/Ant/Messages/FecErgMode.cs | 40 + .../Devices/Ant/Messages/FecErgMode.cs.meta | 11 + .../Ant/Messages/FecUserConfiguration.cs | 40 + .../Ant/Messages/FecUserConfiguration.cs.meta | 11 + .../Messages/GetManufacturersInformation.cs | 16 + .../GetManufacturersInformation.cs.meta | 11 + .../Ant/Messages/GetProductionInformation.cs | 16 + .../Messages/GetProductionInformation.cs.meta | 11 + .../Devices/Ant/Messages/RequestDataPage.cs | 52 + .../Ant/Messages/RequestDataPage.cs.meta | 11 + Assets/Scripts/Devices/Ant/Pages.meta | 8 + .../Devices/Ant/Pages/CalibrationPages.meta | 8 + .../CalibrationPages/FecCalibrationPage.cs | 27 + .../FecCalibrationPage.cs.meta | 11 + .../Scripts/Devices/Ant/Pages/IPageHandler.cs | 15 + .../Devices/Ant/Pages/IPageHandler.cs.meta | 11 + .../Ant/Pages/ManufacturerDataPageHandler.cs | 33 + .../Pages/ManufacturerDataPageHandler.cs.meta | 11 + Assets/Scripts/Devices/Ant/SensorType.cs | 42 + Assets/Scripts/Devices/Ant/SensorType.cs.meta | 11 + Assets/Scripts/Devices/Ant/UserdChannel.cs | 15 + .../Scripts/Devices/Ant/UserdChannel.cs.meta | 11 + Assets/Scripts/Devices/DeviceValueFilter.cs | 52 + .../Scripts/Devices/DeviceValueFilter.cs.meta | 11 + Assets/Scripts/Scenes/MainController.cs | 3 + .../Scripts/UI/Control/PFUIComponentBase.cs | 14 + .../UI/Control/PFUIComponentBase.cs.meta | 11 + Assets/Scripts/UI/Control/PFUIDropdown.cs | 65 + .../Scripts/UI/Control/PFUIDropdown.cs.meta | 11 + Assets/Scripts/UI/Control/PFUIInputField.cs | 54 + .../Scripts/UI/Control/PFUIInputField.cs.meta | 11 + .../UI/Control/{PfText.cs => PFUIText.cs} | 2 +- .../{PfText.cs.meta => PFUIText.cs.meta} | 0 Assets/Scripts/UI/Control/PfPrimaryButton.cs | 4 +- Assets/Scripts/UI/Prefab/Item.meta | 8 + .../UI/Prefab/Panel/DeviceController.cs | 46 +- .../UI/Prefab/Panel/EditUserController.cs | 19 + .../Prefab/Panel/EditUserController.cs.meta | 11 + .../Scripts/UI/Prefab/Panel/HomeController.cs | 5 +- Assets/Scripts/UI/Prefab/Panel/PFUIPanel.cs | 20 + .../Scripts/UI/Prefab/Panel/PFUIPanel.cs.meta | 11 + .../UI/Prefab/Panel/UserInfoController.cs | 10 +- Assets/Scripts/UIManager.cs | 38 +- Assets/StreamingAssets.meta | 8 + ProjectSettings/EditorBuildSettings.asset | 3 + ProjectSettings/ProjectSettings.asset | 3 +- 115 files changed, 9058 insertions(+), 405 deletions(-) rename Assets/{Cyp/Prefab.meta => Editor.meta} (77%) create mode 100644 Assets/Editor/MyBuildPostprocessor.cs create mode 100644 Assets/Editor/MyBuildPostprocessor.cs.meta create mode 100644 Assets/Plugins/ANT_NET.dll create mode 100644 Assets/Plugins/ANT_NET.dll.meta create mode 100644 Assets/Plugins/DSI_CP210xManufacturing_3_1.dll create mode 100644 Assets/Plugins/DSI_CP210xManufacturing_3_1.dll.meta create mode 100644 Assets/Plugins/DSI_SiUSBXp_3_1.dll create mode 100644 Assets/Plugins/DSI_SiUSBXp_3_1.dll.meta create mode 100644 Assets/Resources/Images/Edit.png create mode 100644 Assets/Resources/Images/Edit.png.meta create mode 100644 Assets/Resources/Images/bg-1.png create mode 100644 Assets/Resources/Images/bg-1.png.meta create mode 100644 Assets/Resources/Images/input-bg1.png create mode 100644 Assets/Resources/Images/input-bg1.png.meta create mode 100644 Assets/Resources/Images/input-bg2.png create mode 100644 Assets/Resources/Images/input-bg2.png.meta create mode 100644 Assets/Resources/UI/Control/PFUIDropdown.prefab create mode 100644 Assets/Resources/UI/Control/PFUIDropdown.prefab.meta create mode 100644 Assets/Resources/UI/Control/PFUIInputField.prefab create mode 100644 Assets/Resources/UI/Control/PFUIInputField.prefab.meta rename Assets/Resources/UI/Control/{PfText.prefab => PFUIText.prefab} (100%) rename Assets/Resources/UI/Control/{PfText.prefab.meta => PFUIText.prefab.meta} (100%) rename Assets/{Image.meta => Resources/UI/Prefab/Item.meta} (77%) create mode 100644 Assets/Resources/UI/Prefab/Panel/EditUserPanel.prefab create mode 100644 Assets/Resources/UI/Prefab/Panel/EditUserPanel.prefab.meta create mode 100644 Assets/Resources/UI/Prefab/Panel/RoutesPanel.prefab create mode 100644 Assets/Resources/UI/Prefab/Panel/RoutesPanel.prefab.meta rename Assets/{Shader2D-master.meta => Scripts/Devices.meta} (77%) create mode 100644 Assets/Scripts/Devices/Ant.meta create mode 100644 Assets/Scripts/Devices/Ant/ANTMessage.cs create mode 100644 Assets/Scripts/Devices/Ant/ANTMessage.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/AbstractAntDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/AbstractAntDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/AirDensity.cs create mode 100644 Assets/Scripts/Devices/Ant/AirDensity.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/AntConnector.cs create mode 100644 Assets/Scripts/Devices/Ant/AntConnector.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/DataSourceBase.cs create mode 100644 Assets/Scripts/Devices/Ant/DataSourceBase.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/DeviceState.cs create mode 100644 Assets/Scripts/Devices/Ant/DeviceState.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/FitDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/FitDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/ICalibrationPage.cs create mode 100644 Assets/Scripts/Devices/Ant/ICalibrationPage.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs create mode 100644 Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs create mode 100644 Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs create mode 100644 Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Pages.meta create mode 100644 Assets/Scripts/Devices/Ant/Pages/CalibrationPages.meta create mode 100644 Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs create mode 100644 Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs create mode 100644 Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs create mode 100644 Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/SensorType.cs create mode 100644 Assets/Scripts/Devices/Ant/SensorType.cs.meta create mode 100644 Assets/Scripts/Devices/Ant/UserdChannel.cs create mode 100644 Assets/Scripts/Devices/Ant/UserdChannel.cs.meta create mode 100644 Assets/Scripts/Devices/DeviceValueFilter.cs create mode 100644 Assets/Scripts/Devices/DeviceValueFilter.cs.meta create mode 100644 Assets/Scripts/UI/Control/PFUIComponentBase.cs create mode 100644 Assets/Scripts/UI/Control/PFUIComponentBase.cs.meta create mode 100644 Assets/Scripts/UI/Control/PFUIDropdown.cs create mode 100644 Assets/Scripts/UI/Control/PFUIDropdown.cs.meta create mode 100644 Assets/Scripts/UI/Control/PFUIInputField.cs create mode 100644 Assets/Scripts/UI/Control/PFUIInputField.cs.meta rename Assets/Scripts/UI/Control/{PfText.cs => PFUIText.cs} (81%) rename Assets/Scripts/UI/Control/{PfText.cs.meta => PFUIText.cs.meta} (100%) create mode 100644 Assets/Scripts/UI/Prefab/Item.meta create mode 100644 Assets/Scripts/UI/Prefab/Panel/EditUserController.cs create mode 100644 Assets/Scripts/UI/Prefab/Panel/EditUserController.cs.meta create mode 100644 Assets/Scripts/UI/Prefab/Panel/PFUIPanel.cs create mode 100644 Assets/Scripts/UI/Prefab/Panel/PFUIPanel.cs.meta create mode 100644 Assets/StreamingAssets.meta diff --git a/Assets/Cyp/Prefab.meta b/Assets/Editor.meta similarity index 77% rename from Assets/Cyp/Prefab.meta rename to Assets/Editor.meta index 6f847132..6957961d 100644 --- a/Assets/Cyp/Prefab.meta +++ b/Assets/Editor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3317df3565c7a5243b3fb5d0225e0018 +guid: bbca202329b5220488e71e1c46608a17 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Editor/MyBuildPostprocessor.cs b/Assets/Editor/MyBuildPostprocessor.cs new file mode 100644 index 00000000..7c12eb0d --- /dev/null +++ b/Assets/Editor/MyBuildPostprocessor.cs @@ -0,0 +1,21 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEngine; + +public class MyBuildPostprocessor +{ + [PostProcessBuild] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) + { + //Debug.Log(pathToBuiltProject); + //System.IO.File.AppendAllText("D:\\test.txt",pathToBuiltProject); + var dir = Path.GetDirectoryName(pathToBuiltProject); + + File.Copy(dir + "\\PowerFun-Unity_Data\\Plugins\\x86_64\\ANT_WrappedLib.dll", dir + "\\PowerFun-Unity_Data\\Managed\\ANT_WrappedLib.dll"); + File.Copy(dir + "\\PowerFun-Unity_Data\\Plugins\\x86_64\\DSI_CP210xManufacturing_3_1.dll", dir + "\\PowerFun-Unity_Data\\Managed\\DSI_CP210xManufacturing_3_1.dll"); + File.Copy(dir + "\\PowerFun-Unity_Data\\Plugins\\x86_64\\DSI_SiUSBXp_3_1.dll", dir + "\\PowerFun-Unity_Data\\Managed\\DSI_SiUSBXp_3_1.dll"); + } +} diff --git a/Assets/Editor/MyBuildPostprocessor.cs.meta b/Assets/Editor/MyBuildPostprocessor.cs.meta new file mode 100644 index 00000000..4f6d508b --- /dev/null +++ b/Assets/Editor/MyBuildPostprocessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c69c286f97edb5d408caa387050a40c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/ANT_NET.dll b/Assets/Plugins/ANT_NET.dll new file mode 100644 index 0000000000000000000000000000000000000000..a409a117941f4f5a79a5886bd66f46dac7a7336f GIT binary patch literal 97792 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 S9Q1c8XZrp>umAt2z<&ef3~8+Z literal 0 HcmV?d00001 diff --git a/Assets/Plugins/ANT_NET.dll.meta b/Assets/Plugins/ANT_NET.dll.meta new file mode 100644 index 00000000..03b2eb45 --- /dev/null +++ b/Assets/Plugins/ANT_NET.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2d11902796c439e4cb71dd57cee77265 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/DSI_CP210xManufacturing_3_1.dll b/Assets/Plugins/DSI_CP210xManufacturing_3_1.dll new file mode 100644 index 0000000000000000000000000000000000000000..7be874559f959f23372b63636ab377469550e4c3 GIT binary patch literal 69632 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 literal 0 HcmV?d00001 diff --git a/Assets/Plugins/DSI_SiUSBXp_3_1.dll.meta b/Assets/Plugins/DSI_SiUSBXp_3_1.dll.meta new file mode 100644 index 00000000..bd07038d --- /dev/null +++ b/Assets/Plugins/DSI_SiUSBXp_3_1.dll.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 0aa7b01dfef68764797710a52872bfce +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Images/Edit.png b/Assets/Resources/Images/Edit.png new file mode 100644 index 0000000000000000000000000000000000000000..53f7049b85f451a1f048141505506ed1d0bfd803 GIT binary patch literal 1871 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 literal 0 HcmV?d00001 diff --git a/Assets/Resources/Images/bg-1.png.meta b/Assets/Resources/Images/bg-1.png.meta new file mode 100644 index 00000000..b9fa1cb7 --- /dev/null +++ b/Assets/Resources/Images/bg-1.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: 970fa7b2c5134aa4689616c9085aa237 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 40, y: 40, z: 40, w: 40} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Images/input-bg1.png b/Assets/Resources/Images/input-bg1.png new file mode 100644 index 0000000000000000000000000000000000000000..4f5f8ebcc1d0a9c71c8776d1cb1f82ab263ed372 GIT binary patch literal 1767 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 + /// 设备生产商 + /// + public int ManufacturerId + { + get + { + return _ManufacturerId; + } + set + { + _ManufacturerId = value; + } + } + + private ushort _DeviceNumber; + public ushort DeviceNumber + { + get + { + return _DeviceNumber; + } + set + { + this._DeviceNumber = value; + searchProfile.deviceNumber = value; + this.InitManufacturer(); + } + } + + public byte DeviceType + { + get + { + return getDefaultSearchProfile().deviceType; + } + } + + public int? AntModelId { get; private set; } + + public Action StateChange = null; + + public class AntChannelProfile + { + public byte rfOffset; + public byte transType; + public byte deviceType; + public ushort deviceNumber; + public ushort messagePeriod; + public bool pairingEnabled; + } + + //private readonly Rhino.PowerFun.Services.DeviceService deviceService; + //private readonly DeviceDetailService _deviceDetailService; + //private readonly AntManufacturerService antManufacturerService; + protected List pageHandlers = new List(); + public AbstractAntDevice(String defaultSourceName, racerSportType sportType, SensorType sensor) + : base(sportType, true) + { + State = DeviceState.Disconnected; + this.Name = defaultSourceName; + this.searchProfile = getDefaultSearchProfile(); + this.Sensor = sensor; + + //deviceService = new DeviceService(); + // _deviceDetailService = new DeviceDetailService(); + //antManufacturerService = new AntManufacturerService(); + + + //this.InitManufacturer(); + + pageHandlers.Add(new ManufacturerDataPageHandler(md => { + this.ManufacturerId = md.ManufacturerId; + this.AntModelId = md.ModelNumber; + + //var deviceId = $"{ this.searchProfile.deviceNumber }:{ this.searchProfile.deviceType }"; + //var device = deviceService.Get(PubCommData.CurrentUser.Id, deviceId); + //if (device != null) + //{ + // device.AntManufacturerId = _ManufacturerId; + // device.AntModelId = this.AntModelId; + + // device.ReportedName = antManufacturerService.GetName(device.AntManufacturerId) + " " + Sensor.ToString(); + + // if (device.AntModelId.HasValue) + // { + // var deviceDetail = _deviceDetailService.Get(device.AntManufacturerId, device.AntModelId.Value); + // if (deviceDetail != null) + // { + // device.ReportedName = deviceDetail.Name; + // } + // } + + // this.Name = device.ReportedName; + // deviceService.Update(device); + //} + + })); + } + + /// + /// 从数据库里还原厂商信息 + /// + private void InitManufacturer() + { + //var deviceId = $"{ this.searchProfile.deviceNumber }:{ this.searchProfile.deviceType }"; + //Device device = PubCommData.CurrentUser != null ? deviceService.Get(PubCommData.CurrentUser.Id, deviceId) : null; + //if (device != null && device.AntManufacturerId > 0) + //{ + // this._ManufacturerId = device.AntManufacturerId; + // this.Name = device.ReportedName; + //} + } + + protected abstract AntChannelProfile getDefaultSearchProfile(); + + public abstract void handleChannelResponse(ANT_Response response); + + public override string getDefaultSourceName() + { + //return sourceName; + return String.Format("{0,-14}", Name); //HACK qc to try and even out some of the dynamic sizing issues + } + + //public override void reset() + //{ + // base.reset(); + //} + + public void Connect() + { + if (State == DeviceState.Connected || State == DeviceState.Connecting) + return; + AntConnector.Instance().ConnectDevice(this); + } + + public void Disconnect(bool save = true) + { + if (State == DeviceState.Disconnected || State == DeviceState.Disconnecting) + return; + AntConnector.Instance().DisconnectDevice(this, save); + } + + //public override bool Equals(Object obj) + //{ + // //return base.Equals(obj); + + // var target = obj as AbstractAntDevice; + // return this.searchProfile.deviceNumber == target.searchProfile.deviceNumber && + // this.searchProfile.deviceType == target.searchProfile.deviceType; + //} + + + public bool GetManufacturingInformation() + { + var channel = AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString()); + if (channel == null) { return false; } + var channelId = channel.Index; + + //byte[] Data = new byte[9] + //{ + // channelId, + // (byte)70, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // (byte)4, + // (byte)80, + // (byte)1 + //}; + //var id = (byte)79; + + var msg = new GetManufacturersInformation(channelId); + var result = SendMessage(msg); + return result; + } + + public bool GetProductionInformation() + { + var channelId = AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString()).Index; + + //byte[] Data = new byte[9] + //{ + // channelId, + // (byte)70, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // (byte)4, + // (byte)81, + // (byte)1 + //}; + //var id = (byte)79; + var msg = new GetProductionInformation(channelId); + var result = SendMessage(msg); + return result; + } + + protected bool SendMessage(BaseMessage message) + { + return AntConnector.Instance().SendMessage(message.GetMessage()); + } + + protected byte GetChannelId() + { + return AntConnector.Instance().usedChannels.SingleOrDefault(u => u.DeviceNumber == this.searchProfile.deviceNumber.ToString() && u.DeviceTypeId == this.searchProfile.deviceType.ToString()).Index; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/AbstractAntDevice.cs.meta b/Assets/Scripts/Devices/Ant/AbstractAntDevice.cs.meta new file mode 100644 index 00000000..097d92d1 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/AbstractAntDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e3231e9ae6a9704b9ece49d9ad21a30 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/AirDensity.cs b/Assets/Scripts/Devices/Ant/AirDensity.cs new file mode 100644 index 00000000..e13fd0c3 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/AirDensity.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + internal static class AirDensity + { + static double pi = 3.141592653589793; + static double radPerDeg = 0; + + static double ae = 6378140.0; + //static double alphae = 1 / 298.257; + static double be = 0; + static double phi0 = 0; + static double R0 = 0; + + + static double meanRadius = 6371004.0; //all use SI units + //static double semiMajorAxis = 6378140.0; + static double gravityConst = 3.98600445e14; + //static double J2 = 1.08263e-3; + + static AirDensity() + { + radPerDeg = pi / 180.0; + be = 297.257 / 298.257 * ae; + phi0 = 29.8336 * radPerDeg; + R0 = ae * be / Math.Sqrt(ae * ae * Math.Sin(phi0) * Math.Sin(phi0) + be * be * Math.Cos(phi0) * Math.Cos(phi0)); + + } + + + /// + /// 计算空气密度 + /// + /// + /// + public static double GetAirDensity(double geoHeight) + { + //tested + var H = geoHeightToPotentialH(geoHeight); + var z = H / (1 - H / 6356766); + var w = 0D; + if (z < 11019.1) + { + w = 1.0 - H / 44330.8; + return 1.225 * Math.Pow(w, 4.2559); + } + if (z < 20063.1) + { + w = Math.Exp((14964.7 - H) / 6341.6); + return 1.225 * .15898 * w; + } + if (z < 32161.9) + { + w = 1.0 + (H - 24902.1) / 221552; + return 1.225 * 3.2722e-2 * Math.Pow(w, -35.1629); + } + if (z < 47350.1) + { + w = 1.0 + (H - 39749.9) / 89410.7; + return 1.225 * 3.2618e-3 * Math.Pow(w, -13.2011); + } + if (z < 51412.5) + { + w = Math.Exp((48625.2 - H) / 7922.3); + return 1.225 * 9.4920e-4 * w; + } + if (z < 71802.0) + { + w = 1.0 - (H - 59439.0) / 88221.8; + return 1.225 * 2.5280e-4 * Math.Pow(w, 11.2011); + } + if (z < 86000.0) + { + w = 1.0 - (H - 78030.3) / 100295.0; + return 1.225 * 1.7632e-5 * Math.Pow(w, 16.0816); + } + if (z < 91000.0) + { + w = Math.Exp((87284.8 - H) / 5470.0); + return 1.225 * 3.6411e-6 * w; + } + return .0;//linearInter(90000.0,13000.0,3.416e-6,8.152e-9,z); + } + + + private static double getRadiusFromLatitude(double latitude) + { + var s = Math.Sin(latitude); + var c = Math.Cos(latitude); + return (ae * be / Math.Pow((ae * ae * s * s + be * be * c * c), .5)); + } + + private static double geoHeightToPotentialH(double h) + { + return gravityConst * h / meanRadius / (meanRadius + h) / 9.8066; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/AirDensity.cs.meta b/Assets/Scripts/Devices/Ant/AirDensity.cs.meta new file mode 100644 index 00000000..f55ceebc --- /dev/null +++ b/Assets/Scripts/Devices/Ant/AirDensity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c99e2df823299b44fb62490c70712b1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/AntConnector.cs b/Assets/Scripts/Devices/Ant/AntConnector.cs new file mode 100644 index 00000000..bb843b63 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/AntConnector.cs @@ -0,0 +1,523 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ANT_Managed_Library; +using UnityEngine; + +namespace Assets.Scripts.Devices.Ant +{ + public class AntConnector : IDisposable + { + private readonly byte[] ANTPLUS_NETWORK_KEY = new byte[] + { + //Insert the ANT+ network key here: + 0xB9, 0xA5, 0x21, 0xFB, 0xBD, 0x72, 0xC3, 0x45 + //Distribution of source code containing the ANT+ Network Key is prohibited. + //You may not add the ANT+ Network Key to this source code and republish it. + //The ANT+ Network Key is available to ANT+ Adopters. + //Please refer to http://thisisant.com to become an ANT+ Adopter and access the key. + }; + private readonly static object _lock = new object(); + private static ANT_Device _antDevice = null; + private ANT_Channel searchChannel; + private readonly List _channels = new List(); + private int ChannelCount + { + get + { + //if (_antDevice == null) return 0; + //return _antDevice.getNumChannels(); + return _channels.Count; + } + } + private bool IsBackgroundScanning { get; set; } + //int searchingDeviceIndex = -1; + + private List deviceList = new List(); + + public bool IsAvailable = false; + /// + /// 设备号,频道编号 + /// + public readonly List usedChannels = new List(); + + public readonly List discoveredDevices = new List(); + + + private static AntConnector _antConnector; + public static AntConnector Instance() + { + if (_antConnector == null) + { + _antConnector = new AntConnector(); + } + + return _antConnector; + } + + //private DeviceService deviceService = new DeviceService(); + private AntConnector() + { + if (_antDevice == null) + { + //ANT_Common.enableDebugLogs(); + //findUsableAntDevice(); + } + //CheckStatus(); + + deviceList.Add(new FitDevice()); + //deviceList.Add(new ds_AntPlus_Power()); + //deviceList.Add(new ds_AntPlus_Cadence()); + //deviceList.Add(new ds_AntPlus_HeartRate()); + //deviceList.Add(new ds_AntPlus_BikeSpdCad()); + + var timer = new System.Timers.Timer(1000); + timer.AutoReset = true; + timer.Elapsed += Timer_Elapsed; + timer.Enabled = true; + } + + private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + CheckStatus(); + } + + public void CheckStatus() + { + if (_antDevice != null) + return; + //discoveredDevices.Add(new VirtualPowerDevice()); + this.CreateAntDevice(); + } + + private void CreateAntDevice() + { + try + { + if ((int)ANT_Common.getNumDetectedUSBDevices() == 0) + return; + _antDevice = new ANT_Device(); + if (_antDevice.getNumChannels() <= 4) + { + _antDevice = null; + return; + } + if (!_antDevice.setNetworkKey(0, ANTPLUS_NETWORK_KEY, 500)) + throw new ApplicationException("Failed to set network key"); + IsAvailable = true; + //_antDevice.configureAdvancedBurstSplitting(true); + + _antDevice.deviceResponse += DeviceResponse; + _antDevice.serialError += new ANT_Device.dSerialErrorHandler(antDevice_serialError); + for (int i = 1; i < _antDevice.getNumChannels(); i++) + { + var channel = _antDevice.getChannel(i); + _channels.Add(channel); + channel.channelResponse += new dChannelResponseHandler(DeviceResponse); + } + + if (IsAvailable) + { + usedChannels.Add(new UserdChannel + { + DeviceNumber = "scan", + DeviceTypeId = "", + Index = 0 + }); + StartNextSearch(); + } + } + catch (Exception ex) + { + //ANT_Device.shutdownDeviceInstance(ref _antDevice); //Don't leave here with an invalid device ref + //throw new Exception("Could not connect to valid USB2: " + ex.Message); //forward the exception + //Log.ErrorLog(ex); + //Debug.LogError(ex); + //throw ex; + Log(ex.Message); + } + finally + { + } + } + + private void Log(string str) + { + //System.IO.File.AppendAllText(@"D:\work\PowerFun\PowerFun-Unity\Build\log.txt", str+"\r\n"); + Debug.LogError(str); + } + + private void antDevice_serialError(ANT_Device sender, ANT_Device.serialErrorCode error, bool isCritical) + { + //throw new NotImplementedException(); + Log("出错了"); + if (error != ANT_Device.serialErrorCode.DeviceConnectionLost) + return; + + if (_antDevice != null) + { + _antDevice.deviceResponse -= DeviceResponse; + _antDevice.serialError -= antDevice_serialError; + } + _antDevice = null; + IsAvailable = false; + foreach (var item in _channels) + { + item.channelResponse -= DeviceResponse; + } + searchChannel.channelResponse -= antChannel_channelResponse_FeSearch; + searchChannel = null; + discoveredDevices.Clear(); + usedChannels.Clear(); + IsBackgroundScanning = false; + + } + + void StartNextSearch() + { + //Console.WriteLine("startNextSearch"); + if (searchChannel != null) + { + //searchChannel.Dispose(); + } + + //Get new search channel if neccesary + if (searchChannel == null) + { + //if (usedChannels.Count >= ChannelCount) + // return; //no free channels + + //Find the first free channel and start the search + //for (int i = 0; i < ChannelCount; ++i) + //{ + // if (!usedChannels.Values.Contains((byte)i)) + // { + // searchChannel = _antDevice.getChannel(i); + // searchChannel.channelResponse += new dChannelResponseHandler(antChannel_channelResponse_FeSearch); + // break; + // } + //} + searchChannel = _antDevice.getChannel(0); // _antDevice.getChannel(usedChannels["scan"]); + searchChannel.channelResponse += new dChannelResponseHandler(antChannel_channelResponse_FeSearch); + } + IsBackgroundScanning = true; + ReSearch(); + } + + void DeviceResponse(ANT_Response response) + { + //Debug.Log(response.responseID); + var channelIndex = response.messageContents[0]; + + var antMessageId = (ANT_ReferenceLibrary.ANTMessageID)response.responseID; + if (antMessageId == ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40) + { + //Trace.WriteLine(string.Join(",", response.messageContents)); + var antEventId = (ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]; + //Trace.WriteLine(antEventId.ToString() +", " + string.Join(",",response.messageContents)); + if (antEventId == ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07) + { + + } + //设备断开连接 + else if (antEventId == ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08) + { + Debug.Log(antEventId.ToString() + ", " + string.Join(",", response.messageContents)); + + var cc1 = usedChannels.Where(d => d.Index == channelIndex).FirstOrDefault(); + var dd1 = discoveredDevices.SingleOrDefault(d => d.searchProfile.deviceNumber.ToString() == cc1.DeviceNumber && d.searchProfile.deviceType.ToString() == cc1.DeviceTypeId); + if (dd1 != null) + { + dd1.Disconnect(false); + return; + } + } + } + else + { + //Trace.WriteLine(antMessageId + ", " + string.Join(",", response.messageContents));//EVENT_RX_FAIL_GO_TO_SEARCH_0x08 + } + + //if (antMessageId == ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50) + + if (response.messageContents.Length == 3) return; + var str = string.Join(",", response.messageContents); + + var cc = usedChannels.Where(d => d.Index == channelIndex).FirstOrDefault(); + var dd = discoveredDevices.SingleOrDefault(d => d.searchProfile.deviceNumber.ToString() == cc.DeviceNumber && d.searchProfile.deviceType.ToString() == cc.DeviceTypeId); + if (dd != null) + { + if (dd.State == DeviceState.Connecting) + { + dd.State = DeviceState.Connected; + //IsBackgroundScanning = true; + //ReSearch(); + //StartNextSearch(); + return; + } + dd.handleChannelResponse(response); + } + } + + public bool SendMessage(byte msgID, byte[] msgData) + { + return _antDevice.writeRawMessageToDevice(msgID, msgData); + } + + public bool SendMessage(ANTMessage data) + { + return SendMessage(data.Id, data.Data); + } + + void antChannel_channelResponse_FeSearch(ANT_Response response) + { + if (IsBackgroundScanning == false) + { + searchChannel.closeChannel(); + return; + } + + if (response.messageContents.Length == 3) return; + + + + var message = response.messageContents; + if (response.messageContents.Length >= 14) + { + message = response.messageContents.Skip(10).Take(4).ToArray(); + + var deviceNumber = message[0] + (message[1] << 8); + var deviceTypeId = message[2] & 127; + var transmissionTypeId = message[3]; + + //Console.WriteLine($" {deviceNumber}, {deviceTypeId}"); + + var device2 = discoveredDevices.FirstOrDefault(d => d.searchProfile.deviceNumber == deviceNumber && d.searchProfile.deviceType == deviceTypeId); + if (device2 != null) + { + //ReSearch(); + if (device2.State == DeviceState.Connected) + { + device2.handleChannelResponse(response); + return; + } + else if (device2.State == DeviceState.Disconnected) + { + //var deviceInfo = deviceService.Get(PubCommData.CurrentUser.Id, $"{ device2.searchProfile.deviceNumber }:{ device2.searchProfile.deviceType }"); + //if (deviceInfo != null && deviceInfo.Paired) + //{ + // device2.Connect(); + //} + } + return; + } + var device1 = deviceList.SingleOrDefault(d => d.searchProfile.deviceType == deviceTypeId); + if (device1 != null) + { + AbstractAntDevice device = null; + switch (device1.Sensor) + { + case SensorType.None: + break; + case SensorType.Cadence: + //device = new ds_AntPlus_Cadence(); + break; + case SensorType.HeartRate: + //device = new ds_AntPlus_HeartRate(); + break; + case SensorType.Power: + //device = new ds_AntPlus_Power(); + break; + case SensorType.Speed: + break; + case SensorType.SpeedCadence: + //device = new ds_AntPlus_BikeSpdCad(); + break; + case SensorType.Trainer: + device = new FitDevice(); + break; + case SensorType.VirtualPower: + break; + default: + break; + } + if (device != null) + { + //device.searchProfile.deviceNumber = (ushort)deviceNumber; + device.DeviceNumber = (ushort)deviceNumber; + discoveredDevices.Add(device); + + + } + //ReSearch(); + return; + } + } + } + + private void ReSearch() + { + if (IsBackgroundScanning == false) return; + //Console.WriteLine($"research,{ DateTime.Now }"); + if (searchChannel != null) + { + //searchChannel.closeChannel(500); + //searchChannel.unassignChannel(); + //searchChannel.openChannel(); + //return; + } + var channelIndex = (byte)0; //searchChannel.getChannelNum(); + //Handle setting the search timeout + byte timeout = 4; //default 4*2.5=10 seconds for each device + //if (deviceList.Count - usedChannels.Count == 1) + timeout = 255; //search forever if we only have one device to find; If one of the other devices resets it will startNextSearch again so we won't get stuck + + searchChannel.assignChannelExt(ANT_ReferenceLibrary.ChannelType.ADV_TxRx_Only_or_RxAlwaysWildCard_0x40, 0, ANT_ReferenceLibrary.ChannelTypeExtended.ADV_AlwaysSearch_0x01); + //SendMessage((int)ANT_ReferenceLibrary.ANTMessageID.ASSIGN_CHANNEL_0x42, new byte[] { + // channelIndex, + // (int)ANT_ReferenceLibrary.ChannelType.ADV_TxRx_Only_or_RxAlwaysWildCard_0x40, + // 0 + // }); + searchChannel.setChannelID(0, false, 0, 0); + searchChannel.setChannelFreq(57); + SendMessage(102, new byte[] { channelIndex, Convert.ToByte(true) }); + searchChannel.setLowPrioritySearchTimeout(timeout); + searchChannel.setChannelSearchTimeout(0); + searchChannel.openChannel(500); + } + + public void ConnectDevice(AbstractAntDevice device) + { + if (usedChannels.Any(u => u.DeviceNumber == device.searchProfile.deviceNumber.ToString() && + u.DeviceTypeId == device.searchProfile.deviceType.ToString())) + return; + + if (device.Sensor == SensorType.Trainer || device.Sensor == SensorType.Power) + { + if (discoveredDevices.Any(s => s.Sensor == device.Sensor && (s.State == DeviceState.Connected || s.State == DeviceState.Connecting))) + { + return; + } + } + if (device.Sensor == SensorType.Cadence) + { + if (discoveredDevices.Any(s => s.Sensor == device.Sensor && (s.State == DeviceState.Connected || s.State == DeviceState.Connecting))) + { + return; + } + } + if (device.Sensor == SensorType.HeartRate) + { + if (discoveredDevices.Any(s => s.Sensor == device.Sensor && (s.State == DeviceState.Connected || s.State == DeviceState.Connecting))) + { + return; + } + } + + for (int i = 0; i < ChannelCount; i++) + { + if (!usedChannels.Any(u => u.Index == (byte)i)) + { + usedChannels.Add(new UserdChannel + { + DeviceNumber = device.searchProfile.deviceNumber.ToString(), + DeviceTypeId = device.searchProfile.deviceType.ToString(), + Index = (byte)i + }); + break; + } + } + + //var deviceService = new DeviceService(); + //var info = deviceService.Get(PubCommData.CurrentUser.Id, device.searchProfile.deviceNumber.ToString() + ":" + device.searchProfile.deviceType); + //if (info != null && info.Paired == false) + //{ + // info.Paired = true; + // deviceService.Update(info); + //} + + #region 配对 + device.State = DeviceState.Connecting; + + //var r = searchChannel.closeChannel(500); + //if (!r) + //{ + // throw new Exception("关闭搜索频道出错"); + //} + + //CloseChannel(searchChannel); + //IsBackgroundScanning = false; + + var channelIndex = usedChannels.Single(c => c.DeviceNumber == device.searchProfile.deviceNumber.ToString() && c.DeviceTypeId == device.searchProfile.deviceType.ToString()).Index; + + var channel = _antDevice.getChannel(channelIndex); + //channel.channelResponse += DeviceResponse; + channel.assignChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00, 0); + channel.setChannelID(device.searchProfile.deviceNumber, false, (byte)device.searchProfile.deviceType, device.searchProfile.transType); + channel.setChannelPeriod(device.searchProfile.messagePeriod); + channel.setChannelFreq(device.searchProfile.rfOffset); + channel.openChannel(); + + //if (!r1) + //{ + // throw new Exception($"打开配对频道出错{ channelIndex }"); + //} + //Console.WriteLine($" 连接设备{ device.searchProfile.deviceNumber }, 频道{ channelIndex },{ DateTime.Now }"); + + + //Task.Delay(2000).ContinueWith((t) => + //{ + // IsBackgroundScanning = true; + // ReSearch(); + //}); + #endregion + } + + public void DisconnectDevice(AbstractAntDevice device, bool save) + { + var deviceNumber = device.searchProfile.deviceNumber.ToString(); + var deviceType = device.searchProfile.deviceType.ToString(); + var item = usedChannels.SingleOrDefault(u => u.DeviceNumber == deviceNumber && u.DeviceTypeId == deviceType); + if (item == null) + return; + device.State = DeviceState.Disconnecting; + var channelIndex = item.Index; + var channel = _antDevice.getChannel(channelIndex); + CloseChannel(channel); + usedChannels.Remove(item); + device.State = DeviceState.Disconnected; + + if (save) + { + //var deviceService = new DeviceService(); + //var info = deviceService.Get(PubCommData.CurrentUser.Id, device.searchProfile.deviceNumber.ToString() + ":" + device.searchProfile.deviceType); + //if (info != null && info.Paired) + //{ + // info.Paired = false; + // deviceService.Update(info); + //} + } + } + + public void Dispose() + { + discoveredDevices.Clear(); + deviceList.Clear(); + + _channels.Clear(); + + if (_antDevice != null) + { + _antDevice.Dispose(); + } + } + + public void CloseChannel(ANT_Channel channel) + { + channel.closeChannel(500); + channel.unassignChannel(500); + } + } +} diff --git a/Assets/Scripts/Devices/Ant/AntConnector.cs.meta b/Assets/Scripts/Devices/Ant/AntConnector.cs.meta new file mode 100644 index 00000000..fefa2e48 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/AntConnector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9367d67beb5a1e49b5ecfb438961331 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/DataSourceBase.cs b/Assets/Scripts/Devices/Ant/DataSourceBase.cs new file mode 100644 index 00000000..d496c7dc --- /dev/null +++ b/Assets/Scripts/Devices/Ant/DataSourceBase.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + public abstract class DataSourceBase + { + //double distanceTravelled = 0; + //DataSourcePacket lastPacketRcvd = null; + protected racerSportType sportType; + + //const double defaultRunStrideLength = 2.5; + //const double defaultRowStrideLength = 5; + //const double defaultBikeStrideLength = 8; + //const double defaultSkiStrideLength = 4.5; + + public string customSourceName; + + public bool isInUse = false; + public bool isHuman; + + static byte uidCount = 0; + public readonly byte uid; + + + public DataSourceBase(racerSportType sportType, bool isHuman) + { + this.sportType = sportType; + this.isHuman = isHuman; + uid = ++uidCount; + if (uidCount == byte.MaxValue) + uidCount = byte.MaxValue - 1; //If we overflow just stay at max instead of colliding with earlier values + } + + Action distanceUpdate; + //bool running = false; + + public racerSportType getSportType() + { + return sportType; + } + + //public double getCurrentDistance() + //{ + // return distanceTravelled; + //} + + //public void incrementDistanceAndUpdate(double distToAdd, double speedMs = 0xFFFF, double cadence = -1, byte heartRate = 0xFF, ushort powerW = 0xFFFF) + //{ + // if (running) + // { + // if (cadence == -1) + // cadence = calculateCadence(speedMs); + + // distanceTravelled += distToAdd; + // lastPacketRcvd = new DataSourcePacket(distanceTravelled, speedMs, cadence, heartRate, powerW); + // distanceUpdate(lastPacketRcvd); + // } + // else //Just save the last packet for monitoring purposes + // { + // if(lastPacketRcvd == null) + // lastPacketRcvd = new DataSourcePacket(distToAdd, speedMs, cadence, heartRate, powerW); + // else + // lastPacketRcvd = new DataSourcePacket(lastPacketRcvd.distance + distToAdd, speedMs, cadence, heartRate, powerW); + // } + //} + + //public virtual void reset() + //{ + // stop(); + // distanceTravelled = 0; + // lastPacketRcvd = null; + //} + + //public virtual void start(Action distanceUpdateHandler) + //{ + // distanceUpdate = distanceUpdateHandler; + // running = true; + //} + + //public virtual void stop() + //{ + // running = false; + // distanceUpdate = null; + //} + + //public bool isRunning() + //{ + // return running; + //} + + public abstract string getDefaultSourceName(); + + public string getSourceName() + { + if (String.IsNullOrWhiteSpace(customSourceName)) + return getDefaultSourceName(); + else + return customSourceName; + } + + //public DataSourcePacket getLastDataRcvd() + //{ + // return lastPacketRcvd; + //} + + //protected double calculateCadence(double speed_Ms) + //{ + // switch (sportType) + // { + // case racerSportType.Running: + // return (speed_Ms * 60) / DataSourceBase.defaultRunStrideLength; //[m/min] / [m/str] = str/min + // case racerSportType.Rowing: + // return (speed_Ms * 60) / DataSourceBase.defaultRowStrideLength; + // case racerSportType.Biking: + // return (speed_Ms * 60) / DataSourceBase.defaultBikeStrideLength; + // case racerSportType.Skiing: + // return (speed_Ms * 60) / DataSourceBase.defaultSkiStrideLength; + // default: + // return 0; + // } + //} + } + + public class DataSourcePacket + { + public readonly double distance; //m + public readonly double cadence; //rpm + public readonly double speed_ms; //m/s + public readonly byte heartRate; //bpm + public readonly ushort power; //W + + public DataSourcePacket(double dist, double spdMs, double cad, byte hr, ushort pwr) + { + distance = dist; + cadence = cad; + speed_ms = spdMs; + heartRate = hr; + power = pwr; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/DataSourceBase.cs.meta b/Assets/Scripts/Devices/Ant/DataSourceBase.cs.meta new file mode 100644 index 00000000..de8a2244 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/DataSourceBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d26362003c1b21f419a01b150b02f110 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/DeviceState.cs b/Assets/Scripts/Devices/Ant/DeviceState.cs new file mode 100644 index 00000000..e0f78e24 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/DeviceState.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + public enum DeviceState + { + Connecting, + Connected, + Interrupted, + Disconnecting, + Disconnected, + } +} diff --git a/Assets/Scripts/Devices/Ant/DeviceState.cs.meta b/Assets/Scripts/Devices/Ant/DeviceState.cs.meta new file mode 100644 index 00000000..0e4a5d97 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/DeviceState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da476d42626b4894c80f0fc0b46709ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/FitDevice.cs b/Assets/Scripts/Devices/Ant/FitDevice.cs new file mode 100644 index 00000000..cd850faf --- /dev/null +++ b/Assets/Scripts/Devices/Ant/FitDevice.cs @@ -0,0 +1,471 @@ +using Assets.Scripts.Devices.Ant.Interfaces; +using Assets.Scripts.Devices.Ant.Messages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace Assets.Scripts.Devices.Ant +{ + public class FitDevice : AbstractAntDevice, ISpeedDevice, IPowerDevice, ICadenceDevice, IRequiresRiderWeight + { + public const int MAX_NO_EVENT_STOP_COUNT = 12; + + //byte lastElapsedTimeAcc; + //byte lastDistAcc; + //double calcSpeed = 0; //Averaged Speed over several msgs in case instSpeed is not available + + int lastInstCadence = -1; + ushort lastInstPower = 0xFFFF; + + + /// + /// 当前坡度,当切换到其他模式的时候,需要把坡度设置为0 + /// + private double _grade = 0; + private bool IsCalibrating { get; set; } + public FitDevice() + : base("Ant+ Trainer", racerSportType.Unknown, SensorType.Trainer) + { + this.StateChange = (state) => + { + if (state == DeviceState.Connected) + { + Calibrate(); + } + }; + } + + /// + /// 发送校准命令 + /// + private void Calibrate() + { + if (this.IsCalibrating) + return; + + this.IsCalibrating = true; + + base.SendMessage(new FecCalibrate(GetChannelId())); + } + + protected override AntChannelProfile getDefaultSearchProfile() + { + return new AntChannelProfile() + { + rfOffset = 57, + transType = 0, + deviceType = 17, + deviceNumber = 0, + messagePeriod = 8192, + pairingEnabled = false, + }; + } + //private byte _previousEventCount; + + // Token: 0x0400054F RID: 1359 + //private ushort _previousPeriod; + + // Token: 0x04000550 RID: 1360 + //private ushort _previousAccumulatedTorque; + + private DateTime _lastEventChange = DateTime.UtcNow; + + public double Speed { get; set; } + + private int _Power; + public int Power + { + get + { + return _Power; + } + set + { + _Power = DeviceValueFilter.Power(value); + Debug.Log(_Power); + } + } + + private int _Cadence; + public int Cadence + { + get + { + return _Cadence; + } + set + { + _Cadence = DeviceValueFilter.Cadence(value); + } + } + + private double _riderWeight = 75.0; + + public double RiderWeight + { + get => _riderWeight; + set + { + if (value <= 0) return; + this._riderWeight = value; + this.UpdateUserConfiguration(); + } + } + + public DateTime LastCalibration { get; protected set; } + public int? Offset { get; set; } + + + public override void handleChannelResponse(ANT_Managed_Library.ANT_Response response) + { + //Console.WriteLine(string.Join(",", response.messageContents)); + //Log.LogInfo(string.Join(",", response.messageContents)); + if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E) + { + var pageNumber = response.messageContents[1]; + switch (pageNumber) + { + case 16: //Page 16 - General Page + { + HandleGeneralDataPage(response.messageContents.Skip(1).ToArray()); + } + break; + //case 17: //general settings Page, not on bike, shows on rower, but not very useful + // { + // System.Console.Out.WriteLine("Cycle Length:" + response.messageContents[4] + ",Incline:" + (response.messageContents[5] + (response.messageContents[5] << 8)) + ",Resist:" + response.messageContents[7]); + // } + // break; + //case 18: //metabolic data, doesn't show on rower or bike + // { + // System.Console.Out.WriteLine("BurnRate:" + (response.messageContents[5] + (response.messageContents[6] << 8)) + ",Cal:" + response.messageContents[7]); + // } + // break; + case 19: //treadmill data + { + lastInstCadence = response.messageContents[5]; + } + break; + case 21: //bike data + case 22: //Row data, same format as bike for cad and power + case 20: //Elliptical, same format as bike for cad and power + case 24: //Nordic Skier, same format as bike for cad and power + { + lastInstCadence = response.messageContents[5]; + lastInstPower = (ushort)(response.messageContents[6] + (response.messageContents[7] << 8)); + //System.Console.Out.WriteLine("Cadence:" + response.messageContents[5] + ",Power:" + (response.messageContents[6] + (response.messageContents[7] << 8))); + //System.Console.Out.WriteLine("SPM:"+response.messageContents[5]+"Power:"+(response.messageContents[6] + (response.messageContents[7] << 8))); + } + break; + case 25: + + HandleTrainerDataPage(response.messageContents.Skip(1).ToArray()); + break; + //case 80: + // new ManufacturerDataPageHandler().Handle(response.messageContents.Skip(1).ToArray(), this); + // break; + case 122: + break; + default: + foreach (var handler in pageHandlers) + { + if (handler.CanHandle(pageNumber)) + { + handler.Handle(response.messageContents.Skip(1).ToArray(), this); + } + } + break; + } + } + } + + private void HandleGeneralDataPage(byte[] dataPayload) + { + try + { + byte equipmentType = dataPayload[1]; + byte elapsedTime = dataPayload[2]; + byte distanceTraveled = dataPayload[3]; + + //byte heartRate = dataPayload[6]; + //FecPageHandler.HeartRateDataSource heartRateDataSource = (FecPageHandler.HeartRateDataSource)(dataPayload[7] & 3); + //bool traveledEnabled = (dataPayload[7] & 4) == 1; + //bool distanceTraveledEnabled = (dataPayload[7] & 8) == 1; + //FecPageHandler.FeState feState = (FecPageHandler.FeState)(dataPayload[7] & 128); + //bool lapToggle = (dataPayload[7] & 128) == 1; + //this._fecGeneralData = new FecGeneralData(equipmentType, elapsedTime, distanceTraveled, (short)num, feState, lapToggle, heartRate, heartRateDataSource, traveledEnabled, distanceTraveledEnabled); + bool traveledEnabled = ((int)dataPayload[7] & 4) == 1; + bool distanceTraveledEnabled = ((int)dataPayload[7] & 8) == 1; + + int num1 = (int)dataPayload[4] | (int)dataPayload[5] << 8; // Instantaneous speed, m/s + Speed = (double)num1 / 1000.0 * 60.0 * 60.0 / 1000.0; //转换成公里/小时 + //Console.WriteLine(num1 +"-----"+Speed); + //fecDevice.UpdateSpeed(new double?(value)); + //PubCommData.Speed = num2; + + //byte? b2 = (heartRate == 255) ? null : new byte?(heartRate); + //int? xl = b2.HasValue ? new int?((int)b2.GetValueOrDefault()) : 0; + //Console.WriteLine("最新速度" + Speed); + //Console.WriteLine("最新心率" + xl); + + //string str = ""; + //for (int i = 0; i < response.messageContents.Length; i++) + //{ + // str += "," + response.messageContents[i]; + //} + //PubCommData.sp = "速度:" + str; + } + catch (Exception) + { + } + } + + private void HandleTrainerDataPage(byte[] dataPayload) + { + //if (response.messageContents.Length < 11) break; + //double value = 0; + //for (int i = 0; i < response.messageContents.Length; i++) + //{ + // if (i < 8) + // { + // value += response.messageContents[i]; + // } + //} + + //double value1 = response.messageContents[10] * 256 + response.messageContents[9]; + + + //double power = response.messageContents[7] * 256 + response.messageContents[6]; + //Console.WriteLine("power:" + power); + //PubCommData.power = power; + + try + { + if (dataPayload[5] > 0) + { + //Console.WriteLine(dataPayload[5] + "," + dataPayload[6]);//瞬时功率 + } + byte num1 = dataPayload[1]; + byte num2 = dataPayload[2]; + int accumulatedPower = (int)dataPayload[3] | (int)dataPayload[4] << 8; + int instantaneousPower = (int)dataPayload[5] | ((int)dataPayload[6] & 15) << 8; //Watts + bool bikePowerCalibrationRequired = ((int)dataPayload[6] >> 4 & 1) == 1; + bool resistanceCalibrationRequired = ((int)dataPayload[6] >> 5 & 1) == 1; + bool userConfigurationRequired = ((int)dataPayload[6] >> 6 & 1) == 1; + bool speedIsTooLow = ((int)dataPayload[7] & 1) == 1; + bool speedIsTooHigh = ((int)dataPayload[7] & 2) == 1; + + //PubCommData.power = instantaneousPower; + Power = instantaneousPower; + + //bool bikePowerCalibrationRequired = (response.messageContents[6] >> 4 & 1) == 1; + //bool resistanceCalibrationRequired = (response.messageContents[6] >> 5 & 1) == 1; + //bool flag = (response.messageContents[6] >> 6 & 1) == 1; + //bool speedIsTooLow = (response.messageContents[7] & 1) == 1; + //bool speedIsTooHigh = (response.messageContents[7] & 2) == 1; + //FecPageHandler.FeState feState = (FecPageHandler.FeState)(dataPayload[7] & 112); + //bool lapToggle = (dataPayload[7] & 128) == 1; + //this._fecTrainerData = new FecTrainerData((int)eventCount, (int)b, accumulatedPower, num, bikePowerCalibrationRequired, resistanceCalibrationRequired, flag, speedIsTooLow, speedIsTooHigh, feState, lapToggle); + //device.UpdatePower(new int?(num)); + byte? nullable = (int)num2 == (int)byte.MaxValue ? new byte?() : new byte?(num2); + int? cadence = nullable.HasValue ? new int?((int)nullable.GetValueOrDefault()) : new int?(); + this.Cadence = cadence.GetValueOrDefault(); + + //Console.WriteLine($"power:{ instantaneousPower },Cadence:{ cadence }, data:{ string.Join(",", dataPayload) }"); + + if (!userConfigurationRequired) + return; + UpdateUserConfiguration(); + } + catch (Exception) + { + } + } + + + public void SetErgMode(int targetPower) + { + if (this.State != DeviceState.Connected) + return; + if (_grade > 0) + { + SetTrackResistance(0); + } + + var channelId = GetChannelId(); + + //byte id = (byte)79; + //byte[] Data = new byte[9] + // { + // channelId, + // (byte) 49, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // byte.MaxValue, + // (byte)(targetPower & (int) byte.MaxValue), + // (byte)(targetPower >> 8 & (int) byte.MaxValue) + // }; + AntConnector.Instance().SendMessage(new FecErgMode(channelId, targetPower).GetMessage()); + } + + public void SetResistanceMode(double value) + { + if (this.State != DeviceState.Connected) + return; + if (_grade > 0) + { + SetTrackResistance(0); + } + Console.WriteLine($"阻力模式{ value }"); + var channelId = GetChannelId(); + + double resistance = value / 100 * 200; + byte id = (byte)79; + byte[] Data = new byte[9] + { + channelId, + (byte) 48, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + (byte)resistance + }; + AntConnector.Instance().SendMessage(id, Data); + } + + /// + /// 风阻 + /// + /// 海拔高度,单位米 + public void SetWindResistance(double? height = null) + { + if (this.State != DeviceState.Connected) + return; + if (_grade > 0) + { + SetTrackResistance(0); + } + Console.WriteLine($"自由骑{ height }"); + var channelId = GetChannelId(); + //double resistance = value / 100 * 200; + + byte windResistance = 0; //Product of Frontal Surface Area, Drag Coefficient and Air Density. Use default value: 0xFF, range: 0.00 – 1.86 kg/m + + if (height.HasValue) + { + //Wind Resistance Coefficient [kg/m] = Frontal Surface Area [m2] x Drag Coefficient x Air Density[kg / m3] + var wr = 0.40 * 1.0 * AirDensity.GetAirDensity(height.Value); + if (wr > 1.86) + { + wr = 1.86; + } + windResistance = (byte)(Convert.ToInt32(Math.Round(wr, 2) / 0.01)); + + Console.WriteLine($"风阻系数:{ windResistance }"); + } + + byte id = (byte)79; + byte[] Data = new byte[9] + { + channelId, + (byte) 50, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + //Wind Resistance Coefficient 0.00 – 1.86kg/m Product of Frontal Surface Area, Drag Coefficient and Air Density.Use default value: 0xFF + windResistance, + //Wind Speed -127 – +127km/h + 0xFF, + 0xFF + }; + AntConnector.Instance().SendMessage(id, Data); + } + /// + /// 轨道阻力 + /// + /// 坡度百分比的值,单位是% + public void SetTrackResistance(double grade) + { + if (this.State != DeviceState.Connected) + return; + + _grade = grade; + if (_grade > 15) + { + _grade = 15; + } + else if (_grade < -5) + { + _grade = -5; + } + //Console.WriteLine($"轨道阻力{ grade }"); + var channelId = GetChannelId(); + //double resistance = value / 100 * 200; + + //var windResistance = 0.00; //Product of Frontal Surface Area, Drag Coefficient and Air Density. Use default value: 0xFF, range: 0.00 – 1.86kg/m + + byte id = (byte)79; + + // zwift started + // 0000 a4 09 4e 00 10 19 18 19 1a 41 00 30 80 00 00 + // reply a4 09 4f 00 33 ff ff ff ff 45 4e ff 25 # p.74 [33] track resistance, ff ff ff ff reserved, [45] slope lsb, [4e] slope msb in 1/100%, [ff] coefficient rolling resistance + // Simulated Grade(%) = (Raw Grade Value x 0.01%) – 200.00% , 454e = 20037 x 0.01 -200 = 0.37% + //var gradeBytes = BitConverter.GetBytes(0x4E20); + + var gradeValue = Convert.ToInt32((grade + 200) * 100); + var gradeBytes = BitConverter.GetBytes(gradeValue); + //var gradeBytes = BitConverter.GetBytes(20004); + byte[] Data = new byte[9] + { + channelId, + (byte) 51, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + gradeBytes[0], + gradeBytes[1], + byte.MaxValue + }; + AntConnector.Instance().SendMessage(id, Data); + } + + public void UpdateUserConfiguration() + { + if (this.State != DeviceState.Connected) + return; + + var channelId = GetChannelId(); + //var _weight = (int)(this._riderWeight * 100.0); + //byte id = (byte)79; + //byte[] Data = new byte[9] + // { + // channelId, + // (byte) 55, + // (byte)(_weight & (int) byte.MaxValue), + // (byte)(_weight >> 8 & (int) byte.MaxValue), + // byte.MaxValue, + // (byte) 143, + // (byte) 12, + // (byte) 70, + // (byte) 0 + // }; + //AntConnector.Instance().SendMessage(id, Data); + AntConnector.Instance().SendMessage(new FecUserConfiguration(channelId, this._riderWeight).GetMessage()); + } + + internal void DoCalibrationSuccess(int? offset) + { + this.LastCalibration = DateTime.UtcNow; + this.Offset = offset; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/FitDevice.cs.meta b/Assets/Scripts/Devices/Ant/FitDevice.cs.meta new file mode 100644 index 00000000..79487053 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/FitDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b7cdd6c7cf126c44b931a62300bb6486 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/ICalibrationPage.cs b/Assets/Scripts/Devices/Ant/ICalibrationPage.cs new file mode 100644 index 00000000..4947cc43 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/ICalibrationPage.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + /// + /// 校准接口 + /// + interface ICalibrationPage + { + bool CanHandle(byte calibrationId); + + void Handle(byte[] dataPayload, AbstractAntDevice device); + } +} diff --git a/Assets/Scripts/Devices/Ant/ICalibrationPage.cs.meta b/Assets/Scripts/Devices/Ant/ICalibrationPage.cs.meta new file mode 100644 index 00000000..49f8794f --- /dev/null +++ b/Assets/Scripts/Devices/Ant/ICalibrationPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 136a39036e705ed4b8ef9253254d836a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces.meta b/Assets/Scripts/Devices/Ant/Interfaces.meta new file mode 100644 index 00000000..ebf68cc8 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 47189d348e47acc4b8a453cca1b2fe63 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs b/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs new file mode 100644 index 00000000..2c547f1e --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Interfaces +{ + public interface ICadenceDevice + { + int Cadence { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs.meta b/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs.meta new file mode 100644 index 00000000..301badc6 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/ICadenceDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bbe1ee0aebb20d84096d93ba512531da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs b/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs new file mode 100644 index 00000000..9f08b918 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Interfaces +{ + public interface IHeartRateDevice + { + int HeartRate { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs.meta b/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs.meta new file mode 100644 index 00000000..5d711ee8 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IHeartRateDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef25441eb7ec60c47b6e85836c30a62d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs b/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs new file mode 100644 index 00000000..b29dc385 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Interfaces +{ + public interface IPowerDevice + { + int Power { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs.meta b/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs.meta new file mode 100644 index 00000000..2c3e9e85 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IPowerDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 71445caab189dc14ea3e5f293e495dbf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs b/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs new file mode 100644 index 00000000..54d4a927 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Interfaces +{ + public interface IRequiresRiderWeight + { + double RiderWeight { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs.meta b/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs.meta new file mode 100644 index 00000000..f6754013 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/IRequiresRiderWeight.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11743b109c228f4409238e5bab3df5f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs b/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs new file mode 100644 index 00000000..0bfbafa9 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Interfaces +{ + public interface ISpeedDevice + { + /// + /// 公里/小时 + /// + double Speed { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs.meta b/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs.meta new file mode 100644 index 00000000..54048259 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Interfaces/ISpeedDevice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3850cb59e257d534cb09d66e62c526da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs b/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs new file mode 100644 index 00000000..ee37a36f --- /dev/null +++ b/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + public class ManufacturerDataPageContent + { + public int HardwareRevision { get; } + + public int ManufacturerId { get; } + + public int ModelNumber { get; } + + public ManufacturerDataPageContent(int hwRevision, int mfgId, int modelNumber) + { + this.HardwareRevision = hwRevision; + this.ManufacturerId = mfgId; + this.ModelNumber = modelNumber; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs.meta b/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs.meta new file mode 100644 index 00000000..4fdc8b41 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/ManufacturerDataPageContent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44b81b22dea61054392b3df125113d37 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages.meta b/Assets/Scripts/Devices/Ant/Messages.meta new file mode 100644 index 00000000..21de76ba --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a0e9980bdeaa124bb4f34c29d4cfb6d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs b/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs new file mode 100644 index 00000000..da9b7c64 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public abstract class BaseMessage + { + protected byte Channel; + public BaseMessage(byte channel) + { + Channel = channel; + } + + public abstract ANTMessage GetMessage(); + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs.meta b/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs.meta new file mode 100644 index 00000000..e2fc2d09 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/BaseMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 929d7cdce470dec4d973c5a714fba697 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs b/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs new file mode 100644 index 00000000..3f4c3b9b --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class FecCalibrate : BaseMessage + { + public FecCalibrate(byte channel) : base(channel) + { + } + + public override ANTMessage GetMessage() + { + return new ANTMessage() + { + Id = (byte)79, + Size = (byte)3, + Data = new byte[3] + { + this.Channel, + (byte) 1, + (byte) 192 + } + }; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs.meta b/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs.meta new file mode 100644 index 00000000..e4d72772 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecCalibrate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec7724b4dc1d247428ceab28a8258c6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs b/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs new file mode 100644 index 00000000..0ec3aa75 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class FecErgMode : BaseMessage + { + private readonly int _targetPower; + + public FecErgMode(byte channel, int targetPower) + : base(channel) + { + this._targetPower = targetPower; + } + + public override ANTMessage GetMessage() + { + return new ANTMessage() + { + Id = (byte)79, + Size = (byte)9, + Data = new byte[9] + { + this.Channel, + (byte) 49, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + byte.MaxValue, + (byte) (this._targetPower & (int) byte.MaxValue), + (byte) (this._targetPower >> 8 & (int) byte.MaxValue) + } + }; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs.meta b/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs.meta new file mode 100644 index 00000000..a01d7cb1 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecErgMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d38d163148cfd84faf99c5a2bb04010 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs b/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs new file mode 100644 index 00000000..2cbf4b35 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class FecUserConfiguration : BaseMessage + { + private readonly int _weight; + + public FecUserConfiguration(byte channel, double weight) + : base(channel) + { + this._weight = (int)(weight * 100.0); + } + + public override ANTMessage GetMessage() + { + return new ANTMessage() + { + Id = (byte)79, + Size = (byte)4, + Data = new byte[9] + { + this.Channel, + (byte) 55, + (byte) (this._weight & (int) byte.MaxValue), + (byte) (this._weight >> 8 & (int) byte.MaxValue), + byte.MaxValue, + (byte) 143, + (byte) 12, + (byte) 70, + (byte) 0 + } + }; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs.meta b/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs.meta new file mode 100644 index 00000000..473b4078 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/FecUserConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b2e6e85130827343b3cd09fbae19376 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs b/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs new file mode 100644 index 00000000..e430a65e --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class GetManufacturersInformation : RequestDataPage + { + public GetManufacturersInformation(byte channel) + : base(channel, (byte)80, new byte?(), new byte?(), (byte)4) + { + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs.meta b/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs.meta new file mode 100644 index 00000000..b812bdb5 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/GetManufacturersInformation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c125f730d91490941a69906b4a589f4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs b/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs new file mode 100644 index 00000000..3776268e --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class GetProductionInformation : RequestDataPage + { + public GetProductionInformation(byte channel) + : base(channel, (byte)81, new byte?(), new byte?(), (byte)4) + { + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs.meta b/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs.meta new file mode 100644 index 00000000..257c7e06 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/GetProductionInformation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bb48d2b993bd7e4b941f8c75135dad5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs b/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs new file mode 100644 index 00000000..6cbbaf75 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Messages +{ + public class RequestDataPage: BaseMessage + { + private readonly byte _channel; + private byte _page; + private byte _descriptorByte1; + private byte _descriptorByte2; + private readonly byte _requestedTransmissionResponse; + + public RequestDataPage(byte channel, byte page, byte? descriptorByte1 = null, byte? descriptorByte2 = null, byte requestedTransmissionResponse = (byte)4) + : base(channel) + { + this._channel = channel; + this._page = page;//81 + byte? nullable = descriptorByte1; + this._descriptorByte1 = nullable.HasValue ? nullable.GetValueOrDefault() : byte.MaxValue; + nullable = descriptorByte2; + this._descriptorByte2 = nullable.HasValue ? nullable.GetValueOrDefault() : byte.MaxValue; + this._requestedTransmissionResponse = requestedTransmissionResponse; + } + + public override ANTMessage GetMessage() + { + byte[] numArray1 = new byte[9] + { + this._channel, + (byte) 70, + byte.MaxValue, + byte.MaxValue, + this._descriptorByte1,//byte.MaxValue + this._descriptorByte2,//byte.MaxValue + this._requestedTransmissionResponse,//4 + this._page,//81 + (byte) 1 + }; + ANTMessage antMessage = new ANTMessage(); + antMessage.Id = (byte)79; + int num = (int)(byte)numArray1.Length; + antMessage.Size = (byte)num; + byte[] numArray2 = numArray1; + antMessage.Data = numArray2; + return antMessage; + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs.meta b/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs.meta new file mode 100644 index 00000000..9de59e91 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Messages/RequestDataPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15e2a257350cfc24b90dadd3a2d33e60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Pages.meta b/Assets/Scripts/Devices/Ant/Pages.meta new file mode 100644 index 00000000..3b16aa9c --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 725781b502595ff44b581d48d7e20f1b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Pages/CalibrationPages.meta b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages.meta new file mode 100644 index 00000000..4f675512 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 099c6c049781ec04fa6d891162fa2971 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs new file mode 100644 index 00000000..1f85495e --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Pages.CalibrationPages +{ + internal class FecCalibrationPage : ICalibrationPage + { + public bool CanHandle(byte calibrationId) + { + return (int)calibrationId == 20; + } + + public void Handle(byte[] dataPayload, AbstractAntDevice device) + { + var fecDevice = device as FitDevice; + if (fecDevice == null) + return; + + var offset = (int)(short)((int)dataPayload[7] | (int)dataPayload[6] << 8); + + fecDevice.DoCalibrationSuccess(offset); + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs.meta b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs.meta new file mode 100644 index 00000000..1119e8fd --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/CalibrationPages/FecCalibrationPage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5af3ac698660b3e4b82e1c6e3b597e19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs b/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs new file mode 100644 index 00000000..45dbaf3d --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Pages +{ + public interface IPageHandler + { + bool CanHandle(byte pageNumber); + + void Handle(byte[] dataPayload, AbstractAntDevice device); + } +} diff --git a/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs.meta b/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs.meta new file mode 100644 index 00000000..56e98db5 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/IPageHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3041b61cfb7f39844a5b465f7d67f48c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs b/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs new file mode 100644 index 00000000..e8a7fd3c --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant.Pages +{ + public class ManufacturerDataPageHandler : IPageHandler + { + private readonly Action _callback; + public ManufacturerDataPageHandler(Action callback) + { + _callback = callback; + } + + + public bool CanHandle(byte pageNumber) + { + return pageNumber == 80; + } + + public void Handle(byte[] dataPayload, AbstractAntDevice device) + { + int hwRevision = dataPayload[3]; + int mfgId = (int)dataPayload[4] | (int)dataPayload[5] << 8; + int modelNumber = (int)((int)dataPayload[6] | (int)dataPayload[7] << 8); + + //device.ManufacturerId = mfgId; + _callback(new ManufacturerDataPageContent(hwRevision, mfgId, modelNumber)); + } + } +} diff --git a/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs.meta b/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs.meta new file mode 100644 index 00000000..47f594b2 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/Pages/ManufacturerDataPageHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e295cfb6fd138343888b4aefe868f2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/SensorType.cs b/Assets/Scripts/Devices/Ant/SensorType.cs new file mode 100644 index 00000000..7b8c6469 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/SensorType.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + public enum racerSportType : byte + { + Biking = 0x00, + Running = 0x01, + Rowing = 0x02, + Skiing = 0x03, + Unknown = 0xFF, + } + + public enum racerSourceType + { + TrackRecord, + WorldRecordPace, + FitEquip, + } + + public enum targetType + { + Seconds, + Meters, + } + + public enum SensorType + { + None, + Cadence, + HeartRate, + Power, + Speed, + SpeedCadence, + Trainer, + VirtualPower, + } +} diff --git a/Assets/Scripts/Devices/Ant/SensorType.cs.meta b/Assets/Scripts/Devices/Ant/SensorType.cs.meta new file mode 100644 index 00000000..c632efbc --- /dev/null +++ b/Assets/Scripts/Devices/Ant/SensorType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b075797e7a977fd4e8ab4dbea18719fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/Ant/UserdChannel.cs b/Assets/Scripts/Devices/Ant/UserdChannel.cs new file mode 100644 index 00000000..2d4dc86b --- /dev/null +++ b/Assets/Scripts/Devices/Ant/UserdChannel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices.Ant +{ + public class UserdChannel + { + public string DeviceNumber { get; set; } + public string DeviceTypeId { get; set; } + public byte Index { get; set; } + } +} diff --git a/Assets/Scripts/Devices/Ant/UserdChannel.cs.meta b/Assets/Scripts/Devices/Ant/UserdChannel.cs.meta new file mode 100644 index 00000000..278a0a42 --- /dev/null +++ b/Assets/Scripts/Devices/Ant/UserdChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab9369d05dedaa44eb00a63d47ac95fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Devices/DeviceValueFilter.cs b/Assets/Scripts/Devices/DeviceValueFilter.cs new file mode 100644 index 00000000..ae153dd3 --- /dev/null +++ b/Assets/Scripts/Devices/DeviceValueFilter.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Assets.Scripts.Devices +{ + static class DeviceValueFilter + { + public const int MaxCadence = 255; + public const int MaxHeartRate = 254; + public const int MaxPower = 2000; + public const double MaxSpeed = 150.0; + + public static int Cadence(int? value) + { + if (value.HasValue) + { + if (value.GetValueOrDefault(0) < MaxCadence) + { + return value.Value; + } + } + return -1; + } + + public static int HeartRate(int? value) + { + if (value.HasValue) + { + if (value.GetValueOrDefault(0) < MaxHeartRate && value.GetValueOrDefault(0) >= 0) + { + return value.Value; + } + } + return -1; + } + + public static int Power(int? value) + { + if (value.HasValue) + { + if (value.GetValueOrDefault(0) < MaxPower && value.GetValueOrDefault(0) >= 0) + { + return value.Value; + } + } + return -1; + } + } +} diff --git a/Assets/Scripts/Devices/DeviceValueFilter.cs.meta b/Assets/Scripts/Devices/DeviceValueFilter.cs.meta new file mode 100644 index 00000000..dc6d8781 --- /dev/null +++ b/Assets/Scripts/Devices/DeviceValueFilter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3aaa2f30cd6bf484b80a372b5f2bcb49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Scenes/MainController.cs b/Assets/Scripts/Scenes/MainController.cs index a71aaf68..22b5b29a 100644 --- a/Assets/Scripts/Scenes/MainController.cs +++ b/Assets/Scripts/Scenes/MainController.cs @@ -8,6 +8,8 @@ public class MainController : MonoBehaviour void Start() { UIManager.Instance.MainPanel = (GameObject)this.transform.Find("Panel").gameObject; + UIManager.Instance.ModalsPanel = this.transform.Find("PanelModals").gameObject; + //MainMenu.transform.Find("Home").GetComponent