From bad07e1ec9dabf4741b283cf88506a178468fd74 Mon Sep 17 00:00:00 2001 From: Anja Date: Tue, 20 Sep 2022 13:51:55 +0200 Subject: [PATCH] Version 3.0.340 --- LastenradBayern/TINK.Android/MainActivity.cs | 10 +- .../Properties/AndroidManifest.xml | 2 +- LastenradBayern/TINK.iOS/Info.plist | 4 +- .../BikesAtStation/BikesAtStationPage.xaml | 241 ++++++++--------- .../View/CopriWebView/ManageAccountPage.xaml | 18 +- .../CopriWebView/PasswordForgottenPage.xaml | 18 +- .../TINK/View/CopriWebView/RegisterPage.xaml | 18 +- .../TINK/View/FindBike/FindBikePage.xaml | 133 +++++---- LastenradBayern/TINK/View/Map/MapPage.xaml | 252 ++++++++---------- .../TINK/View/MyBikes/MyBikesPage.xaml | 126 ++++----- .../Services/BluetoothLock/BLE/LockItBase.cs | 125 ++++++++- .../BluetoothLock/BLE/LockItByScanService.cs | 4 + LockItShared/LockItShared.csproj | 1 - .../Bikes/Bike/BluetoothLock/LockInfo.cs | 30 +-- .../Services/BluetoothLock/ILockService.cs | 13 +- .../Services/BluetoothLock/NullLock.cs | 9 +- .../BluetoothLock/Tdo/VersionInfoTdo.cs | 41 +++ .../Properties/AndroidManifest.xml | 2 +- Meinkonrad/TINK.iOS/Info.plist | 4 +- .../BikesAtStation/BikesAtStationPage.xaml | 201 +++++++------- .../View/CopriWebView/ManageAccountPage.xaml | 18 +- .../CopriWebView/PasswordForgottenPage.xaml | 18 +- .../TINK/View/CopriWebView/RegisterPage.xaml | 18 +- .../TINK/View/FindBike/FindBikePage.xaml | 134 +++++----- Meinkonrad/TINK/View/Map/MapPage.xaml | 225 ++++++++-------- Meinkonrad/TINK/View/MyBikes/MyBikesPage.xaml | 127 +++++---- TINK/TINK.Android/MainActivity.cs | 10 +- .../Properties/AndroidManifest.xml | 2 +- TINK/TINK.iOS/Info.plist | 4 +- .../BikeInfoNS/BluetoothLock/BikeInfo.cs | 27 +- .../BluetoothLock/ILockInfoMutable.cs | 7 +- .../BikeInfoNS/BluetoothLock/IVersionInfo.cs | 20 ++ .../BluetoothLock/LockInfoMutable.cs | 23 +- .../BikeInfoNS/BluetoothLock/VersionInfo.cs | 69 +++++ .../Connector/Command/CommandLoggedIn.cs | 7 +- TINKLib/Model/WhatsNew.cs | 10 + .../AppResources.Designer.cs | 9 + .../AppResources.de.resx | 3 + .../MultilingualResources/AppResources.resx | 3 + TINKLib/MultilingualResources/TINKLib.de.xlf | 4 + TINKLib/Repository/CopriCallsHttps.cs | 8 +- TINKLib/Repository/CopriCallsMemory.cs | 6 +- TINKLib/Repository/CopriCallsMonkeyStore.cs | 6 +- TINKLib/Repository/ICopriServer.cs | 6 +- TINKLib/Repository/Request/IRequestBuilder.cs | 9 +- TINKLib/Repository/Request/RequestBuilder.cs | 9 +- .../Request/RequestBuilderLoggedIn.cs | 12 +- .../Services/CopriApi/CopriProviderHttps.cs | 11 +- .../CopriApi/CopriProviderMonkeyStore.cs | 9 +- TINKLib/View/Themes/Konrad.xaml | 18 +- TINKLib/View/Themes/LastenradBayern.xaml | 155 ++++++----- .../RequestHandler/BookedClosed.cs | 19 +- .../RequestHandler/BookedUnknown.cs | 17 +- .../RequestHandler/DisposableDisconnected.cs | 21 +- .../RequestHandler/ReservedClosed.cs | 19 +- .../RequestHandler/ReservedDisconnected.cs | 21 +- .../RequestHandler/ReservedUnknown.cs | 19 +- .../Repository/CopriCallMemoryBase.cs | 6 +- TestFramework/Repository/ExceptionServer.cs | 6 +- .../CopriApi/CopriCallsCacheMemory001.cs | 6 +- .../Request/TestRequestBuilderLoggedIn.cs | 22 +- .../Mocks/Connector/CopriCallsCacheMemory.cs | 6 +- 62 files changed, 1401 insertions(+), 1000 deletions(-) create mode 100644 LockItShared/Services/BluetoothLock/Tdo/VersionInfoTdo.cs create mode 100644 TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/IVersionInfo.cs create mode 100644 TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/VersionInfo.cs diff --git a/LastenradBayern/TINK.Android/MainActivity.cs b/LastenradBayern/TINK.Android/MainActivity.cs index 1eea213..73b8b94 100644 --- a/LastenradBayern/TINK.Android/MainActivity.cs +++ b/LastenradBayern/TINK.Android/MainActivity.cs @@ -1,4 +1,4 @@ - + using Android.App; using Android.Content; using Android.Content.PM; @@ -18,15 +18,15 @@ namespace TINK.Droid [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, DataScheme = "https", - DataHost = "sharee.bike", - DataPathPrefix = "/lastenrad", + DataHost = "app.sharee.bike", + DataPathPrefix = "/App-LastenradBayern", AutoVerify = true)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, DataScheme = "http", - DataHost = "sharee.bike", - DataPathPrefix = "/lastenrad", + DataHost = "app.sharee.bike", + DataPathPrefix = "/App-LastenradBayern", AutoVerify = true)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity diff --git a/LastenradBayern/TINK.Android/Properties/AndroidManifest.xml b/LastenradBayern/TINK.Android/Properties/AndroidManifest.xml index 8a2a8df..a50a376 100644 --- a/LastenradBayern/TINK.Android/Properties/AndroidManifest.xml +++ b/LastenradBayern/TINK.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/LastenradBayern/TINK.iOS/Info.plist b/LastenradBayern/TINK.iOS/Info.plist index 763ff40..3ad9e81 100644 --- a/LastenradBayern/TINK.iOS/Info.plist +++ b/LastenradBayern/TINK.iOS/Info.plist @@ -55,8 +55,8 @@ CFBundleDisplayName LastenradBayern CFBundleVersion - 339 + 340 CFBundleShortVersionString - 3.0.339 + 3.0.340 diff --git a/LastenradBayern/TINK/View/BikesAtStation/BikesAtStationPage.xaml b/LastenradBayern/TINK/View/BikesAtStation/BikesAtStationPage.xaml index c37d14a..271c423 100644 --- a/LastenradBayern/TINK/View/BikesAtStation/BikesAtStationPage.xaml +++ b/LastenradBayern/TINK/View/BikesAtStation/BikesAtStationPage.xaml @@ -1,137 +1,106 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.BikesAtStation.BikesAtStationPage" + xmlns:local_bike="clr-namespace:TINK.View.Bike" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LastenradBayern/TINK/View/CopriWebView/ManageAccountPage.xaml b/LastenradBayern/TINK/View/CopriWebView/ManageAccountPage.xaml index 7d1d5fa..13183d1 100644 --- a/LastenradBayern/TINK/View/CopriWebView/ManageAccountPage.xaml +++ b/LastenradBayern/TINK/View/CopriWebView/ManageAccountPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/LastenradBayern/TINK/View/CopriWebView/PasswordForgottenPage.xaml b/LastenradBayern/TINK/View/CopriWebView/PasswordForgottenPage.xaml index 8d5e2f6..7c54cf5 100644 --- a/LastenradBayern/TINK/View/CopriWebView/PasswordForgottenPage.xaml +++ b/LastenradBayern/TINK/View/CopriWebView/PasswordForgottenPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/LastenradBayern/TINK/View/CopriWebView/RegisterPage.xaml b/LastenradBayern/TINK/View/CopriWebView/RegisterPage.xaml index 8c9200f..3b39d6e 100644 --- a/LastenradBayern/TINK/View/CopriWebView/RegisterPage.xaml +++ b/LastenradBayern/TINK/View/CopriWebView/RegisterPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/LastenradBayern/TINK/View/FindBike/FindBikePage.xaml b/LastenradBayern/TINK/View/FindBike/FindBikePage.xaml index 4a1e82a..294b21b 100644 --- a/LastenradBayern/TINK/View/FindBike/FindBikePage.xaml +++ b/LastenradBayern/TINK/View/FindBike/FindBikePage.xaml @@ -1,68 +1,67 @@ - + - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.FindBike.FindBikePage" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:local_bike="clr-namespace:TINK.View.Bike" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"> + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" + xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + BackgroundColor="{DynamicResource Key=primary-back-title-color}" + x:Class="TINK.View.Map.MapPage"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LastenradBayern/TINK/View/MyBikes/MyBikesPage.xaml b/LastenradBayern/TINK/View/MyBikes/MyBikesPage.xaml index 4cbcdde..0af7499 100644 --- a/LastenradBayern/TINK/View/MyBikes/MyBikesPage.xaml +++ b/LastenradBayern/TINK/View/MyBikes/MyBikesPage.xaml @@ -1,64 +1,64 @@ - + - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.MyBikes.MyBikesPage" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" + xmlns:local_bike="clr-namespace:TINK.View.Bike"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LockItBLE/Services/BluetoothLock/BLE/LockItBase.cs b/LockItBLE/Services/BluetoothLock/BLE/LockItBase.cs index 403f5ec..e435072 100644 --- a/LockItBLE/Services/BluetoothLock/BLE/LockItBase.cs +++ b/LockItBLE/Services/BluetoothLock/BLE/LockItBase.cs @@ -83,6 +83,8 @@ namespace TINK.Services.BluetoothLock.BLE private ICharacteristic BatteryCharacteristic { get; set; } + private ICharacteristic FirmwareVersionCharacteristic { get; set; } + private readonly AsyncRetryPolicy _retryPollicy; /// Gets the lock control service. @@ -301,6 +303,27 @@ namespace TINK.Services.BluetoothLock.BLE return BatteryCharacteristic; } + /// Gets the versions info characteristic. + protected async Task GetVersionsCharacteristicAsync() + { + if (FirmwareVersionCharacteristic != null) return FirmwareVersionCharacteristic ; + + FirmwareVersionCharacteristic = null; + + Log.ForContext().Debug("Request to get versions info characteristic."); + try + { + FirmwareVersionCharacteristic = await (await GetLockControlService())?.GetCharacteristicAsync(new Guid("0000baad-1212-efde-1523-785fef13d123")); + } + catch (System.Exception exception) + { + Log.ForContext().Error("Getting versions info charcteristic failed. {Exception}", exception); + throw new System.Exception(string.Format("Can not get versions info characteristic. {0}", exception.Message), exception); + } + + Log.ForContext().Debug("Get versions info characteristic retrieved successfully."); + return FirmwareVersionCharacteristic ; + } /// Query name of lock. private void GetName() { @@ -822,12 +845,12 @@ namespace TINK.Services.BluetoothLock.BLE throw new CoundntGetCharacteristicException("Can not get battery percentage. State characteristic must not be null."); } - byte[] state; + byte[] percentage; var cts = new CancellationTokenSource(); cts.CancelAfter(READ_TIMEOUT_MS); try { - state = await batteryCharacteristic.ReadAsync(cts.Token); + percentage = await batteryCharacteristic.ReadAsync(cts.Token); } catch (System.Exception exception) { @@ -839,17 +862,109 @@ namespace TINK.Services.BluetoothLock.BLE cts.Dispose(); } - if (state == null || state.Length <= 0) + if (percentage == null || percentage.Length <= 0) { Log.ForContext().Debug("Retrieving charging level (ReadAsync-call) failed. Data read is null or empty.{BatteryCharacteristic}", ToSerilogString(batteryCharacteristic)); throw new System.Exception("Can not get battery percentage. No data read."); } - Log.ForContext().Debug("Retrieving charging level (ReadAsync-call) succeeded.{Level}{BatteryCharacteristic}{Reading}", state[0], ToSerilogString(batteryCharacteristic), state); + Log.ForContext().Debug("Retrieving charging level (ReadAsync-call) succeeded.{Level}{BatteryCharacteristic}{Reading}", percentage[0], ToSerilogString(batteryCharacteristic), percentage); - return state[0]; + return percentage[0]; } + /// Gets version info about the lock. + /// + /// Lock state is first byte of of value read from state characteristic ("0000baaa-1212-efde-1523-785fef13d123"). + /// Values are as follows + /// Byte number 0: firmware version, + /// Byte number 1: lock version (2 – classic, 3 – plus, 4 – GPS) + /// Byte number 2: hardware version, + /// + /// . + public async Task GetVersionInfoAsync() + { + if (DeviceInfo.Platform != DevicePlatform.Unknown && MainThread.IsMainThread == false) + { + throw new System.Exception("Can not get versions info. Platform must not be unknown and bluetooth code must be run on main thread."); + } + + DeviceState? deviceState; + Log.ForContext().Debug("Request to get connection state in context of getting versions info."); + try + { + deviceState = Device?.State.GetDeviceState() + ?? throw new System.Exception("Can not get bluetooth device state. State must not be null."); + } + catch (System.Exception exception) + { + Log.ForContext().Error("Can not get versions info. Retrieving bluetooth state failed. {Exception}", exception); + throw new System.Exception(string.Format("Can not get versions info. Getting bluetooth state failed. {0}", exception.Message), exception); + } + + switch (deviceState) + { + case DeviceState.Disconnected: + throw new BluetoothDisconnectedException(); + + case DeviceState.Connected: + break; + + default: + // Can not get state if device is not connected. + Log.ForContext().Error($"Getting versions info failed. Unexpected versions info {deviceState} detected."); + throw new System.Exception(string.Format("Can not get versions info. Unexpected bluetooth state {0} detected.", deviceState)); + } + + Log.ForContext().Debug($"Connection state is {deviceState}."); + + var firmwareVersionCharacteristic = await GetVersionsCharacteristicAsync(); + if (firmwareVersionCharacteristic == null) + { + Log.ForContext().Error($"Can not get versions info. versions info characteristic is not available."); + throw new CoundntGetCharacteristicException("Can not get versions info. versions info characteristic must not be null."); + } + + byte[] version; + var cts = new CancellationTokenSource(); + cts.CancelAfter(READ_TIMEOUT_MS); + try + { + version = await firmwareVersionCharacteristic.ReadAsync(cts.Token); + } + catch (System.Exception exception) + { + Log.ForContext().Error("Retrieving versions info (ReadAsync-call) failed inside delegate.{StateCharacteristic}{Exception}", ToSerilogString(firmwareVersionCharacteristic), exception); + throw; + } + finally + { + cts.Dispose(); + } + + if (version == null || version.Length <= 0) + { + Log.ForContext().Debug("Retrieving versions info (ReadAsync-call) failed. Data read is null or empty.{StateCharacteristic}", ToSerilogString(firmwareVersionCharacteristic)); + throw new System.Exception("Can not get versions info. No data read"); + } + + VersionInfo = new VersionInfoTdo.Builder + { + FirmwareVersion = version[0], + LockVersion = version[1], + HardwareVersion = version[2] + }.Build(); + + Log.ForContext().Debug("Retrieving versions info (ReadAsync-call) succeeded. {@LockInfoTdo}{StateCharacteristic}{Reading}", + VersionInfo, + ToSerilogString(firmwareVersionCharacteristic), + version); + + return VersionInfo; + } + + public VersionInfoTdo VersionInfo { get; private set; } + /// Opens lock. /// Locking state. public abstract Task OpenAsync(); diff --git a/LockItBLE/Services/BluetoothLock/BLE/LockItByScanService.cs b/LockItBLE/Services/BluetoothLock/BLE/LockItByScanService.cs index a63cae8..be1867c 100644 --- a/LockItBLE/Services/BluetoothLock/BLE/LockItByScanService.cs +++ b/LockItBLE/Services/BluetoothLock/BLE/LockItByScanService.cs @@ -151,6 +151,8 @@ namespace TINK.Services.BluetoothLock.BLE DeviceList.Add(lockIt); + await lockIt.GetVersionInfoAsync(); + return await lockIt.GetLockStateAsync(); } @@ -230,6 +232,8 @@ namespace TINK.Services.BluetoothLock.BLE Log.ForContext().Debug($"Auth succeeded for device {device}."); locksList.Add(lockIt); + + await lockIt.GetVersionInfoAsync(); } return locksList; diff --git a/LockItShared/LockItShared.csproj b/LockItShared/LockItShared.csproj index 5235d76..08df52f 100644 --- a/LockItShared/LockItShared.csproj +++ b/LockItShared/LockItShared.csproj @@ -20,7 +20,6 @@ - diff --git a/LockItShared/Model/Bikes/Bike/BluetoothLock/LockInfo.cs b/LockItShared/Model/Bikes/Bike/BluetoothLock/LockInfo.cs index 8f659ba..dd01bd9 100644 --- a/LockItShared/Model/Bikes/Bike/BluetoothLock/LockInfo.cs +++ b/LockItShared/Model/Bikes/Bike/BluetoothLock/LockInfo.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.Serialization; using Newtonsoft.Json; using TINK.Model.Connector; @@ -53,39 +53,32 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock public bool IsGuidValid => Guid != TextToLockItTypeHelper.INVALIDLOCKGUID; - public override bool Equals(object obj) => this.Equals(obj as LockInfo); + public override bool Equals(object obj) + => Equals(obj as LockInfo); public bool Equals(LockInfo other) { - if (Object.ReferenceEquals(other, null)) return false; - if (Object.ReferenceEquals(this, other)) return true; - if (this.GetType() != other.GetType()) return false; + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + if (GetType() != other.GetType()) return false; return ToString() == other.ToString(); } - public override int GetHashCode() - { - return ToString().GetHashCode(); - } + public override int GetHashCode() => ToString().GetHashCode(); - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } + public override string ToString() => JsonConvert.SerializeObject(this); public static bool operator ==(LockInfo lhs, LockInfo rhs) { - if (Object.ReferenceEquals(lhs, null)) - return Object.ReferenceEquals(rhs, null) ? true /*null == null = true*/: false; + if (ReferenceEquals(lhs, null)) + return ReferenceEquals(rhs, null) ? true /*null == null = true*/: false; return lhs.Equals(rhs); } public static bool operator !=(LockInfo lhs, LockInfo rhs) - { - return !(lhs == rhs); - } + => !(lhs == rhs); public class Builder { @@ -127,6 +120,5 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock return LockInfo; } } - } } diff --git a/LockItShared/Services/BluetoothLock/ILockService.cs b/LockItShared/Services/BluetoothLock/ILockService.cs index a184873..b17d160 100644 --- a/LockItShared/Services/BluetoothLock/ILockService.cs +++ b/LockItShared/Services/BluetoothLock/ILockService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using TINK.Services.BluetoothLock.Tdo; @@ -49,6 +49,17 @@ namespace TINK.Services.BluetoothLock Task GetIsAlarmOffAsync(); + /// + /// Get info about lock firmware- hardware- and lock-version. + /// + /// Lock versions info. + Task GetVersionInfoAsync(); + + /// + /// Holds info about lock firmware- hardware- and lock-version, null if info has not yet been read. + /// + VersionInfoTdo VersionInfo { get; } + Task SetIsAlarmOffAsync(bool isActivated); /// Gets the battery percentage. diff --git a/LockItShared/Services/BluetoothLock/NullLock.cs b/LockItShared/Services/BluetoothLock/NullLock.cs index d0d455a..88d7abb 100644 --- a/LockItShared/Services/BluetoothLock/NullLock.cs +++ b/LockItShared/Services/BluetoothLock/NullLock.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using TINK.Services.BluetoothLock.Tdo; @@ -37,6 +37,13 @@ namespace TINK.Services.BluetoothLock public Task GetBatteryPercentageAsync() => throw new System.Exception($"Can not get battery percentage. Lock {BikeId} not found."); + public Task GetVersionInfoAsync() => + throw new System.Exception($"Can not get versions. Lock {BikeId} not found."); + + public VersionInfoTdo VersionInfo + { + get => throw new System.Exception($"Can not get versions. Lock {BikeId} not found."); + } public DeviceState? GetDeviceState() => throw new NotImplementedException(); diff --git a/LockItShared/Services/BluetoothLock/Tdo/VersionInfoTdo.cs b/LockItShared/Services/BluetoothLock/Tdo/VersionInfoTdo.cs new file mode 100644 index 0000000..2bcfe9c --- /dev/null +++ b/LockItShared/Services/BluetoothLock/Tdo/VersionInfoTdo.cs @@ -0,0 +1,41 @@ +namespace TINK.Services.BluetoothLock.Tdo +{ + public class VersionInfoTdo + { + /// + /// Holds info about firmware- and hardware version of a lock and the type of lock (lock version). + /// + private VersionInfoTdo() { } + + /// + /// Holds the firmware version of the lock. + /// + public int FirmwareVersion { get; private set; } + + /// + /// Holds the hardware version (revision) of the lock. + /// + public int HardwareVersion { get; private set; } + + /// + /// Holds lock version (2 – classic, 3 – plus, 4 – GPS). + /// + public int LockVersion { get; private set; } + + public class Builder + { + private VersionInfoTdo lockVersionTdo = new VersionInfoTdo(); + + public int FirmwareVersion { get => lockVersionTdo.FirmwareVersion; set => lockVersionTdo.FirmwareVersion = value; } + + public int HardwareVersion { get => lockVersionTdo.HardwareVersion; set => lockVersionTdo.HardwareVersion = value; } + + public int LockVersion { get => lockVersionTdo.LockVersion; set => lockVersionTdo.LockVersion = value; } + + public VersionInfoTdo Build() + { + return lockVersionTdo; + } + } + } +} diff --git a/Meinkonrad/TINK.Android/Properties/AndroidManifest.xml b/Meinkonrad/TINK.Android/Properties/AndroidManifest.xml index 204b1c9..462ba1b 100644 --- a/Meinkonrad/TINK.Android/Properties/AndroidManifest.xml +++ b/Meinkonrad/TINK.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/Meinkonrad/TINK.iOS/Info.plist b/Meinkonrad/TINK.iOS/Info.plist index 506f30a..b632d4f 100644 --- a/Meinkonrad/TINK.iOS/Info.plist +++ b/Meinkonrad/TINK.iOS/Info.plist @@ -55,8 +55,8 @@ CFBundleDisplayName Mein konrad CFBundleVersion - 339 + 340 CFBundleShortVersionString - 3.0.339 + 3.0.340 diff --git a/Meinkonrad/TINK/View/BikesAtStation/BikesAtStationPage.xaml b/Meinkonrad/TINK/View/BikesAtStation/BikesAtStationPage.xaml index fbb92ec..80282da 100644 --- a/Meinkonrad/TINK/View/BikesAtStation/BikesAtStationPage.xaml +++ b/Meinkonrad/TINK/View/BikesAtStation/BikesAtStationPage.xaml @@ -1,96 +1,107 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.BikesAtStation.BikesAtStationPage" + xmlns:local_bike="clr-namespace:TINK.View.Bike" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Meinkonrad/TINK/View/CopriWebView/ManageAccountPage.xaml b/Meinkonrad/TINK/View/CopriWebView/ManageAccountPage.xaml index f43129a..631b5c6 100644 --- a/Meinkonrad/TINK/View/CopriWebView/ManageAccountPage.xaml +++ b/Meinkonrad/TINK/View/CopriWebView/ManageAccountPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/Meinkonrad/TINK/View/CopriWebView/PasswordForgottenPage.xaml b/Meinkonrad/TINK/View/CopriWebView/PasswordForgottenPage.xaml index e8f2ed5..063ffc5 100644 --- a/Meinkonrad/TINK/View/CopriWebView/PasswordForgottenPage.xaml +++ b/Meinkonrad/TINK/View/CopriWebView/PasswordForgottenPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/Meinkonrad/TINK/View/CopriWebView/RegisterPage.xaml b/Meinkonrad/TINK/View/CopriWebView/RegisterPage.xaml index 8a8da80..f774713 100644 --- a/Meinkonrad/TINK/View/CopriWebView/RegisterPage.xaml +++ b/Meinkonrad/TINK/View/CopriWebView/RegisterPage.xaml @@ -1,4 +1,4 @@ - + - - + + + - \ No newline at end of file + diff --git a/Meinkonrad/TINK/View/FindBike/FindBikePage.xaml b/Meinkonrad/TINK/View/FindBike/FindBikePage.xaml index bfc48b8..294b21b 100644 --- a/Meinkonrad/TINK/View/FindBike/FindBikePage.xaml +++ b/Meinkonrad/TINK/View/FindBike/FindBikePage.xaml @@ -1,69 +1,67 @@ - + - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.FindBike.FindBikePage" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:local_bike="clr-namespace:TINK.View.Bike" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"> + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" + xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + x:Class="TINK.View.Map.MapPage" + BackgroundColor="{DynamicResource Key=primary-back-title-color}"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Meinkonrad/TINK/View/MyBikes/MyBikesPage.xaml b/Meinkonrad/TINK/View/MyBikes/MyBikesPage.xaml index 56ad9b3..0af7499 100644 --- a/Meinkonrad/TINK/View/MyBikes/MyBikesPage.xaml +++ b/Meinkonrad/TINK/View/MyBikes/MyBikesPage.xaml @@ -1,65 +1,64 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.MyBikes.MyBikesPage" + xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" + xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" + xmlns:local_bike="clr-namespace:TINK.View.Bike"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TINK/TINK.Android/MainActivity.cs b/TINK/TINK.Android/MainActivity.cs index 60b3f70..448af9c 100644 --- a/TINK/TINK.Android/MainActivity.cs +++ b/TINK/TINK.Android/MainActivity.cs @@ -1,4 +1,4 @@ - + using Android.App; using Android.Content; using Android.Content.PM; @@ -17,15 +17,15 @@ namespace TINK.Droid [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, DataScheme = "https", - DataHost = "sharee.bike", - DataPathPrefix = "/sharee", + DataHost = "app.sharee.bike", + DataPathPrefix = "/App-shareebike", AutoVerify = true)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, DataScheme = "http", - DataHost = "sharee.bike", - DataPathPrefix = "/sharee", + DataHost = "app.sharee.bike", + DataPathPrefix = "/App-shareebike", AutoVerify = true)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity diff --git a/TINK/TINK.Android/Properties/AndroidManifest.xml b/TINK/TINK.Android/Properties/AndroidManifest.xml index c1a5910..a4ffe24 100644 --- a/TINK/TINK.Android/Properties/AndroidManifest.xml +++ b/TINK/TINK.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/TINK/TINK.iOS/Info.plist b/TINK/TINK.iOS/Info.plist index 55fc5ca..105ac37 100644 --- a/TINK/TINK.iOS/Info.plist +++ b/TINK/TINK.iOS/Info.plist @@ -55,8 +55,8 @@ CFBundleDisplayName sharee.bike CFBundleVersion - 339 + 340 CFBundleShortVersionString - 3.0.339 + 3.0.340 diff --git a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/BikeInfo.cs b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/BikeInfo.cs index d5f17aa..58e08b6 100644 --- a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/BikeInfo.cs +++ b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/BikeInfo.cs @@ -1,13 +1,12 @@ -using System; +using System; using System.Collections.Generic; using TINK.Model.Bikes.BikeInfoNS.BikeNS; using TINK.Model.Bikes.BikeInfoNS.DriveNS; using TINK.Model.State; - namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock { - public class BikeInfo : Model.Bikes.BikeInfoNS.BC.BikeInfo, IBikeInfo + public class BikeInfo : BC.BikeInfo, IBikeInfo { /// /// Constructs a bike info object for a available bike. @@ -18,7 +17,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock /// Holds the uri of the operator or null, in case of single operator setup. /// Hold tariff description of bike. public BikeInfo( - BikeNS.Bike bike, + Bike bike, Drive drive, int lockId, Guid lockGuid, @@ -29,7 +28,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock IEnumerable group = null) : base( new StateInfo(), bike != null - ? new BikeNS.Bike( + ? new Bike( bike.Id, LockModel.ILockIt /* Ensure consistend lock model value */, bike.WheelType, @@ -43,7 +42,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock operatorUri, tariffDescription) { - LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder { Id = lockId, Guid = lockGuid }.Build(); + LockInfo = new LockInfo.Builder { Id = lockId, Guid = lockGuid }.Build(); } /// @@ -59,7 +58,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock /// Hold tariff description of bike. /// Date time provider to calculate reaining time. public BikeInfo( - BikeNS.Bike bike, + Bike bike, Drive drive, int lockId, Guid lockGuid, @@ -80,7 +79,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock mailAddress, ""), bike != null - ? new BikeNS.Bike( + ? new Bike( bike.Id, LockModel.ILockIt /* Ensure consistend lock model value */, bike.WheelType, @@ -94,7 +93,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock operatorUri, tariffDescription) { - LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder { Id = lockId, Guid = lockGuid, UserKey = userKey, AdminKey = adminKey, Seed = seed }.Build(); + LockInfo = new LockInfo.Builder { Id = lockId, Guid = lockGuid, UserKey = userKey, AdminKey = adminKey, Seed = seed }.Build(); } /// @@ -110,7 +109,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock /// Hold tariff description of bike. /// public BikeInfo( - BikeNS.Bike bike, + Bike bike, Drive drive, int lockId, Guid lockGuid, @@ -129,7 +128,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock mailAddress, ""), bike != null - ? new BikeNS.Bike( + ? new Bike( bike.Id, LockModel.ILockIt /* Ensure consistend lock model value */, bike.WheelType, @@ -143,16 +142,16 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock operatorUri, tariffDescription) { - LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder { Id = lockId, Guid = lockGuid, UserKey = userKey, AdminKey = adminKey, Seed = seed }.Build(); + LockInfo = new LockInfo.Builder { Id = lockId, Guid = lockGuid, UserKey = userKey, AdminKey = adminKey, Seed = seed }.Build(); } - public BikeInfo(Model.Bikes.BikeInfoNS.BC.BikeInfo bikeInfo, Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo lockInfo) : base( + public BikeInfo(Model.Bikes.BikeInfoNS.BC.BikeInfo bikeInfo, LockInfo lockInfo) : base( bikeInfo ?? throw new ArgumentException($"Can not copy-construct {typeof(BikeInfo).Name}-object. Source bike info must not be null.")) { LockInfo = lockInfo ?? throw new ArgumentException($"Can not copy-construct {typeof(BikeInfo).Name}-object. Source lock object must not be null."); } - public Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo LockInfo { get; private set; } + public LockInfo LockInfo { get; private set; } } } diff --git a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/ILockInfoMutable.cs b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/ILockInfoMutable.cs index 2066512..b4b1af4 100644 --- a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/ILockInfoMutable.cs +++ b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/ILockInfoMutable.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock { @@ -19,5 +19,10 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock Guid Guid { get; set; } byte[] Seed { get; } + + /// + /// Gets the version info of the locks. + /// + IVersionInfo VersionInfo { get; set; } } } diff --git a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/IVersionInfo.cs b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/IVersionInfo.cs new file mode 100644 index 0000000..e5c3960 --- /dev/null +++ b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/IVersionInfo.cs @@ -0,0 +1,20 @@ +namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock +{ + public interface IVersionInfo + { + /// + /// Holds the firmware version of the lock. + /// + int FirmwareVersion { get; } + + /// + /// Holds the hardware version (revision) of the lock. + /// + int HardwareVersion { get; } + + /// + /// Holds lock version (2 – classic, 3 – plus, 4 – GPS). + /// + int LockVersion { get; } + } +} diff --git a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/LockInfoMutable.cs b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/LockInfoMutable.cs index 4dd02c2..bda72f1 100644 --- a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/LockInfoMutable.cs +++ b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/LockInfoMutable.cs @@ -1,11 +1,11 @@ -using System; +using System; namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock { - public class LockInfoMutable : TINK.Model.Bikes.BikeInfoNS.BluetoothLock.ILockInfoMutable + public class LockInfoMutable : ILockInfoMutable { /// Lock info object. - private Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo LockInfo { get; set; } + private LockInfo LockInfo { get; set; } /// Constructs a bluetooth lock info object. /// Id of lock must always been known when constructing an lock info object. @@ -15,9 +15,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock byte[] userKey, byte[] adminKey, byte[] seed, - Model.Bikes.BikeInfoNS.BluetoothLock.LockingState state) + LockingState state) { - LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder() { Id = id, Guid = guid, UserKey = userKey, AdminKey = adminKey, Seed = seed, State = state }.Build(); + LockInfo = new LockInfo.Builder() { Id = id, Guid = guid, UserKey = userKey, AdminKey = adminKey, Seed = seed, State = state }.Build(); } public int Id => LockInfo.Id; @@ -26,7 +26,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock public Guid Guid { get => LockInfo.Guid; - set => LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder(LockInfo) { Guid = value }.Build(); + set => LockInfo = new LockInfo.Builder(LockInfo) { Guid = value }.Build(); } public byte[] Seed => LockInfo.Seed; @@ -35,19 +35,24 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock public byte[] AdminKey => LockInfo.AdminKey; - public Model.Bikes.BikeInfoNS.BluetoothLock.LockingState State + public LockingState State { get => LockInfo.State; - set => LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder(LockInfo) { State = value }.Build(); + set => LockInfo = new LockInfo.Builder(LockInfo) { State = value }.Build(); } /// Holds the percentage of lock battery. public double BatteryPercentage { get; set; } = double.NaN; + /// + /// Gets the version info of the lock. + /// + public IVersionInfo VersionInfo { get; set; } = new VersionInfo.Builder().Build(); + /// Loads lock info object from values. public void Load(int id, Guid guid, byte[] seed, byte[] userKey, byte[] adminKey) { - LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder(LockInfo) { Id = id, Guid = guid, Seed = seed, UserKey = userKey, AdminKey = adminKey }.Build(); + LockInfo = new LockInfo.Builder(LockInfo) { Id = id, Guid = guid, Seed = seed, UserKey = userKey, AdminKey = adminKey }.Build(); } } } diff --git a/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/VersionInfo.cs b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/VersionInfo.cs new file mode 100644 index 0000000..ca83bd2 --- /dev/null +++ b/TINKLib/Model/Bikes/BikeInfoNS/BluetoothLock/VersionInfo.cs @@ -0,0 +1,69 @@ +using Newtonsoft.Json; + +namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock +{ + public class VersionInfo : IVersionInfo + { + /// + /// Holds info about firmware- and hardware version of a lock and the type of lock (lock version). + /// + private VersionInfo() { } + + /// + /// Holds the firmware version of the lock. + /// + public int FirmwareVersion { get; private set; } = 0; + + /// + /// Holds the hardware version (revision) of the lock. + /// + public int HardwareVersion { get; private set; } = 0; + + /// + /// Holds lock version (2 – classic, 3 – plus, 4 – GPS). + /// + public int LockVersion { get; private set; } = 0; + + public override bool Equals(object obj) + => Equals(obj as VersionInfo); + + public bool Equals(VersionInfo other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(this, other)) return true; + if (GetType() != other.GetType()) return false; + + return ToString() == other.ToString(); + } + + public override int GetHashCode() => ToString().GetHashCode(); + + public override string ToString() => JsonConvert.SerializeObject(this); + + public static bool operator ==(VersionInfo lhs, VersionInfo rhs) + { + if (ReferenceEquals(lhs, null)) + return ReferenceEquals(rhs, null) ? true /*null == null = true*/: false; + + return lhs.Equals(rhs); + } + + public static bool operator !=(VersionInfo lhs, VersionInfo rhs) + => !(lhs == rhs); + public class Builder + { + private VersionInfo versionInfo = new VersionInfo(); + + public int FirmwareVersion { get => versionInfo.FirmwareVersion; set => versionInfo.FirmwareVersion = value; } + + public int HardwareVersion { get => versionInfo.HardwareVersion; set => versionInfo.HardwareVersion = value; } + + public int LockVersion { get => versionInfo.LockVersion; set => versionInfo.LockVersion = value; } + + public VersionInfo Build() + { + return versionInfo; + } + } + } +} diff --git a/TINKLib/Model/Connector/Command/CommandLoggedIn.cs b/TINKLib/Model/Connector/Command/CommandLoggedIn.cs index 4b83fae..138a966 100644 --- a/TINKLib/Model/Connector/Command/CommandLoggedIn.cs +++ b/TINKLib/Model/Connector/Command/CommandLoggedIn.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; @@ -226,7 +226,8 @@ namespace TINK.Model.Connector state.Value, bike.OperatorUri, location, - bike.LockInfo.BatteryPercentage)).GetIsBookingResponseOk(bike.Id); + bike.LockInfo.BatteryPercentage, + bike.LockInfo.VersionInfo)).GetIsBookingResponseOk(bike.Id); } catch (Exception) { @@ -320,4 +321,4 @@ namespace TINK.Model.Connector public async Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike) => await CopriServer.CloseAync(bike); } -} \ No newline at end of file +} diff --git a/TINKLib/Model/WhatsNew.cs b/TINKLib/Model/WhatsNew.cs index 91f84dc..8e849fd 100644 --- a/TINKLib/Model/WhatsNew.cs +++ b/TINKLib/Model/WhatsNew.cs @@ -594,6 +594,16 @@ namespace TINK.Model new Version(3, 0, 339), AppResources.ChangeLog3_0_339_MK, new List { AppFlavor.MeinKonrad } + }, + { + new Version(3, 0, 340), + AppResources.ChangeLog_MinorDesignImprovements, + new List { AppFlavor.LastenradBayern, AppFlavor.MeinKonrad } + }, + { + new Version(3, 0, 340), + AppResources.ChangeLog_MinorBugFixes, + new List { AppFlavor.ShareeBike } } }; diff --git a/TINKLib/MultilingualResources/AppResources.Designer.cs b/TINKLib/MultilingualResources/AppResources.Designer.cs index 10f7862..6c759e9 100644 --- a/TINKLib/MultilingualResources/AppResources.Designer.cs +++ b/TINKLib/MultilingualResources/AppResources.Designer.cs @@ -645,6 +645,15 @@ namespace TINK.MultilingualResources { } } + /// + /// Looks up a localized string similar to A few small things have been changed in the design.. + /// + public static string ChangeLog_MinorDesignImprovements { + get { + return ResourceManager.GetString("ChangeLog_MinorDesignImprovements", resourceCulture); + } + } + /// /// Looks up a localized string similar to Updated to latest lock firmware.. /// diff --git a/TINKLib/MultilingualResources/AppResources.de.resx b/TINKLib/MultilingualResources/AppResources.de.resx index b66b6a3..2c1bca0 100644 --- a/TINKLib/MultilingualResources/AppResources.de.resx +++ b/TINKLib/MultilingualResources/AppResources.de.resx @@ -1031,4 +1031,7 @@ Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben: Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben: im Menü ganz unten. Bitte aktualisieren Sie die App regelmäßig, um in Funktionalität und Design auf dem neuesten Stand zu sein! + + Es wurden ein paar Kleinigkeiten im Design verändert. + \ No newline at end of file diff --git a/TINKLib/MultilingualResources/AppResources.resx b/TINKLib/MultilingualResources/AppResources.resx index d8a1c21..3e9a650 100644 --- a/TINKLib/MultilingualResources/AppResources.resx +++ b/TINKLib/MultilingualResources/AppResources.resx @@ -1123,4 +1123,7 @@ You can now see at a glance which app version you have installed: in the menu at You can now see at a glance which app version you have installed: in the menu at the very bottom. Please update the app regularly to be up to date in functionality and design! + + A few small things have been changed in the design. + \ No newline at end of file diff --git a/TINKLib/MultilingualResources/TINKLib.de.xlf b/TINKLib/MultilingualResources/TINKLib.de.xlf index 0580d8e..5fba665 100644 --- a/TINKLib/MultilingualResources/TINKLib.de.xlf +++ b/TINKLib/MultilingualResources/TINKLib.de.xlf @@ -1400,6 +1400,10 @@ Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben: You can now see at a glance which app version you have installed: in the menu at the very bottom. Please update the app regularly to be up to date in functionality and design! Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben: im Menü ganz unten. Bitte aktualisieren Sie die App regelmäßig, um in Funktionalität und Design auf dem neuesten Stand zu sein! + + A few small things have been changed in the design. + Es wurden ein paar Kleinigkeiten im Design verändert. + diff --git a/TINKLib/Repository/CopriCallsHttps.cs b/TINKLib/Repository/CopriCallsHttps.cs index 271479f..3ba1cde 100644 --- a/TINKLib/Repository/CopriCallsHttps.cs +++ b/TINKLib/Repository/CopriCallsHttps.cs @@ -1,4 +1,4 @@ - + using System; using System.Collections.Generic; using System.IO; @@ -6,6 +6,7 @@ using System.Net; using System.Text; using System.Threading.Tasks; using Serilog; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Model.Logging; using TINK.Repository.Exception; @@ -172,10 +173,11 @@ namespace TINK.Repository lock_state state, Uri operatorUri, LocationDto location, - double batteryLevel) => + double batteryLevel, + IVersionInfo versionInfo) => await DoUpdateLockingStateAsync( operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri, - requestBuilder.UpateLockingState(bikeId, state, location, batteryLevel), + requestBuilder.UpateLockingState(bikeId, state, location, batteryLevel, versionInfo), UserAgent); /// Gets booking request request. diff --git a/TINKLib/Repository/CopriCallsMemory.cs b/TINKLib/Repository/CopriCallsMemory.cs index 579006a..12ebce4 100644 --- a/TINKLib/Repository/CopriCallsMemory.cs +++ b/TINKLib/Repository/CopriCallsMemory.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository.Request; using TINK.Repository.Response; @@ -1636,7 +1637,8 @@ namespace TINK.Repository lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryLevel) => null; + double batteryLevel, + IVersionInfo versionInfo) => null; public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) => null; diff --git a/TINKLib/Repository/CopriCallsMonkeyStore.cs b/TINKLib/Repository/CopriCallsMonkeyStore.cs index b37aad2..a00de3b 100644 --- a/TINKLib/Repository/CopriCallsMonkeyStore.cs +++ b/TINKLib/Repository/CopriCallsMonkeyStore.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using MonkeyCache.FileStore; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Model.Services.CopriApi; using TINK.Repository.Request; @@ -171,7 +172,8 @@ namespace TINK.Repository lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryLevel) + double batteryLevel, + IVersionInfo versionInfo) => throw new System.Exception("Aktualisierung des Schlossstatuses im Offlinemodus nicht möglich!"); public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) diff --git a/TINKLib/Repository/ICopriServer.cs b/TINKLib/Repository/ICopriServer.cs index 95136de..a1d7fe7 100644 --- a/TINKLib/Repository/ICopriServer.cs +++ b/TINKLib/Repository/ICopriServer.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository.Request; using TINK.Repository.Response; @@ -69,7 +70,8 @@ namespace TINK.Repository lock_state state, Uri operatorUri, LocationDto location = null, - double batteryPercentage = double.NaN); + double batteryPercentage = double.NaN, + IVersionInfo versionInfo = null); /// Books a bluetooth bike. /// Id of the bike to book. diff --git a/TINKLib/Repository/Request/IRequestBuilder.cs b/TINKLib/Repository/Request/IRequestBuilder.cs index fa679f0..5a25287 100644 --- a/TINKLib/Repository/Request/IRequestBuilder.cs +++ b/TINKLib/Repository/Request/IRequestBuilder.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; namespace TINK.Repository.Request @@ -63,14 +64,16 @@ namespace TINK.Repository.Request /// Gets the request for updating lock state for a booked bike. /// Id of the bike to update locking state for. - /// Geolocation of lock when state change occurred. /// New locking state. + /// Geolocation of lock when state change occurred. + /// Information about lock (firmware version, hardware version, ...). /// Request to update locking state. string UpateLockingState( string bikeId, lock_state state, LocationDto location = null, - double batteryPercentage = double.NaN); + double batteryPercentage = double.NaN, + IVersionInfo versionInfo = null); /// Gets the booking request (synonym: booking == renting == mieten). /// Id of the bike to book. diff --git a/TINKLib/Repository/Request/RequestBuilder.cs b/TINKLib/Repository/Request/RequestBuilder.cs index 022167d..214e59f 100644 --- a/TINKLib/Repository/Request/RequestBuilder.cs +++ b/TINKLib/Repository/Request/RequestBuilder.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Net; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository.Exception; @@ -101,7 +102,11 @@ namespace TINK.Repository.Request public string StartReturningBike(string bikeId) => throw new NotSupportedException(); - public string UpateLockingState(string bikeId, lock_state state, LocationDto geolocation, double batteryPercentage) + /// + /// Not supported if user is not logged in. Lock state is only updated after open/ close which is only possible if user is logged in. + /// + /// + public string UpateLockingState(string bikeId, lock_state state, LocationDto geolocation, double batteryPercentage, IVersionInfo versionInfo) => throw new NotSupportedException(); public string DoBook(string bikeId, Guid guid, double batteryPercentage) diff --git a/TINKLib/Repository/Request/RequestBuilderLoggedIn.cs b/TINKLib/Repository/Request/RequestBuilderLoggedIn.cs index 56f8246..c243750 100644 --- a/TINKLib/Repository/Request/RequestBuilderLoggedIn.cs +++ b/TINKLib/Repository/Request/RequestBuilderLoggedIn.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository.Exception; using TINK.Services.Logging; @@ -129,17 +130,20 @@ namespace TINK.Repository.Request /// Operator specific call. /// Id of the bike to update locking state for. /// New locking state. + /// Information about lock (firmware version, hardware version, ...). /// Request to update locking state. public string UpateLockingState( string bikeId, lock_state state, LocationDto geolocation, - double batteryPercentage) + double batteryPercentage, + IVersionInfo versionInfo) => "request=booking_update" + GetBikeIdParameter(bikeId) + GetLocationParameters(geolocation) + GetLockStateParameter(state) + GetBatteryPercentageParameters(batteryPercentage) + + GetVersionInfoParameter(versionInfo) + AuthCookieParameter + UiIsoLanguageNameParameter; @@ -272,6 +276,10 @@ namespace TINK.Repository.Request ? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}" : string.Empty; + private static string GetVersionInfoParameter(IVersionInfo versionInfo) => versionInfo?.FirmwareVersion > 0 || versionInfo?.HardwareVersion > 0 || versionInfo?.LockVersion > 0 + ? $"&firmware=HW%20{versionInfo.HardwareVersion};FW%20{versionInfo.FirmwareVersion};Lock%20{versionInfo.LockVersion}" + : string.Empty; + /// Gets the geolocation parameter. /// Geolocation or null. private static string GetLocationParameters(LocationDto geolocation) diff --git a/TINKLib/Services/CopriApi/CopriProviderHttps.cs b/TINKLib/Services/CopriApi/CopriProviderHttps.cs index 4e18f8b..f8e06ae 100644 --- a/TINKLib/Services/CopriApi/CopriProviderHttps.cs +++ b/TINKLib/Services/CopriApi/CopriProviderHttps.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Serilog; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Connector.Updater; using TINK.Model.Device; using TINK.Repository; @@ -235,13 +236,15 @@ namespace TINK.Model.Services.CopriApi lock_state state, Uri operatorUri, LocationDto location, - double batteryLevel) + double batteryLevel, + IVersionInfo versionInfo) => await HttpsServer.UpdateLockingStateAsync( bikeId, state, operatorUri, location, - batteryLevel); + batteryLevel, + versionInfo); /// Books a bike. /// Id of the bike to book. @@ -303,4 +306,4 @@ namespace TINK.Model.Services.CopriApi => await HttpsServer.DoSubmitMiniSurvey(answers); } -} \ No newline at end of file +} diff --git a/TINKLib/Services/CopriApi/CopriProviderMonkeyStore.cs b/TINKLib/Services/CopriApi/CopriProviderMonkeyStore.cs index c7fee11..cdfa7e7 100644 --- a/TINKLib/Services/CopriApi/CopriProviderMonkeyStore.cs +++ b/TINKLib/Services/CopriApi/CopriProviderMonkeyStore.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository; using TINK.Repository.Request; @@ -53,13 +54,15 @@ namespace TINK.Model.Services.CopriApi lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryLevel) + double batteryLevel, + IVersionInfo versionInfo) => await monkeyStore.UpdateLockingStateAsync( bikeId, state, operatorUri, geolocation, - batteryLevel); + batteryLevel, + versionInfo); public async Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) { diff --git a/TINKLib/View/Themes/Konrad.xaml b/TINKLib/View/Themes/Konrad.xaml index bc3557d..3366e23 100644 --- a/TINKLib/View/Themes/Konrad.xaml +++ b/TINKLib/View/Themes/Konrad.xaml @@ -1,11 +1,15 @@ - + + #D21113 + + #FF0020 + + + + + + + + + + + - \ No newline at end of file + diff --git a/TINKLib/View/Themes/LastenradBayern.xaml b/TINKLib/View/Themes/LastenradBayern.xaml index 77f8c6d..05991ae 100644 --- a/TINKLib/View/Themes/LastenradBayern.xaml +++ b/TINKLib/View/Themes/LastenradBayern.xaml @@ -1,83 +1,92 @@ - + + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.Themes.LastenradBayern"> - #009BDB + + #009BDB - + - - - - - --> + + + + + + + + + + + + - + + - \ No newline at end of file + diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedClosed.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedClosed.cs index 46b8804..e3d7a9f 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedClosed.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedClosed.cs @@ -318,13 +318,15 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler await ViewUpdateManager().StopUpdatePeridically(); BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { - SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; + btLock = LockService[SelectedBike.LockInfo.Id]; + SelectedBike.LockInfo.State = (await btLock.OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) { - BikesViewModel.ActionText = string.Empty; + BikesViewModel.ActionText = string.Empty; if (exception is OutOfReachException) { @@ -389,7 +391,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -409,7 +411,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedUnknown.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedUnknown.cs index fb763ec..42f623a 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedUnknown.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/BookedUnknown.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -69,8 +69,10 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler await ViewUpdateManager().StopUpdatePeridically(); BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { + btLock = LockService[SelectedBike.LockInfo.Id]; SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) @@ -140,7 +142,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -160,7 +162,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/DisposableDisconnected.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/DisposableDisconnected.cs index f6fa548..a5b9f38 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/DisposableDisconnected.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/DisposableDisconnected.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Serilog; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; @@ -58,7 +58,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler { BikesViewModel.IsIdle = false; - // Ask whether to really book bike? + // Ask whether to really reserve bike? var alertResult = await ViewService.DisplayAlert( string.Empty, string.Format(AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes), @@ -257,9 +257,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Unlock bike. BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { - SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; + btLock = LockService[SelectedBike.LockInfo.Id]; + SelectedBike.LockInfo.State = (await btLock.OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) { @@ -336,7 +338,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -356,7 +358,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedClosed.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedClosed.cs index cebe7ca..ab41883 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedClosed.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedClosed.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Serilog; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; @@ -222,9 +222,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Unlock bike. BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { - SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; + btLock = LockService[SelectedBike.LockInfo.Id]; + SelectedBike.LockInfo.State = (await btLock.OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) { @@ -301,7 +303,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -321,7 +323,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedDisconnected.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedDisconnected.cs index 077f61a..b1764fd 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedDisconnected.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedDisconnected.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Serilog; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; @@ -246,7 +246,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler } else { - Log.ForContext().Error("Lock can not be found. {Exception}", exception); + Log.ForContext().Error("Lock can not be found. {Exception}", exception); string message; if (retryCount < 2) @@ -384,9 +384,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Unlock bike. BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { - SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; + btLock = LockService[SelectedBike.LockInfo.Id]; + SelectedBike.LockInfo.State = (await btLock.OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) { @@ -463,7 +465,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -483,7 +485,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedUnknown.cs b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedUnknown.cs index 8ac0a50..93b0753 100644 --- a/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedUnknown.cs +++ b/TINKLib/ViewModel/Bikes/Bike/BluetoothLock/RequestHandler/ReservedUnknown.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -65,9 +65,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler await ViewUpdateManager().StopUpdatePeridically(); BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; + ILockService btLock; try { - SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; + btLock = LockService[SelectedBike.LockInfo.Id]; + SelectedBike.LockInfo.State = (await btLock.OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; } catch (Exception exception) { @@ -136,7 +138,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; try { - SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); + SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync(); } catch (Exception exception) { @@ -156,7 +158,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; - + var versionTdo = btLock.VersionInfo; + if (versionTdo != null) + { + SelectedBike.LockInfo.VersionInfo = new VersionInfo.Builder + { + FirmwareVersion = versionTdo.FirmwareVersion, + HardwareVersion = versionTdo.HardwareVersion, + LockVersion = versionTdo.LockVersion, + }.Build(); + } IsConnected = IsConnectedDelegate(); try diff --git a/TestFramework/Repository/CopriCallMemoryBase.cs b/TestFramework/Repository/CopriCallMemoryBase.cs index f0d2cc9..b37eb14 100644 --- a/TestFramework/Repository/CopriCallMemoryBase.cs +++ b/TestFramework/Repository/CopriCallMemoryBase.cs @@ -1,9 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading.Tasks; using TINK.Model; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository; using TINK.Repository.Request; @@ -258,7 +259,8 @@ namespace TestFramework.Repository lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryLevel) + double batteryLevel, + IVersionInfo versionInfo) => null; public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) diff --git a/TestFramework/Repository/ExceptionServer.cs b/TestFramework/Repository/ExceptionServer.cs index 694a952..d3066a1 100644 --- a/TestFramework/Repository/ExceptionServer.cs +++ b/TestFramework/Repository/ExceptionServer.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Repository; using TINK.Repository.Request; @@ -59,7 +60,8 @@ namespace TestFramework.Repository lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryPercentage) + double batteryPercentage, + IVersionInfo versionInfo) => throw new NotImplementedException(); public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) diff --git a/TestFramework/Services/CopriApi/CopriCallsCacheMemory001.cs b/TestFramework/Services/CopriApi/CopriCallsCacheMemory001.cs index 9b92af6..7469036 100644 --- a/TestFramework/Services/CopriApi/CopriCallsCacheMemory001.cs +++ b/TestFramework/Services/CopriApi/CopriCallsCacheMemory001.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using TestFramework.Repository; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Model.Services.CopriApi; using TINK.Repository.Request; @@ -79,7 +80,8 @@ namespace TestFramework.Services.CopriApi.Connector lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryPercentage) + double batteryPercentage, + IVersionInfo versionInfo) => throw new NotImplementedException(); public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) diff --git a/TestShareeLib/Repository/Request/TestRequestBuilderLoggedIn.cs b/TestShareeLib/Repository/Request/TestRequestBuilderLoggedIn.cs index bc9fff3..22236e4 100644 --- a/TestShareeLib/Repository/Request/TestRequestBuilderLoggedIn.cs +++ b/TestShareeLib/Repository/Request/TestRequestBuilderLoggedIn.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using NUnit.Framework; using TINK.Repository.Exception; @@ -185,7 +185,7 @@ namespace TestShareeLib.Repository.Request { var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); Assert.That( - builder.UpateLockingState("12", lock_state.locked, null, 15.03), + builder.UpateLockingState("12", lock_state.locked, null /* geolocaion */, 15.03, null /* version info */), Is.EqualTo("request=booking_update&bike=12&lock_state=locked&voltage=15.03&authcookie=MySessionCookieMyMeranctIt")); } @@ -194,7 +194,7 @@ namespace TestShareeLib.Repository.Request { var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); Assert.That( - builder.UpateLockingState("12", lock_state.locked, null, double.NaN), + builder.UpateLockingState("12", lock_state.locked, null /* geolocaion */, double.NaN, null /* version info */), Is.EqualTo("request=booking_update&bike=12&lock_state=locked&authcookie=MySessionCookieMyMeranctIt")); } @@ -203,7 +203,7 @@ namespace TestShareeLib.Repository.Request { var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); Assert.That( - builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), 12), + builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), 12, null /* version info */), Is.EqualTo("request=booking_update&bike=12&gps=21,17&gps_age=0.07&lock_state=locked&voltage=12&authcookie=MySessionCookieMyMeranctIt")); } @@ -212,7 +212,7 @@ namespace TestShareeLib.Repository.Request { var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); Assert.That( - builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), double.NaN), + builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), double.NaN, null /* version info */), Is.EqualTo("request=booking_update&bike=12&gps=21,17&gps_age=0.07&lock_state=locked&authcookie=MySessionCookieMyMeranctIt")); } @@ -221,10 +221,20 @@ namespace TestShareeLib.Repository.Request { var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); Assert.That( - builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Accuracy = 5.7, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), 98), + builder.UpateLockingState("12", lock_state.locked, new LocationDto.Builder { Latitude = 21, Longitude = 17, Accuracy = 5.7, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(), 98, null /* version info */), Is.EqualTo("request=booking_update&bike=12&gps=21,17&gps_accuracy=5.7&gps_age=0.07&lock_state=locked&voltage=98&authcookie=MySessionCookieMyMeranctIt")); } + [Test] + public void TestUpateLockingStateVersionsInfo() + { + var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); + Assert.That( + builder.UpateLockingState("12", lock_state.locked, null /* geolocaion */, 15.03, new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.VersionInfo.Builder { FirmwareVersion=13, HardwareVersion=12, LockVersion=14}.Build()), + Is.EqualTo("request=booking_update&bike=12&lock_state=locked&voltage=15.03&firmware=HW%2012;FW%2013;Lock%2014&authcookie=MySessionCookieMyMeranctIt")); + } + + [Test] public void TestDoReturnGeolocationIsNull() { diff --git a/TestTINKLib/Mocks/Connector/CopriCallsCacheMemory.cs b/TestTINKLib/Mocks/Connector/CopriCallsCacheMemory.cs index 79267fa..2e46c92 100644 --- a/TestTINKLib/Mocks/Connector/CopriCallsCacheMemory.cs +++ b/TestTINKLib/Mocks/Connector/CopriCallsCacheMemory.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Device; using TINK.Model.Services.CopriApi; using TINK.Repository; @@ -84,7 +85,8 @@ namespace TestTINKLib.Mocks.Connector lock_state state, Uri operatorUri, LocationDto geolocation, - double batteryPercentage) + double batteryPercentage, + IVersionInfo versionInfo) => throw new NotImplementedException(); public Task DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)