接入基本设备
This commit is contained in:
1 parent
2f84f70a5f
commit
7729332f41
62 files changed
+2880
-86
No files matched your search
@@ -0,0 +1,49 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class BatteryLevel : ICharacteristic
|
||||
{
|
||||
public Guid Uuid => ServiceUuids.Characteristics.BatteryLevel;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.Battery).IdGuid;
|
||||
|
||||
private ICharacteristic _characteristicUnavailable = null;
|
||||
public ICharacteristic CharacteristicUnavailable
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._characteristicUnavailable;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsOptional
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int BatteryLevelValue { get; private set; }
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
BatteryLevelValue = (int)data[0];
|
||||
|
||||
Debug.Log($"电量:{ BatteryLevelValue }");
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
this._characteristicUnavailable = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b654b3a52c37e6f47b9823953c8fd5d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class CyclingPowerMeasurement: ICharacteristic
|
||||
{
|
||||
public Guid Uuid
|
||||
{
|
||||
get
|
||||
{
|
||||
return ServiceUuids.Characteristics.CyclingPowerMeasurement;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid ServiceUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
return ServiceUuids.Get(ServiceUuids.CyclingPower).IdGuid;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsOptional
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private double wheelCircumference;
|
||||
|
||||
public int Power { get; private set; }
|
||||
|
||||
public CyclingPowerMeasurement(double wheelCircumference)
|
||||
{
|
||||
this.wheelCircumference = wheelCircumference;
|
||||
}
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
|
||||
this.Power = BitConverter.ToInt16(data, 2);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b0646295dbaa0a4e951de9bd391e475
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,271 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Assets.Scripts.Devices.Ble.Extension;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class CyclingSpeedCadenceMeasurement : ICharacteristic
|
||||
{
|
||||
private CyclingSpeedCadenceMeasurement.IUpdate _currentUpdate;
|
||||
private CyclingSpeedCadenceMeasurement.IUpdate _previousUpdate = new CyclingSpeedCadenceMeasurement.NullUpdate();
|
||||
private const byte MaxNoEvents = (byte)4;
|
||||
private byte _noCadenceEventCount;
|
||||
private byte _noSpeedEventCount;
|
||||
|
||||
|
||||
public Guid Uuid => ServiceUuids.Characteristics.CscMeasurement;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.CyclingSpeedCadence).IdGuid;
|
||||
|
||||
public bool IsOptional => false;
|
||||
|
||||
public double Speed { get; private set; }
|
||||
public int Cadence { get; private set; }
|
||||
|
||||
public double WheelCircumference { private get; set; }
|
||||
|
||||
public CyclingSpeedCadenceMeasurement(double wheelCircumference)
|
||||
{
|
||||
this.WheelCircumference = wheelCircumference;
|
||||
}
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
//Debug.Log(string.Join(",", data));
|
||||
|
||||
this._currentUpdate = new CyclingSpeedCadenceMeasurement.Update(data);
|
||||
this.HandleCadenceUpdate();
|
||||
this.HandleSpeedUpdate();
|
||||
this._previousUpdate = this._currentUpdate;
|
||||
}
|
||||
|
||||
private void HandleCadenceUpdate()
|
||||
{
|
||||
if (this._currentUpdate.HasCadence && (int)this._currentUpdate.CadenceEventCount != (int)this._previousUpdate.CadenceEventCount)
|
||||
{
|
||||
this._noCadenceEventCount = (byte)0;
|
||||
if (this.CadenceTimeDifference() <= 0)
|
||||
return;
|
||||
this.Cadence = this.CalculateCadence();
|
||||
}
|
||||
else
|
||||
{
|
||||
this._noCadenceEventCount = (byte)((uint)this._noCadenceEventCount + 1U);
|
||||
if ((int)this._noCadenceEventCount < 4)
|
||||
return;
|
||||
this.Cadence = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSpeedUpdate()
|
||||
{
|
||||
if (this._currentUpdate.HasSpeed && (int)this._currentUpdate.SpeedEventCount != (int)this._previousUpdate.SpeedEventCount)
|
||||
{
|
||||
this._noSpeedEventCount = (byte)0;
|
||||
double num = this.CalculateSpeed();
|
||||
if (num >= 150.0)
|
||||
return;
|
||||
this.Speed = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._noSpeedEventCount = (byte)((uint)this._noSpeedEventCount + 1U);
|
||||
if ((int)this._noSpeedEventCount < 4)
|
||||
return;
|
||||
this.Speed = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private int CalculateCadence()
|
||||
{
|
||||
int num = this.CadenceEventDifference() * 61440 / this.CadenceTimeDifference();
|
||||
if (num > (int)byte.MaxValue)
|
||||
return (int)byte.MaxValue;
|
||||
if (num < 0)
|
||||
return 0;
|
||||
return num;
|
||||
}
|
||||
|
||||
private int CadenceTimeDifference()
|
||||
{
|
||||
if ((int)this._currentUpdate.CadenceTime1024 > (int)this._previousUpdate.CadenceTime1024)
|
||||
return (int)this._currentUpdate.CadenceTime1024 - (int)this._previousUpdate.CadenceTime1024;
|
||||
return (int)ushort.MaxValue - (int)this._previousUpdate.CadenceTime1024 + (int)this._currentUpdate.CadenceTime1024 + 1;
|
||||
}
|
||||
|
||||
private int CadenceEventDifference()
|
||||
{
|
||||
if ((int)this._currentUpdate.CadenceEventCount > (int)this._previousUpdate.CadenceEventCount)
|
||||
return (int)this._currentUpdate.CadenceEventCount - (int)this._previousUpdate.CadenceEventCount;
|
||||
return (int)ushort.MaxValue - (int)this._previousUpdate.CadenceEventCount + (int)this._currentUpdate.CadenceEventCount + 1;
|
||||
}
|
||||
|
||||
private double CalculateSpeed()
|
||||
{
|
||||
double num = (double)(ulong)(this.WheelCircumference / 10.0 * 36864.0 * (double)this.SpeedEventDifference() / (double)this.SpeedTimeDifference()) / 1000.0;
|
||||
if (num >= 0.0)
|
||||
return num;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private int SpeedTimeDifference()
|
||||
{
|
||||
if ((int)this._currentUpdate.SpeedTime1024 > (int)this._previousUpdate.SpeedTime1024)
|
||||
return (int)this._currentUpdate.SpeedTime1024 - (int)this._previousUpdate.SpeedTime1024;
|
||||
return (int)ushort.MaxValue - (int)this._previousUpdate.SpeedTime1024 + (int)this._currentUpdate.SpeedTime1024 + 1;
|
||||
}
|
||||
|
||||
private uint SpeedEventDifference()
|
||||
{
|
||||
if (this._currentUpdate.SpeedEventCount > this._previousUpdate.SpeedEventCount)
|
||||
return this._currentUpdate.SpeedEventCount - this._previousUpdate.SpeedEventCount;
|
||||
return (uint)(-1 - (int)this._previousUpdate.SpeedEventCount + (int)this._currentUpdate.SpeedEventCount + 1);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private interface IUpdate
|
||||
{
|
||||
bool HasCadence { get; }
|
||||
|
||||
bool HasSpeed { get; }
|
||||
|
||||
uint SpeedEventCount { get; }
|
||||
|
||||
ushort SpeedTime1024 { get; }
|
||||
|
||||
ushort CadenceEventCount { get; }
|
||||
|
||||
ushort CadenceTime1024 { get; }
|
||||
}
|
||||
|
||||
private class Update : CyclingSpeedCadenceMeasurement.IUpdate
|
||||
{
|
||||
private static readonly byte WheelRevolutionsFlagBit = (byte)0;
|
||||
private static readonly byte CrankRevolutionsFlagBit = (byte)1;
|
||||
private readonly byte[] _data;
|
||||
|
||||
private byte Flags
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._data[0];
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return PrimitiveExtensions.IsBitSet(this.Flags, (int)CyclingSpeedCadenceMeasurement.Update.CrankRevolutionsFlagBit);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return PrimitiveExtensions.IsBitSet(this.Flags, (int)CyclingSpeedCadenceMeasurement.Update.WheelRevolutionsFlagBit);
|
||||
}
|
||||
}
|
||||
|
||||
public uint SpeedEventCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitConvertHelper.ToUInt32(this._data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort SpeedTime1024
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitConvertHelper.ToUInt16(this._data, 5);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort CadenceEventCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitConvertHelper.ToUInt16(this._data, this.HasSpeed ? 7 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
public ushort CadenceTime1024
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitConvertHelper.ToUInt16(this._data, this.HasSpeed ? 9 : 3);
|
||||
}
|
||||
}
|
||||
|
||||
public Update(byte[] data)
|
||||
{
|
||||
this._data = data;
|
||||
}
|
||||
}
|
||||
|
||||
private class NullUpdate : CyclingSpeedCadenceMeasurement.IUpdate
|
||||
{
|
||||
public bool HasCadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public uint SpeedEventCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort SpeedTime1024
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ushort)0;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort CadenceEventCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ushort)0;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort CadenceTime1024
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ushort)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ea4d73295288ad4a9f561a37246110a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class FtmsFitnessMachineFeature : ICharacteristic
|
||||
{
|
||||
public Guid Uuid => ServiceUuids.Characteristics.FitnessMachineFeature;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.Ftms).IdGuid;
|
||||
|
||||
public bool IsOptional => false;
|
||||
|
||||
public bool IsInclinationSupported
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public bool IsInclinationTargetSettingSupported
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
if (data.Length != 8)
|
||||
return;
|
||||
this.IsInclinationSupported = ByteExtensions.IsFlagSet(data[0], (byte)8);
|
||||
//this.ResistanceLevelSupported = ByteExtensions.IsFlagSet(data[0], sbyte.MinValue);
|
||||
|
||||
this.IsInclinationTargetSettingSupported = ByteExtensions.IsFlagSet(data[4], 2);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6095c96152da4c47870708061e1d5ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,220 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class FtmsIndoorBikeData : ICharacteristic
|
||||
{
|
||||
private readonly ushort? _instantSpeedSubject = new ushort?();
|
||||
private readonly ushort? _averageSpeedSubject = new ushort?();
|
||||
private readonly ushort? _instantCadenceSubject = new ushort?();
|
||||
private readonly ushort? _averageCadenceSubject = (new ushort?());
|
||||
private readonly uint? _totalDistanceSubject = (new uint?());
|
||||
private readonly short? _resistanceLevelSubject = (new short?());
|
||||
private readonly short? _instantPowerSubject = (new short?());
|
||||
private readonly short? _averagePowerSubject = (new short?());
|
||||
private readonly ushort? _totalEnergySubject = (new ushort?());
|
||||
private readonly ushort? _energyPerHourSubject = (new ushort?());
|
||||
private readonly byte? _energyPerMinuteSubject = (new byte?());
|
||||
private readonly byte? _heartRateSubject = (new byte?());
|
||||
private readonly byte? _metabolicEquivalentSubject = (new byte?());
|
||||
private readonly ushort? _elapsedTimeSubject = (new ushort?());
|
||||
private readonly ushort? _remainingTimeSubject = (new ushort?());
|
||||
|
||||
public short? InstantPower
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._instantPowerSubject;
|
||||
}
|
||||
}
|
||||
public ushort? InstantCadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._instantCadenceSubject;
|
||||
}
|
||||
}
|
||||
public ushort? InstantSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._instantSpeedSubject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Guid Uuid => ServiceUuids.Characteristics.IndoorBikeData;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.Ftms).IdGuid;
|
||||
|
||||
public bool IsOptional => false;
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
if(data.Length < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<FtmsIndoorBikeData.IndoorBikeDataField> list = new List<FtmsIndoorBikeData.IndoorBikeDataField>();
|
||||
if (!ByteExtensions.IsFlagSetAtPosition(data[0], (byte)0))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)1))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)2))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)3))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)4))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)5))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)6))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)7))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AveragePower);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)0))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)1))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.HeartRate);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)2))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)3))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime);
|
||||
if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)4))
|
||||
list.Add(FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime);
|
||||
int offset = 2;
|
||||
foreach (FtmsIndoorBikeData.IndoorBikeDataField field in list)
|
||||
offset += this.ParseField(data, offset, field);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private int ParseField(byte[] attribute, int offset, FtmsIndoorBikeData.IndoorBikeDataField field)
|
||||
{
|
||||
int fieldSize = FtmsIndoorBikeData.GetFieldSize(field);
|
||||
if (attribute.Length < fieldSize + offset)
|
||||
throw new ArgumentException("attribute");
|
||||
switch (field)
|
||||
{
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._instantSpeedSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._averageSpeedSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._instantCadenceSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._averageCadenceSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance:
|
||||
ICharacteristicExtensions.HandleUint24AttributeValue((ICharacteristic)this, attribute, offset, this._totalDistanceSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel:
|
||||
ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._resistanceLevelSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower:
|
||||
ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._instantPowerSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AveragePower:
|
||||
ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._averagePowerSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._totalEnergySubject);
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset + 2, this._energyPerHourSubject);
|
||||
ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset + 4, this._energyPerMinuteSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.HeartRate:
|
||||
ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset, this._heartRateSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent:
|
||||
ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset, this._metabolicEquivalentSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._elapsedTimeSubject);
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime:
|
||||
ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._remainingTimeSubject);
|
||||
break;
|
||||
}
|
||||
return fieldSize;
|
||||
}
|
||||
|
||||
private static int GetFieldSize(FtmsIndoorBikeData.IndoorBikeDataField field)
|
||||
{
|
||||
int num = 0;
|
||||
switch (field)
|
||||
{
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance:
|
||||
num = 3;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.AveragePower:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy:
|
||||
num = 5;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.HeartRate:
|
||||
num = 1;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent:
|
||||
num = 1;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime:
|
||||
num = 2;
|
||||
break;
|
||||
case FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime:
|
||||
num = 2;
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
private enum IndoorBikeDataField
|
||||
{
|
||||
InstantaneousSpeed,
|
||||
AverageSpeed,
|
||||
InstantaneousCadence,
|
||||
AverageCadence,
|
||||
TotalDistance,
|
||||
ResistanceLevel,
|
||||
InstantaneousPower,
|
||||
AveragePower,
|
||||
ExpendedEnergy,
|
||||
HeartRate,
|
||||
MetabolicEquivalent,
|
||||
ElapsedTime,
|
||||
RemainingTime,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3577d5802131984c9463ba280183935
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,5 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -8,7 +9,7 @@ using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class HeartRateMeasurement
|
||||
public class HeartRateMeasurement : ICharacteristic
|
||||
{
|
||||
public Guid Uuid
|
||||
{
|
||||
@@ -26,6 +27,13 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOptional
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private HrmFormat Format { get; set; }
|
||||
|
||||
// Token: 0x170005EB RID: 1515
|
||||
@@ -39,7 +47,7 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
if (this.Format == HrmFormat.Short)
|
||||
{
|
||||
this.BeatsPerMinute = BitConvertHelper.ToUInt8(data, 1);
|
||||
Debug.Log("心率:" + this.BeatsPerMinute);
|
||||
//Debug.Log("心率:" + this.BeatsPerMinute);
|
||||
return;
|
||||
}
|
||||
if (data.Length < 3)
|
||||
@@ -49,6 +57,10 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
this.BeatsPerMinute = BitConvertHelper.ToUInt16(data, 1);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum HrmFlags
|
||||
{
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public static class ICharacteristicExtensions
|
||||
{
|
||||
public static void HandleByteAttributeValue(this ICharacteristic characteristic, byte[] attribute, int offset, byte? subject)
|
||||
{
|
||||
if (attribute.Length < 1 + offset)
|
||||
throw new ArgumentException("attribute");
|
||||
byte num = attribute[offset];
|
||||
subject =new byte?(num);
|
||||
}
|
||||
|
||||
public static void HandleShortAttributeValue(this ICharacteristic characteristic, byte[] attribute, int offset, short? subject)
|
||||
{
|
||||
if (attribute.Length < 2 + offset)
|
||||
throw new ArgumentException("attribute");
|
||||
short num = BitConverter.ToInt16(attribute, offset);
|
||||
subject= new short?(num);
|
||||
}
|
||||
|
||||
public static void HandleUshortAttributeValue(this ICharacteristic characteristic, byte[] attribute, int offset, ushort? subject)
|
||||
{
|
||||
if (attribute.Length < 2 + offset)
|
||||
throw new ArgumentException("attribute");
|
||||
ushort num = BitConverter.ToUInt16(attribute, offset);
|
||||
subject =new ushort?(num);
|
||||
}
|
||||
|
||||
public static void HandleUint24AttributeValue(this ICharacteristic characteristic, byte[] attribute, int offset, uint? subject)
|
||||
{
|
||||
if (attribute.Length < 4 + offset - 1)
|
||||
throw new ArgumentException("attribute");
|
||||
byte[] numArray = new byte[4];
|
||||
Buffer.BlockCopy((Array)attribute, offset, (Array)numArray, 0, 3);
|
||||
uint num = BitConverter.ToUInt32(numArray, 0);
|
||||
subject = (new uint?(num));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 238bc68320174c9429b5958b5207b2c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class ManufacturerNameCharacteristic : ICharacteristic
|
||||
{
|
||||
public Guid Uuid => ServiceUuids.Characteristics.ManufactureNameString;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.DeviceInformation).IdGuid;
|
||||
|
||||
public bool IsOptional => true;
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
Debug.Log(Encoding.UTF8.GetString(data));
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f0a2af64ce8fe84cbdf0e5a14bbc8ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class ModelNumberCharacteristic : ICharacteristic
|
||||
{
|
||||
public Guid Uuid => ServiceUuids.Characteristics.ModelNumber;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.DeviceInformation).IdGuid;
|
||||
|
||||
public bool IsOptional => true;
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
Debug.Log($"model number:\t{ Encoding.UTF8.GetString(data) }");
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef489f56607ba2540b8954b67e1a4d3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,205 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class TacxFecNotify : ICharacteristic
|
||||
{
|
||||
public Guid Uuid => ServiceUuids.Characteristics.TacxFecRead;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.TacxBle).IdGuid;
|
||||
|
||||
public virtual bool IsOptional
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
var responseId = data[2];
|
||||
|
||||
if (responseId != (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var data1 = data.Skip(3).ToArray();
|
||||
var pageNumber = data1[1];
|
||||
switch (pageNumber)
|
||||
{
|
||||
case 16:
|
||||
{
|
||||
HandleGeneralDataPage(data1.Skip(1).ToArray());
|
||||
}
|
||||
break;
|
||||
case 19:
|
||||
{
|
||||
//lastInstCadence = data1[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 = data1[5];
|
||||
//lastInstPower = (ushort)(data1[6] + (data1[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(data1.Skip(1).ToArray());
|
||||
break;
|
||||
default:
|
||||
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 virtual void SetUnavailable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 640f21041d0bf6347b1e48669c9a8691
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using Assets.Scripts.Ble;
|
||||
using Assets.Scripts.Devices.Ble.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
public class TacxFecWrite : ICharacteristic
|
||||
{
|
||||
public virtual bool IsOptional
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid Uuid => ServiceUuids.Characteristics.TacxFecRead;
|
||||
|
||||
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.TacxBle).IdGuid;
|
||||
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void WriteMessageToControlPoint()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void SetUnavailable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c9564a0124aa5946b25bdd1a97ade2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user