Version 3.0.340

This commit is contained in:
Anja 2022-09-20 13:51:55 +02:00
parent 52c9f6f1d9
commit bad07e1ec9
62 changed files with 1401 additions and 1000 deletions

View file

@ -1,4 +1,4 @@

using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
@ -18,15 +18,15 @@ namespace TINK.Droid
[IntentFilter(new[] { Intent.ActionView }, [IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault },
DataScheme = "https", DataScheme = "https",
DataHost = "sharee.bike", DataHost = "app.sharee.bike",
DataPathPrefix = "/lastenrad", DataPathPrefix = "/App-LastenradBayern",
AutoVerify = true)] AutoVerify = true)]
[IntentFilter(new[] { Intent.ActionView }, [IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault },
DataScheme = "http", DataScheme = "http",
DataHost = "sharee.bike", DataHost = "app.sharee.bike",
DataPathPrefix = "/lastenrad", DataPathPrefix = "/App-LastenradBayern",
AutoVerify = true)] AutoVerify = true)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.339" android:versionCode="339"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.340" android:versionCode="340">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>LastenradBayern</string> <string>LastenradBayern</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>339</string> <string>340</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.339</string> <string>3.0.340</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,137 +1,106 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.BikesAtStation.BikesAtStationPage" x:Class="TINK.View.BikesAtStation.BikesAtStationPage"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"> xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
<Shell.TitleView> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View">
<Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Shell.TitleView>
Text="{Binding Title}"/> <Grid ColumnDefinitions="Auto, 1*">
</Grid> <Label Style="{StaticResource Label-Navbar}"
</Shell.TitleView> Text="{Binding Title}"/>
<ContentPage.Resources> </Grid>
<ResourceDictionary> </Shell.TitleView>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> <ContentPage.Resources>
</ContentPage.Resources> <ResourceDictionary>
<ContentPage.Content> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<Frame> </ResourceDictionary>
<StackLayout </ContentPage.Resources>
Orientation="Vertical">
<!-- Title bar stack layout--> <ContentPage.Content>
<StackLayout
Orientation="Vertical"> <Frame>
<Label
HorizontalOptions="Center" <!--Grid for Bike(s) view and Running process in same row-->
FontAttributes="Bold" <Grid>
TextColor="{DynamicResource primary-back-title-color}" <Grid.RowDefinitions>
Text="{Binding StationDetailText}"/> <RowDefinition Height="Auto"/>
<BoxView <RowDefinition Height="*"/>
HeightRequest="1" <RowDefinition Height="Auto"/>
Color="{DynamicResource primary-back-title-color}"/> </Grid.RowDefinitions>
</StackLayout>
<!-- Center stack layout --> <!--Bike(s) view-->
<StackLayout <StackLayout Grid.Row="0"
Orientation="Vertical" Orientation="Vertical">
VerticalOptions="CenterAndExpand">
<ListView <!--Title-->
x:Name="BikesAtStationListView" <Label
SelectionMode="None" HorizontalOptions="Center"
SelectedItem="{Binding SelectedBike}" FontAttributes="Bold"
IsEnabled="{Binding IsIdle}" TextColor="{DynamicResource primary-back-title-color}"
IsVisible="{Binding IsBikesListVisible}" Text="{Binding StationDetailText}"/>
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> <!--Line-->
<Label <BoxView
IsVisible="{Binding IsNoBikesAtStationVisible}" HeightRequest="1"
Text="{Binding NoBikesAtStationText}"/> Color="{DynamicResource primary-back-title-color}"/>
</StackLayout> </StackLayout>
<!-- Status bar stack layout-->
<StackLayout <!--Bike(s)-->
Orientation="Vertical"> <ListView
<Label Grid.Row="1"
TextType="Html" x:Name="BikesAtStationListView"
Text="{Binding ContactSupportHintText}"> SelectionMode="None"
<Label.GestureRecognizers> SelectedItem="{Binding SelectedBike}"
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/> IsEnabled="{Binding IsIdle}"
</Label.GestureRecognizers> IsVisible="{Binding IsBikesListVisible}"
</Label> HasUnevenRows="True"
<Label ItemTemplate="{StaticResource bikeTemplateSelector}"/>
IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html" <!--No Bikes-->
Text="{Binding LoginRequiredHintText}"> <Label
<Label.GestureRecognizers> Grid.Row="1"
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/> IsVisible="{Binding IsNoBikesAtStationVisible}"
</Label.GestureRecognizers> Text="{Binding NoBikesAtStationText}"/>
</Label>
<StackLayout <!-- Contact and Login at end of page-->
Orientation="Horizontal"> <StackLayout
<Label Orientation="Vertical"
HeightRequest="24" Grid.Row="2">
Text="{Binding StatusInfoText}"
FontSize="Small" <!--Line-->
VerticalOptions="Center" <BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/>
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}" <!--Contact to operator-->
IsVisible="{Binding IsRunning}" <Label
HeightRequest="20" TextType="Html"
VerticalOptions="CenterAndExpand" Text="{Binding ContactSupportHintText}">
HorizontalOptions="End"> <Label.GestureRecognizers>
<ActivityIndicator.WidthRequest> <TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" /> </Label.GestureRecognizers>
</ActivityIndicator.WidthRequest> </Label>
<ActivityIndicator.Color>
<OnPlatform x:TypeArguments="Color" <!--Login required-->
Android="#009BDB" iOS="#009BDB" WinPhone="#009BDB" /> <Label
</ActivityIndicator.Color> IsVisible="{Binding IsLoginRequiredHintVisible}"
</ActivityIndicator> TextType="Html"
</StackLayout> Text="{Binding LoginRequiredHintText}">
</StackLayout> <Label.GestureRecognizers>
<!-- Possible New Design --> <TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
<!--<StackLayout </Label.GestureRecognizers>
Orientation="Vertical"> </Label>
<StackLayout </StackLayout>
Orientation="Horizontal">
<Label <!--While process is running-->
HeightRequest="24" <sharedGui:RunningProcessView
FontSize="Small" IsVisible="{Binding IsRunning}"
Text="{Binding StatusInfoText}" Grid.Row="1"/>
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/> </Grid>
<ActivityIndicator IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}" </Frame>
HeightRequest="20"
VerticalOptions="CenterAndExpand" </ContentPage.Content>
HorizontalOptions="End"> </ContentPage>
<ActivityIndicator.WidthRequest>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest>
<ActivityIndicator.Color>
<OnPlatform x:TypeArguments="Color"
Android="#009BDB" iOS="#009BDB" WinPhone="#009BDB" />
</ActivityIndicator.Color>
</ActivityIndicator>
</StackLayout>
<BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/>
<Label
TextType="Html"
Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers>
</Label>
<Label
IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html"
Text="{Binding LoginRequiredHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</StackLayout>-->
</StackLayout>
</Frame>
</ContentPage.Content>
</ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -23,11 +23,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -22,11 +22,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -22,11 +22,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,68 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" x:Class="TINK.View.FindBike.FindBikePage"
x:Class="TINK.View.FindBike.FindBikePage" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike"> xmlns:local_bike="clr-namespace:TINK.View.Bike"
<Shell.TitleView> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View">
<Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Shell.TitleView>
Text="{x:Static resources:AppResources.MarkingFindBike}"/> <Grid ColumnDefinitions="Auto, 1*">
</Grid> <Label Style="{StaticResource Label-Navbar}"
</Shell.TitleView> Text="{x:Static resources:AppResources.MarkingFindBike}"/>
<ContentPage.Resources> </Grid>
<ResourceDictionary> </Shell.TitleView>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> <ContentPage.Resources>
</ContentPage.Resources> <ResourceDictionary>
<ContentPage.Content> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<Frame> </ResourceDictionary>
<StackLayout> </ContentPage.Resources>
<Entry
Placeholder="Fahrrad-Nummer bitte hier eingeben" <ContentPage.Content>
IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10" <Frame>
CursorPosition="0"
Text="{Binding BikeIdUserInput}"> <!--Grid for Bike(s) view and Running process in same row-->
</Entry> <Grid>
<Button <Grid.RowDefinitions>
Text="Rad Wählen" <RowDefinition Height="*"/>
IsEnabled="{Binding IsSelectBikeEnabled}" </Grid.RowDefinitions>
IsVisible="{Binding IsSelectBikeVisible}"
Command="{Binding OnSelectBikeRequest}"> <!--Search bike-->
</Button> <StackLayout Grid.Row="0">
<ListView <Entry
x:Name="FindBikeListView" Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
SelectionMode="None" IsVisible="{Binding IsSelectBikeVisible}"
SelectedItem="{Binding SelectedBike}" MaxLength="10"
IsEnabled="{Binding IsIdle}" CursorPosition="0"
IsVisible="{Binding IsBikesListVisible}" Text="{Binding BikeIdUserInput}"/>
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> <Button
<StackLayout Text="{x:Static resources:AppResources.MarkingFindBike}"
VerticalOptions="EndAndExpand" IsEnabled="{Binding IsSelectBikeEnabled}"
Orientation="Horizontal"> IsVisible="{Binding IsSelectBikeVisible}"
<Label Command="{Binding OnSelectBikeRequest}"/>
HeightRequest="24"
Text="{Binding StatusInfoText}" <ListView
FontSize="Small" x:Name="FindBikeListView"
VerticalOptions="Center" SelectionMode="None"
HorizontalOptions="FillAndExpand"/> SelectedItem="{Binding SelectedBike}"
<ActivityIndicator IsRunning="{Binding IsRunning}" IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsBikesListVisible}"
HeightRequest="20" HasUnevenRows="True"
VerticalOptions="CenterAndExpand" ItemTemplate="{StaticResource bikeTemplateSelector}"/>
HorizontalOptions="End">
<ActivityIndicator.WidthRequest> </StackLayout>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest> <!--While process is running-->
<ActivityIndicator.Color> <sharedGui:RunningProcessView
<OnPlatform x:TypeArguments="Color" Grid.Row="0"
Android="#009BDB" iOS="#009BDB" WinPhone="#009BDB" /> IsVisible="{Binding IsRunning}"/>
</ActivityIndicator.Color>
</ActivityIndicator> </Grid>
</StackLayout>
</StackLayout> </Frame>
</Frame> </ContentPage.Content>
</ContentPage.Content> </ContentPage>
</ContentPage>

View file

@ -1,140 +1,116 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 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:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Map.MapPage"> BackgroundColor="{DynamicResource Key=primary-back-title-color}"
<!--BackgroundColor="{DynamicResource Key=primary-back-title-color}"--> x:Class="TINK.View.Map.MapPage">
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Label Style="{StaticResource Label-Navbar}"
Text="{x:Static resources:AppResources.MarkingMapPage}"/> Text="{x:Static resources:AppResources.MarkingMapPage}"/>
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<Grid
RowDefinitions="3,46,1*,33" <!--Grid for Map with Buttons and Running process-->
ColumnDefinitions="1*,Auto,1*" <Grid
IsEnabled="{Binding IsMapPageEnabled}" RowDefinitions="3,46,1*,Auto"
VerticalOptions="FillAndExpand" ColumnDefinitions="1*,Auto,1*"
> IsEnabled="{Binding IsMapPageEnabled}"
<maps:Map VerticalOptions="FillAndExpand">
Grid.RowSpan="3"
Grid.ColumnSpan="3" <!--Map-->
WidthRequest="320" <maps:Map
HeightRequest="800" Grid.RowSpan="3"
x:Name="MyMap" Grid.ColumnSpan="3"
IsShowingUser="False" WidthRequest="320"
MapType="Street"> HeightRequest="800"
<maps:Map.Behaviors> x:Name="MyMap"
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> IsShowingUser="False"
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> MapType="Street">
</maps:Map.Behaviors> <maps:Map.Behaviors>
</maps:Map> <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
<Frame <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
CornerRadius="13" </maps:Map.Behaviors>
Grid.Row="1" </maps:Map>
Grid.Column="1"
Margin="0" <!--Buttons for choosing bike type-->
Padding="0" <Frame
BackgroundColor="{DynamicResource secondary-back-title-color}"> CornerRadius="13"
<StackLayout Orientation="Horizontal" Grid.Row="1"
Margin="0" Grid.Column="1"
Padding="0"> Margin="0"
<Button Padding="0"
x:Name="KonradButton" BackgroundColor="{DynamicResource secondary-back-title-color}">
AutomationId ="FilterKonrad_button" <StackLayout
Text="{x:Static resources:AppResources.MarkingCityBike}" Orientation="Horizontal"
Command="{Binding OnToggleTinkToKonrad}" Margin="0"
IsVisible="{Binding IsToggleVisible}" Padding="0">
BackgroundColor="{Binding KonradColor}" <Button
BorderColor="{Binding KonradColor}" x:Name="KonradButton"
BorderWidth="0" AutomationId ="FilterKonrad_button"
VerticalOptions="Center" Text="{x:Static resources:AppResources.MarkingCityBike}"
HorizontalOptions="Center" Command="{Binding OnToggleTinkToKonrad}"
WidthRequest="94" IsVisible="{Binding IsToggleVisible}"
HeightRequest="40" BackgroundColor="{Binding KonradColor}"
BorderRadius="10" BorderColor="{Binding KonradColor}"
Margin="3,0,0,0" BorderWidth="0"
FontSize="Small" VerticalOptions="Center"
FontAttributes="Bold" HorizontalOptions="Center"
TextColor="{Binding NoKonradColor}"> WidthRequest="94"
</Button> HeightRequest="40"
<Button BorderRadius="10"
x:Name="TINKButton" Margin="3,0,0,0"
AutomationId ="FilterTINK_button" FontSize="Small"
Text="{x:Static resources:AppResources.MarkingCargoBike}" FontAttributes="Bold"
Command="{Binding OnToggleKonradToTink}" TextColor="{Binding NoKonradColor}">
IsVisible="{Binding IsToggleVisible}" </Button>
BackgroundColor="{Binding TinkColor}" <Button
BorderColor="{Binding TinkColor}" x:Name="TINKButton"
BorderWidth="0" AutomationId ="FilterTINK_button"
VerticalOptions="Center" Text="{x:Static resources:AppResources.MarkingCargoBike}"
HorizontalOptions="Center" Command="{Binding OnToggleKonradToTink}"
WidthRequest="94" IsVisible="{Binding IsToggleVisible}"
HeightRequest="40" BackgroundColor="{Binding TinkColor}"
BorderRadius="10" BorderColor="{Binding TinkColor}"
Margin="0,0,3,0" BorderWidth="0"
FontSize="Small" VerticalOptions="Center"
FontAttributes="Bold" HorizontalOptions="Center"
TextColor="{Binding NoTinkColor}"> WidthRequest="94"
</Button> HeightRequest="40"
</StackLayout> BorderRadius="10"
</Frame> Margin="0,0,3,0"
<StackLayout FontSize="Small"
Grid.Row="3" FontAttributes="Bold"
Grid.ColumnSpan="3" TextColor="{Binding NoTinkColor}">
Margin="6,3,6,6" </Button>
VerticalOptions="EndAndExpand" </StackLayout>
Orientation="Horizontal"> </Frame>
<Label
HeightRequest="24" <!--While process is running-->
FontSize="Small" <!--Spinner-->
Text="{Binding StatusInfoText}" <ActivityIndicator
VerticalOptions="Center" Grid.RowSpan="4"
HorizontalOptions="FillAndExpand"/> Grid.ColumnSpan="3"
<ActivityIndicator IsRunning="{Binding IsRunning}" IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsRunning}"
HeightRequest="20" Scale="2"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
HorizontalOptions="End"> HorizontalOptions="CenterAndExpand"
<ActivityIndicator.WidthRequest> Color="{x:DynamicResource primary-back-title-color}"/>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest> <!--Info text-->
<ActivityIndicator.Color> <Label
<OnPlatform x:TypeArguments="Color" Grid.Row="3"
Android="#009BDB" iOS="#009BDB" WinPhone="#009BDB"/> Grid.ColumnSpan="3"
</ActivityIndicator.Color> Text="{Binding StatusInfoText}"
</ActivityIndicator> TextColor="White"
</StackLayout> FontSize="Small"
<!-- New StatusInfoText Layout --> HorizontalOptions="Center"
<!--<StackLayout Padding="0,0,0,10"/>
Grid.Row="3"
Grid.ColumnSpan="3" </Grid>
Margin="6,3,6,6"
VerticalOptions="EndAndExpand" </ContentPage>
Orientation="Horizontal">
<Label
HeightRequest="24"
FontSize="Small"
Text="{Binding StatusInfoText}"
TextColor="White"
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}"
HeightRequest="20"
VerticalOptions="CenterAndExpand"
HorizontalOptions="End">
<ActivityIndicator.WidthRequest>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest>
<ActivityIndicator.Color>
<OnPlatform x:TypeArguments="Color"
Android="White" iOS="White" WinPhone="White"/>
</ActivityIndicator.Color>
</ActivityIndicator>
</StackLayout>-->
</Grid>
</ContentPage>

View file

@ -1,64 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.MyBikes.MyBikesPage" x:Class="TINK.View.MyBikes.MyBikesPage"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike"> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
<Shell.TitleView> xmlns:local_bike="clr-namespace:TINK.View.Bike">
<Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Shell.TitleView>
Text="{x:Static resources:AppResources.MarkingMyBikes}"/> <Grid ColumnDefinitions="Auto, 1*">
</Grid> <Label Style="{StaticResource Label-Navbar}"
</Shell.TitleView> Text="{x:Static resources:AppResources.MarkingMyBikes}"/>
<ContentPage.Resources> </Grid>
<ResourceDictionary> </Shell.TitleView>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> <ContentPage.Resources>
</ContentPage.Resources> <ResourceDictionary>
<ContentPage.Content> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<Frame> </ResourceDictionary>
<StackLayout </ContentPage.Resources>
Orientation="Vertical">
<!-- Center stack layout --> <ContentPage.Content>
<StackLayout
VerticalOptions="CenterAndExpand" <Frame>
Orientation="Vertical">
<ListView <!--Grid for Bike(s) view and Running process in same row-->
x:Name="MyBikesListView" <Grid>
SelectionMode="None" <Grid.RowDefinitions>
SelectedItem="{Binding SelectedBike}" <RowDefinition Height="*"/>
IsEnabled="{Binding IsIdle}" </Grid.RowDefinitions>
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True" <!--Bike(s) view-->
ItemTemplate="{StaticResource bikeTemplateSelector}"/> <StackLayout Grid.Row="0"
<Label VerticalOptions="CenterAndExpand"
IsVisible="{Binding IsNoBikesOccupiedVisible}" Orientation="Vertical">
Text="{Binding NoBikesOccupiedText}"/>
</StackLayout> <!--Bike(s)-->
<!-- Status bar stack layout--> <ListView
<StackLayout x:Name="MyBikesListView"
Orientation="Horizontal"> SelectionMode="None"
<Label SelectedItem="{Binding SelectedBike}"
HeightRequest="24" IsEnabled="{Binding IsIdle}"
Text="{Binding StatusInfoText}" IsVisible="{Binding IsBikesListVisible}"
FontSize="Small" HasUnevenRows="True"
VerticalOptions="Center" ItemTemplate="{StaticResource bikeTemplateSelector}"/>
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}" <!--No Bikes-->
IsVisible="{Binding IsRunning}" <Label
HeightRequest="20" IsVisible="{Binding IsNoBikesOccupiedVisible}"
VerticalOptions="CenterAndExpand" Text="{Binding NoBikesOccupiedText}"/>
HorizontalOptions="End">
<ActivityIndicator.WidthRequest> </StackLayout>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest> <!--While process is running-->
<ActivityIndicator.Color> <sharedGui:RunningProcessView
<OnPlatform x:TypeArguments="Color" Grid.Row="0"
Android="#009BDB" iOS="#009BDB" WinPhone="#009BDB" /> IsVisible="{Binding IsRunning}"/>
</ActivityIndicator.Color>
</ActivityIndicator> </Grid>
</StackLayout>
</StackLayout> </Frame>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -83,6 +83,8 @@ namespace TINK.Services.BluetoothLock.BLE
private ICharacteristic BatteryCharacteristic { get; set; } private ICharacteristic BatteryCharacteristic { get; set; }
private ICharacteristic FirmwareVersionCharacteristic { get; set; }
private readonly AsyncRetryPolicy<byte[]> _retryPollicy; private readonly AsyncRetryPolicy<byte[]> _retryPollicy;
/// <summary> Gets the lock control service.</summary> /// <summary> Gets the lock control service.</summary>
@ -301,6 +303,27 @@ namespace TINK.Services.BluetoothLock.BLE
return BatteryCharacteristic; return BatteryCharacteristic;
} }
/// <summary> Gets the versions info characteristic.</summary>
protected async Task<ICharacteristic> GetVersionsCharacteristicAsync()
{
if (FirmwareVersionCharacteristic != null) return FirmwareVersionCharacteristic ;
FirmwareVersionCharacteristic = null;
Log.ForContext<LockItBase>().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<LockItBase>().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<LockItBase>().Debug("Get versions info characteristic retrieved successfully.");
return FirmwareVersionCharacteristic ;
}
/// <summary> Query name of lock.</summary> /// <summary> Query name of lock.</summary>
private void GetName() 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."); throw new CoundntGetCharacteristicException("Can not get battery percentage. State characteristic must not be null.");
} }
byte[] state; byte[] percentage;
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfter(READ_TIMEOUT_MS); cts.CancelAfter(READ_TIMEOUT_MS);
try try
{ {
state = await batteryCharacteristic.ReadAsync(cts.Token); percentage = await batteryCharacteristic.ReadAsync(cts.Token);
} }
catch (System.Exception exception) catch (System.Exception exception)
{ {
@ -839,17 +862,109 @@ namespace TINK.Services.BluetoothLock.BLE
cts.Dispose(); cts.Dispose();
} }
if (state == null || state.Length <= 0) if (percentage == null || percentage.Length <= 0)
{ {
Log.ForContext<LockItBase>().Debug("Retrieving charging level (ReadAsync-call) failed. Data read is null or empty.{BatteryCharacteristic}", ToSerilogString(batteryCharacteristic)); Log.ForContext<LockItBase>().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."); throw new System.Exception("Can not get battery percentage. No data read.");
} }
Log.ForContext<LockItBase>().Debug("Retrieving charging level (ReadAsync-call) succeeded.{Level}{BatteryCharacteristic}{Reading}", state[0], ToSerilogString(batteryCharacteristic), state); Log.ForContext<LockItBase>().Debug("Retrieving charging level (ReadAsync-call) succeeded.{Level}{BatteryCharacteristic}{Reading}", percentage[0], ToSerilogString(batteryCharacteristic), percentage);
return state[0]; return percentage[0];
} }
/// <summary> Gets version info about the lock. </summary>
/// <remarks>
/// 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,
/// </remarks>
/// <returns> .</returns>
public async Task<VersionInfoTdo> 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<LockItBase>().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<LockItBase>().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<LockItBase>().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<LockItBase>().Debug($"Connection state is {deviceState}.");
var firmwareVersionCharacteristic = await GetVersionsCharacteristicAsync();
if (firmwareVersionCharacteristic == null)
{
Log.ForContext<LockItBase>().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<LockItBase>().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<LockItBase>().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<LockItBase>().Debug("Retrieving versions info (ReadAsync-call) succeeded. {@LockInfoTdo}{StateCharacteristic}{Reading}",
VersionInfo,
ToSerilogString(firmwareVersionCharacteristic),
version);
return VersionInfo;
}
public VersionInfoTdo VersionInfo { get; private set; }
/// <summary> Opens lock. </summary> /// <summary> Opens lock. </summary>
/// <returns> Locking state.</returns> /// <returns> Locking state.</returns>
public abstract Task<LockitLockingState?> OpenAsync(); public abstract Task<LockitLockingState?> OpenAsync();

View file

@ -151,6 +151,8 @@ namespace TINK.Services.BluetoothLock.BLE
DeviceList.Add(lockIt); DeviceList.Add(lockIt);
await lockIt.GetVersionInfoAsync();
return await lockIt.GetLockStateAsync(); return await lockIt.GetLockStateAsync();
} }
@ -230,6 +232,8 @@ namespace TINK.Services.BluetoothLock.BLE
Log.ForContext<LockItByScanServiceBase>().Debug($"Auth succeeded for device {device}."); Log.ForContext<LockItByScanServiceBase>().Debug($"Auth succeeded for device {device}.");
locksList.Add(lockIt); locksList.Add(lockIt);
await lockIt.GetVersionInfoAsync();
} }
return locksList; return locksList;

View file

@ -20,7 +20,6 @@
<ItemGroup> <ItemGroup>
<Folder Include="Model\Device\" /> <Folder Include="Model\Device\" />
<Folder Include="Services\BluetoothLock\Crypto\" /> <Folder Include="Services\BluetoothLock\Crypto\" />
<Folder Include="Services\BluetoothLock\Tdo\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using TINK.Model.Connector; using TINK.Model.Connector;
@ -53,39 +53,32 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public bool IsGuidValid => Guid != TextToLockItTypeHelper.INVALIDLOCKGUID; 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) public bool Equals(LockInfo other)
{ {
if (Object.ReferenceEquals(other, null)) return false; if (ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true; if (ReferenceEquals(this, other)) return true;
if (this.GetType() != other.GetType()) return false; if (GetType() != other.GetType()) return false;
return ToString() == other.ToString(); return ToString() == other.ToString();
} }
public override int GetHashCode() public override int GetHashCode() => ToString().GetHashCode();
{
return ToString().GetHashCode();
}
public override string ToString() public override string ToString() => JsonConvert.SerializeObject(this);
{
return JsonConvert.SerializeObject(this);
}
public static bool operator ==(LockInfo lhs, LockInfo rhs) public static bool operator ==(LockInfo lhs, LockInfo rhs)
{ {
if (Object.ReferenceEquals(lhs, null)) if (ReferenceEquals(lhs, null))
return Object.ReferenceEquals(rhs, null) ? true /*null == null = true*/: false; return ReferenceEquals(rhs, null) ? true /*null == null = true*/: false;
return lhs.Equals(rhs); return lhs.Equals(rhs);
} }
public static bool operator !=(LockInfo lhs, LockInfo rhs) public static bool operator !=(LockInfo lhs, LockInfo rhs)
{ => !(lhs == rhs);
return !(lhs == rhs);
}
public class Builder public class Builder
{ {
@ -127,6 +120,5 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
return LockInfo; return LockInfo;
} }
} }
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Services.BluetoothLock.Tdo; using TINK.Services.BluetoothLock.Tdo;
@ -49,6 +49,17 @@ namespace TINK.Services.BluetoothLock
Task<bool> GetIsAlarmOffAsync(); Task<bool> GetIsAlarmOffAsync();
/// <summary>
/// Get info about lock firmware- hardware- and lock-version.
/// </summary>
/// <returns>Lock versions info.</returns>
Task<VersionInfoTdo> GetVersionInfoAsync();
/// <summary>
/// Holds info about lock firmware- hardware- and lock-version, null if info has not yet been read.
/// </summary>
VersionInfoTdo VersionInfo { get; }
Task SetIsAlarmOffAsync(bool isActivated); Task SetIsAlarmOffAsync(bool isActivated);
/// <summary>Gets the battery percentage.</summary> /// <summary>Gets the battery percentage.</summary>

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Services.BluetoothLock.Tdo; using TINK.Services.BluetoothLock.Tdo;
@ -37,6 +37,13 @@ namespace TINK.Services.BluetoothLock
public Task<double> GetBatteryPercentageAsync() => public Task<double> GetBatteryPercentageAsync() =>
throw new System.Exception($"Can not get battery percentage. Lock {BikeId} not found."); throw new System.Exception($"Can not get battery percentage. Lock {BikeId} not found.");
public Task<VersionInfoTdo> 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() => public DeviceState? GetDeviceState() =>
throw new NotImplementedException(); throw new NotImplementedException();

View file

@ -0,0 +1,41 @@
namespace TINK.Services.BluetoothLock.Tdo
{
public class VersionInfoTdo
{
/// <summary>
/// Holds info about firmware- and hardware version of a lock and the type of lock (lock version).
/// </summary>
private VersionInfoTdo() { }
/// <summary>
/// Holds the firmware version of the lock.
/// </summary>
public int FirmwareVersion { get; private set; }
/// <summary>
/// Holds the hardware version (revision) of the lock.
/// </summary>
public int HardwareVersion { get; private set; }
/// <summary>
/// Holds lock version (2 classic, 3 plus, 4 GPS).
/// </summary>
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;
}
}
}
}

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.339" android:versionCode="339"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.340" android:versionCode="340">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Mein konrad</string> <string>Mein konrad</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>339</string> <string>340</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.339</string> <string>3.0.340</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,96 +1,107 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.BikesAtStation.BikesAtStationPage" x:Class="TINK.View.BikesAtStation.BikesAtStationPage"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"> xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
<Shell.TitleView> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View">
<Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/> <Shell.TitleView>
<Label Style="{StaticResource Label-Navbar}" <Grid ColumnDefinitions="Auto, 1*">
Text="{Binding Title}"/> <Image Style="{StaticResource Image-Navbar}"/>
</Grid> <Label Style="{StaticResource Label-Navbar}"
</Shell.TitleView> Text="{Binding Title}"/>
<ContentPage.Resources> </Grid>
<ResourceDictionary> </Shell.TitleView>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> <ContentPage.Resources>
</ContentPage.Resources> <ResourceDictionary>
<ContentPage.Content> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<Frame> </ResourceDictionary>
<StackLayout </ContentPage.Resources>
Orientation="Vertical">
<!-- Title bar stack layout--> <ContentPage.Content>
<StackLayout
Orientation="Vertical"> <Frame>
<Label
HorizontalOptions="Center" <!--Grid for Bike(s) view and Running process in same row-->
FontAttributes="Bold" <Grid>
TextColor="{DynamicResource primary-back-title-color}" <Grid.RowDefinitions>
Text="{Binding StationDetailText}"/> <RowDefinition Height="Auto"/>
<BoxView <RowDefinition Height="*"/>
HeightRequest="1" <RowDefinition Height="Auto"/>
Color="{DynamicResource primary-back-title-color}"/> </Grid.RowDefinitions>
</StackLayout>
<!-- Center stack layout --> <!--Bike(s) view-->
<StackLayout <StackLayout Grid.Row="0"
Orientation="Vertical" Orientation="Vertical">
VerticalOptions="CenterAndExpand">
<ListView <!--Title-->
x:Name="BikesAtStationListView" <Label
SelectionMode="None" HorizontalOptions="Center"
SelectedItem="{Binding SelectedBike}" FontAttributes="Bold"
IsEnabled="{Binding IsIdle}" TextColor="{DynamicResource primary-back-title-color}"
IsVisible="{Binding IsBikesListVisible}" Text="{Binding StationDetailText}"/>
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> <!--Line-->
<Label <BoxView
IsVisible="{Binding IsNoBikesAtStationVisible}" HeightRequest="1"
Text="{Binding NoBikesAtStationText}"/> Color="{DynamicResource primary-back-title-color}"/>
</StackLayout> </StackLayout>
<!-- Status bar stack layout-->
<StackLayout <!--Bike(s)-->
Orientation="Vertical"> <ListView
<StackLayout Grid.Row="1"
Orientation="Horizontal"> x:Name="BikesAtStationListView"
<Label SelectionMode="None"
HeightRequest="24" SelectedItem="{Binding SelectedBike}"
FontSize="Small" IsEnabled="{Binding IsIdle}"
Text="{Binding StatusInfoText}" IsVisible="{Binding IsBikesListVisible}"
VerticalOptions="Center" HasUnevenRows="True"
HorizontalOptions="FillAndExpand"/> ItemTemplate="{StaticResource bikeTemplateSelector}"/>
<ActivityIndicator IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}" <!--No Bikes-->
HeightRequest="20" <Label
VerticalOptions="CenterAndExpand" Grid.Row="1"
HorizontalOptions="End"> IsVisible="{Binding IsNoBikesAtStationVisible}"
<ActivityIndicator.WidthRequest> Text="{Binding NoBikesAtStationText}"/>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest> <!-- Contact and Login at end of page-->
<ActivityIndicator.Color> <StackLayout
<OnPlatform x:TypeArguments="Color" Orientation="Vertical"
Android="#D21113" iOS="#D21113" WinPhone="#D21113" /> Grid.Row="2">
</ActivityIndicator.Color>
</ActivityIndicator> <!--Line-->
</StackLayout> <BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/>
<BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/>
<Label <!--Contact to operator-->
TextType="Html" <Label
Text="{Binding ContactSupportHintText}"> TextType="Html"
<Label.GestureRecognizers> Text="{Binding ContactSupportHintText}">
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/> <Label.GestureRecognizers>
</Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label> </Label.GestureRecognizers>
<Label </Label>
IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html" <!--Login required-->
Text="{Binding LoginRequiredHintText}"> <Label
<Label.GestureRecognizers> IsVisible="{Binding IsLoginRequiredHintVisible}"
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/> TextType="Html"
</Label.GestureRecognizers> Text="{Binding LoginRequiredHintText}">
</Label> <Label.GestureRecognizers>
</StackLayout> <TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</StackLayout> </Label.GestureRecognizers>
</Frame> </Label>
</ContentPage.Content> </StackLayout>
</ContentPage>
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
Grid.Row="1"/>
</Grid>
</Frame>
</ContentPage.Content>
</ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -23,11 +23,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -22,11 +22,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -22,11 +22,13 @@
HeightRequest="1400" HeightRequest="1400"
WidthRequest="1000" WidthRequest="1000"
Source="{Binding Uri}" /> Source="{Binding Uri}" />
<ActivityIndicator
x:Name="ActivityIndicatorLoading" <ActivityIndicator Grid.Row="0"
HeightRequest="100" x:Name="ActivityIndicatorLoading"
VerticalOptions="CenterAndExpand" Scale="2"
HorizontalOptions="CenterAndExpand"/> VerticalOptions="CenterAndExpand"
</Grid> HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,69 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.FindBike.FindBikePage" x:Class="TINK.View.FindBike.FindBikePage"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike"> xmlns:local_bike="clr-namespace:TINK.View.Bike"
<Shell.TitleView> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View">
<Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/> <Shell.TitleView>
<Label Style="{StaticResource Label-Navbar}" <Grid ColumnDefinitions="Auto, 1*">
Text="{x:Static resources:AppResources.MarkingFindBike}"/> <Label Style="{StaticResource Label-Navbar}"
</Grid> Text="{x:Static resources:AppResources.MarkingFindBike}"/>
</Shell.TitleView> </Grid>
<ContentPage.Resources> </Shell.TitleView>
<ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <ContentPage.Resources>
</ResourceDictionary> <ResourceDictionary>
</ContentPage.Resources> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<ContentPage.Content> </ResourceDictionary>
<Frame> </ContentPage.Resources>
<StackLayout>
<Entry <ContentPage.Content>
Placeholder="Fahrrad-Nummer bitte hier eingeben"
IsVisible="{Binding IsSelectBikeVisible}" <Frame>
MaxLength="10"
CursorPosition="0" <!--Grid for Bike(s) view and Running process in same row-->
Text="{Binding BikeIdUserInput}"> <Grid>
</Entry> <Grid.RowDefinitions>
<Button <RowDefinition Height="*"/>
Text="Rad Wählen" </Grid.RowDefinitions>
IsEnabled="{Binding IsSelectBikeEnabled}"
IsVisible="{Binding IsSelectBikeVisible}" <!--Search bike-->
Command="{Binding OnSelectBikeRequest}"> <StackLayout Grid.Row="0">
</Button> <Entry
<ListView Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
x:Name="FindBikeListView" IsVisible="{Binding IsSelectBikeVisible}"
SelectionMode="None" MaxLength="10"
SelectedItem="{Binding SelectedBike}" CursorPosition="0"
IsEnabled="{Binding IsIdle}" Text="{Binding BikeIdUserInput}"/>
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True" <Button
ItemTemplate="{StaticResource bikeTemplateSelector}"/> Text="{x:Static resources:AppResources.MarkingFindBike}"
<StackLayout IsEnabled="{Binding IsSelectBikeEnabled}"
VerticalOptions="EndAndExpand" IsVisible="{Binding IsSelectBikeVisible}"
Orientation="Horizontal"> Command="{Binding OnSelectBikeRequest}"/>
<Label
HeightRequest="24" <ListView
Text="{Binding StatusInfoText}" x:Name="FindBikeListView"
FontSize="Small" SelectionMode="None"
VerticalOptions="Center" SelectedItem="{Binding SelectedBike}"
HorizontalOptions="FillAndExpand"/> IsEnabled="{Binding IsIdle}"
<ActivityIndicator IsRunning="{Binding IsRunning}" IsVisible="{Binding IsBikesListVisible}"
IsVisible="{Binding IsRunning}" HasUnevenRows="True"
HeightRequest="20" ItemTemplate="{StaticResource bikeTemplateSelector}"/>
VerticalOptions="CenterAndExpand"
HorizontalOptions="End"> </StackLayout>
<ActivityIndicator.WidthRequest>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" /> <!--While process is running-->
</ActivityIndicator.WidthRequest> <sharedGui:RunningProcessView
<ActivityIndicator.Color> Grid.Row="0"
<OnPlatform x:TypeArguments="Color" IsVisible="{Binding IsRunning}"/>
Android="#D21113" iOS="#D21113" WinPhone="#D21113" />
</ActivityIndicator.Color> </Grid>
</ActivityIndicator>
</StackLayout> </Frame>
</StackLayout> </ContentPage.Content>
</Frame> </ContentPage>
</ContentPage.Content>
</ContentPage>

View file

@ -1,113 +1,116 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 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:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Map.MapPage" x:Class="TINK.View.Map.MapPage"
BackgroundColor="{DynamicResource Key=primary-back-title-color}"> BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Shell.TitleView>
<Image Style="{StaticResource Image-Navbar}"/> <Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Image Style="{StaticResource Image-Navbar}"/>
Text="{x:Static resources:AppResources.MarkingMapPage}"/> <Label Style="{StaticResource Label-Navbar}"
</Grid> Text="{x:Static resources:AppResources.MarkingMapPage}"/>
</Shell.TitleView> </Grid>
<Grid </Shell.TitleView>
RowDefinitions="3,46,1*,33"
ColumnDefinitions="1*,Auto,1*" <!--Grid for Map with Buttons and Running process-->
IsEnabled="{Binding IsMapPageEnabled}" <Grid
VerticalOptions="FillAndExpand" RowDefinitions="3,46,1*,Auto"
> ColumnDefinitions="1*,Auto,1*"
<maps:Map IsEnabled="{Binding IsMapPageEnabled}"
Grid.RowSpan="3" VerticalOptions="FillAndExpand">
Grid.ColumnSpan="3"
WidthRequest="320" <!--Map-->
HeightRequest="800" <maps:Map
x:Name="MyMap" Grid.RowSpan="3"
IsShowingUser="False" Grid.ColumnSpan="3"
MapType="Street"> WidthRequest="320"
<maps:Map.Behaviors> HeightRequest="800"
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> x:Name="MyMap"
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> IsShowingUser="False"
</maps:Map.Behaviors> MapType="Street">
</maps:Map> <maps:Map.Behaviors>
<Frame <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
CornerRadius="13" <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
Grid.Row="1" </maps:Map.Behaviors>
Grid.Column="1" </maps:Map>
Margin="0"
Padding="0" <!--Buttons for choosing bike type-->
BackgroundColor="{DynamicResource secondary-back-title-color}"> <Frame
<StackLayout Orientation="Horizontal" CornerRadius="13"
Margin="0" Grid.Row="1"
Padding="0"> Grid.Column="1"
<Button Margin="0"
x:Name="KonradButton" Padding="0"
AutomationId ="FilterKonrad_button" BackgroundColor="{DynamicResource secondary-back-title-color}">
Text="{x:Static resources:AppResources.MarkingCityBike}" <StackLayout
Command="{Binding OnToggleTinkToKonrad}" Orientation="Horizontal"
IsVisible="{Binding IsToggleVisible}" Margin="0"
BackgroundColor="{Binding KonradColor}" Padding="0">
BorderColor="{Binding KonradColor}" <Button
BorderWidth="0" x:Name="KonradButton"
VerticalOptions="Center" AutomationId ="FilterKonrad_button"
HorizontalOptions="Center" Text="{x:Static resources:AppResources.MarkingCityBike}"
WidthRequest="94" Command="{Binding OnToggleTinkToKonrad}"
HeightRequest="40" IsVisible="{Binding IsToggleVisible}"
BorderRadius="10" BackgroundColor="{Binding KonradColor}"
Margin="3,0,0,0" BorderColor="{Binding KonradColor}"
FontSize="Small" BorderWidth="0"
FontAttributes="Bold" VerticalOptions="Center"
TextColor="{Binding NoKonradColor}"> HorizontalOptions="Center"
</Button> WidthRequest="94"
<Button HeightRequest="40"
x:Name="TINKButton" BorderRadius="10"
AutomationId ="FilterTINK_button" Margin="3,0,0,0"
Text="{x:Static resources:AppResources.MarkingCargoBike}" FontSize="Small"
Command="{Binding OnToggleKonradToTink}" FontAttributes="Bold"
IsVisible="{Binding IsToggleVisible}" TextColor="{Binding NoKonradColor}">
BackgroundColor="{Binding TinkColor}" </Button>
BorderColor="{Binding TinkColor}" <Button
BorderWidth="0" x:Name="TINKButton"
VerticalOptions="Center" AutomationId ="FilterTINK_button"
HorizontalOptions="Center" Text="{x:Static resources:AppResources.MarkingCargoBike}"
WidthRequest="94" Command="{Binding OnToggleKonradToTink}"
HeightRequest="40" IsVisible="{Binding IsToggleVisible}"
BorderRadius="10" BackgroundColor="{Binding TinkColor}"
Margin="0,0,3,0" BorderColor="{Binding TinkColor}"
FontSize="Small" BorderWidth="0"
FontAttributes="Bold" VerticalOptions="Center"
TextColor="{Binding NoTinkColor}"> HorizontalOptions="Center"
</Button> WidthRequest="94"
</StackLayout> HeightRequest="40"
</Frame> BorderRadius="10"
<StackLayout Margin="0,0,3,0"
Grid.Row="3" FontSize="Small"
Grid.ColumnSpan="3" FontAttributes="Bold"
Margin="6,3,6,6" TextColor="{Binding NoTinkColor}">
VerticalOptions="EndAndExpand" </Button>
Orientation="Horizontal"> </StackLayout>
<Label </Frame>
HeightRequest="24"
FontSize="Small" <!--While process is running-->
Text="{Binding StatusInfoText}" <!--Spinner-->
TextColor="White" <ActivityIndicator
VerticalOptions="Center" Grid.RowSpan="4"
HorizontalOptions="FillAndExpand"/> Grid.ColumnSpan="3"
<ActivityIndicator IsRunning="{Binding IsRunning}" IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsRunning}"
HeightRequest="20" Scale="2"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
HorizontalOptions="End"> HorizontalOptions="CenterAndExpand"
<ActivityIndicator.WidthRequest> Color="{x:DynamicResource primary-back-title-color}"/>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
</ActivityIndicator.WidthRequest> <!--Info text-->
<ActivityIndicator.Color> <Label
<OnPlatform x:TypeArguments="Color" Grid.Row="3"
Android="White" iOS="White" WinPhone="White"/> Grid.ColumnSpan="3"
</ActivityIndicator.Color> Text="{Binding StatusInfoText}"
</ActivityIndicator> TextColor="White"
</StackLayout> FontSize="Small"
</Grid> HorizontalOptions="Center"
</ContentPage> Padding="0,0,0,10"/>
</Grid>
</ContentPage>

View file

@ -1,65 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.MyBikes.MyBikesPage" x:Class="TINK.View.MyBikes.MyBikesPage"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike"> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
<Shell.TitleView> xmlns:local_bike="clr-namespace:TINK.View.Bike">
<Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/> <Shell.TitleView>
<Label Style="{StaticResource Label-Navbar}" <Grid ColumnDefinitions="Auto, 1*">
Text="{x:Static resources:AppResources.MarkingMyBikes}"/> <Label Style="{StaticResource Label-Navbar}"
</Grid> Text="{x:Static resources:AppResources.MarkingMyBikes}"/>
</Shell.TitleView> </Grid>
<ContentPage.Resources> </Shell.TitleView>
<ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <ContentPage.Resources>
</ResourceDictionary> <ResourceDictionary>
</ContentPage.Resources> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
<ContentPage.Content> </ResourceDictionary>
<Frame> </ContentPage.Resources>
<StackLayout
Orientation="Vertical"> <ContentPage.Content>
<!-- Center stack layout -->
<StackLayout <Frame>
VerticalOptions="CenterAndExpand"
Orientation="Vertical"> <!--Grid for Bike(s) view and Running process in same row-->
<ListView <Grid>
x:Name="MyBikesListView" <Grid.RowDefinitions>
SelectionMode="None" <RowDefinition Height="*"/>
SelectedItem="{Binding SelectedBike}" </Grid.RowDefinitions>
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}" <!--Bike(s) view-->
HasUnevenRows="True" <StackLayout Grid.Row="0"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> VerticalOptions="CenterAndExpand"
<Label Orientation="Vertical">
IsVisible="{Binding IsNoBikesOccupiedVisible}"
Text="{Binding NoBikesOccupiedText}"/> <!--Bike(s)-->
</StackLayout> <ListView
<!-- Status bar stack layout--> x:Name="MyBikesListView"
<StackLayout SelectionMode="None"
Orientation="Horizontal"> SelectedItem="{Binding SelectedBike}"
<Label IsEnabled="{Binding IsIdle}"
HeightRequest="24" IsVisible="{Binding IsBikesListVisible}"
FontSize="Small" HasUnevenRows="True"
Text="{Binding StatusInfoText}" ItemTemplate="{StaticResource bikeTemplateSelector}"/>
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/> <!--No Bikes-->
<ActivityIndicator IsRunning="{Binding IsRunning}" <Label
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsNoBikesOccupiedVisible}"
HeightRequest="20" Text="{Binding NoBikesOccupiedText}"/>
VerticalOptions="CenterAndExpand"
HorizontalOptions="End"> </StackLayout>
<ActivityIndicator.WidthRequest>
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" /> <!--While process is running-->
</ActivityIndicator.WidthRequest> <sharedGui:RunningProcessView
<ActivityIndicator.Color> Grid.Row="0"
<OnPlatform x:TypeArguments="Color" IsVisible="{Binding IsRunning}"/>
Android="#D21113" iOS="#D21113" WinPhone="#D21113" />
</ActivityIndicator.Color> </Grid>
</ActivityIndicator>
</StackLayout> </Frame>
</StackLayout>
</Frame> </ContentPage.Content>
</ContentPage.Content> </ContentPage>
</ContentPage>

View file

@ -1,4 +1,4 @@

using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
@ -17,15 +17,15 @@ namespace TINK.Droid
[IntentFilter(new[] { Intent.ActionView }, [IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault },
DataScheme = "https", DataScheme = "https",
DataHost = "sharee.bike", DataHost = "app.sharee.bike",
DataPathPrefix = "/sharee", DataPathPrefix = "/App-shareebike",
AutoVerify = true)] AutoVerify = true)]
[IntentFilter(new[] { Intent.ActionView }, [IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault }, Categories = new[] { Intent.ActionView, Intent.CategoryBrowsable, Intent.CategoryDefault },
DataScheme = "http", DataScheme = "http",
DataHost = "sharee.bike", DataHost = "app.sharee.bike",
DataPathPrefix = "/sharee", DataPathPrefix = "/App-shareebike",
AutoVerify = true)] AutoVerify = true)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.339" android:versionCode="339"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.340" android:versionCode="340">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="30" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>sharee.bike</string> <string>sharee.bike</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>339</string> <string>340</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.339</string> <string>3.0.340</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,13 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.BikeNS; using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS; using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.State; using TINK.Model.State;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
public class BikeInfo : Model.Bikes.BikeInfoNS.BC.BikeInfo, IBikeInfo public class BikeInfo : BC.BikeInfo, IBikeInfo
{ {
/// <summary> /// <summary>
/// Constructs a bike info object for a available bike. /// Constructs a bike info object for a available bike.
@ -18,7 +17,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param> /// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <param name="tariffDescription">Hold tariff description of bike.</param> /// <param name="tariffDescription">Hold tariff description of bike.</param>
public BikeInfo( public BikeInfo(
BikeNS.Bike bike, Bike bike,
Drive drive, Drive drive,
int lockId, int lockId,
Guid lockGuid, Guid lockGuid,
@ -29,7 +28,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
IEnumerable<string> group = null) : base( IEnumerable<string> group = null) : base(
new StateInfo(), new StateInfo(),
bike != null bike != null
? new BikeNS.Bike( ? new Bike(
bike.Id, bike.Id,
LockModel.ILockIt /* Ensure consistend lock model value */, LockModel.ILockIt /* Ensure consistend lock model value */,
bike.WheelType, bike.WheelType,
@ -43,7 +42,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
operatorUri, operatorUri,
tariffDescription) tariffDescription)
{ {
LockInfo = new Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo.Builder { Id = lockId, Guid = lockGuid }.Build(); LockInfo = new LockInfo.Builder { Id = lockId, Guid = lockGuid }.Build();
} }
/// <summary> /// <summary>
@ -59,7 +58,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <param name="tariffDescription">Hold tariff description of bike.</param> /// <param name="tariffDescription">Hold tariff description of bike.</param>
/// <param name="dateTimeProvider">Date time provider to calculate reaining time.</param> /// <param name="dateTimeProvider">Date time provider to calculate reaining time.</param>
public BikeInfo( public BikeInfo(
BikeNS.Bike bike, Bike bike,
Drive drive, Drive drive,
int lockId, int lockId,
Guid lockGuid, Guid lockGuid,
@ -80,7 +79,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
mailAddress, mailAddress,
""), ""),
bike != null bike != null
? new BikeNS.Bike( ? new Bike(
bike.Id, bike.Id,
LockModel.ILockIt /* Ensure consistend lock model value */, LockModel.ILockIt /* Ensure consistend lock model value */,
bike.WheelType, bike.WheelType,
@ -94,7 +93,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
operatorUri, operatorUri,
tariffDescription) 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();
} }
/// <summary> /// <summary>
@ -110,7 +109,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <param name="tariffDescription">Hold tariff description of bike.</param> /// <param name="tariffDescription">Hold tariff description of bike.</param>
/// <param name="wheelType"></param> /// <param name="wheelType"></param>
public BikeInfo( public BikeInfo(
BikeNS.Bike bike, Bike bike,
Drive drive, Drive drive,
int lockId, int lockId,
Guid lockGuid, Guid lockGuid,
@ -129,7 +128,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
mailAddress, mailAddress,
""), ""),
bike != null bike != null
? new BikeNS.Bike( ? new Bike(
bike.Id, bike.Id,
LockModel.ILockIt /* Ensure consistend lock model value */, LockModel.ILockIt /* Ensure consistend lock model value */,
bike.WheelType, bike.WheelType,
@ -143,16 +142,16 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
operatorUri, operatorUri,
tariffDescription) 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.")) bikeInfo ?? throw new ArgumentException($"Can not copy-construct {typeof(BikeInfo).Name}-object. Source bike info must not be null."))
{ {
LockInfo = lockInfo LockInfo = lockInfo
?? throw new ArgumentException($"Can not copy-construct {typeof(BikeInfo).Name}-object. Source lock object must not be null."); ?? 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; }
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
@ -19,5 +19,10 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
Guid Guid { get; set; } Guid Guid { get; set; }
byte[] Seed { get; } byte[] Seed { get; }
/// <summary>
/// Gets the version info of the locks.
/// </summary>
IVersionInfo VersionInfo { get; set; }
} }
} }

View file

@ -0,0 +1,20 @@
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{
public interface IVersionInfo
{
/// <summary>
/// Holds the firmware version of the lock.
/// </summary>
int FirmwareVersion { get; }
/// <summary>
/// Holds the hardware version (revision) of the lock.
/// </summary>
int HardwareVersion { get; }
/// <summary>
/// Holds lock version (2 classic, 3 plus, 4 GPS).
/// </summary>
int LockVersion { get; }
}
}

View file

@ -1,11 +1,11 @@
using System; using System;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
public class LockInfoMutable : TINK.Model.Bikes.BikeInfoNS.BluetoothLock.ILockInfoMutable public class LockInfoMutable : ILockInfoMutable
{ {
/// <summary> Lock info object. </summary> /// <summary> Lock info object. </summary>
private Model.Bikes.BikeInfoNS.BluetoothLock.LockInfo LockInfo { get; set; } private LockInfo LockInfo { get; set; }
/// <summary> Constructs a bluetooth lock info object. </summary> /// <summary> Constructs a bluetooth lock info object. </summary>
/// <param name="id">Id of lock must always been known when constructing an lock info object.</param> /// <param name="id">Id of lock must always been known when constructing an lock info object.</param>
@ -15,9 +15,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
byte[] userKey, byte[] userKey,
byte[] adminKey, byte[] adminKey,
byte[] seed, 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; public int Id => LockInfo.Id;
@ -26,7 +26,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public Guid Guid public Guid Guid
{ {
get => LockInfo.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; public byte[] Seed => LockInfo.Seed;
@ -35,19 +35,24 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public byte[] AdminKey => LockInfo.AdminKey; public byte[] AdminKey => LockInfo.AdminKey;
public Model.Bikes.BikeInfoNS.BluetoothLock.LockingState State public LockingState State
{ {
get => LockInfo.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();
} }
/// <summary> Holds the percentage of lock battery.</summary> /// <summary> Holds the percentage of lock battery.</summary>
public double BatteryPercentage { get; set; } = double.NaN; public double BatteryPercentage { get; set; } = double.NaN;
/// <summary>
/// Gets the version info of the lock.
/// </summary>
public IVersionInfo VersionInfo { get; set; } = new VersionInfo.Builder().Build();
/// <summary> Loads lock info object from values. </summary> /// <summary> Loads lock info object from values. </summary>
public void Load(int id, Guid guid, byte[] seed, byte[] userKey, byte[] adminKey) 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();
} }
} }
} }

View file

@ -0,0 +1,69 @@
using Newtonsoft.Json;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{
public class VersionInfo : IVersionInfo
{
/// <summary>
/// Holds info about firmware- and hardware version of a lock and the type of lock (lock version).
/// </summary>
private VersionInfo() { }
/// <summary>
/// Holds the firmware version of the lock.
/// </summary>
public int FirmwareVersion { get; private set; } = 0;
/// <summary>
/// Holds the hardware version (revision) of the lock.
/// </summary>
public int HardwareVersion { get; private set; } = 0;
/// <summary>
/// Holds lock version (2 classic, 3 plus, 4 GPS).
/// </summary>
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;
}
}
}
}

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
@ -226,7 +226,8 @@ namespace TINK.Model.Connector
state.Value, state.Value,
bike.OperatorUri, bike.OperatorUri,
location, location,
bike.LockInfo.BatteryPercentage)).GetIsBookingResponseOk(bike.Id); bike.LockInfo.BatteryPercentage,
bike.LockInfo.VersionInfo)).GetIsBookingResponseOk(bike.Id);
} }
catch (Exception) catch (Exception)
{ {
@ -320,4 +321,4 @@ namespace TINK.Model.Connector
public async Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike) public async Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
=> await CopriServer.CloseAync(bike); => await CopriServer.CloseAync(bike);
} }
} }

View file

@ -594,6 +594,16 @@ namespace TINK.Model
new Version(3, 0, 339), new Version(3, 0, 339),
AppResources.ChangeLog3_0_339_MK, AppResources.ChangeLog3_0_339_MK,
new List<AppFlavor> { AppFlavor.MeinKonrad } new List<AppFlavor> { AppFlavor.MeinKonrad }
},
{
new Version(3, 0, 340),
AppResources.ChangeLog_MinorDesignImprovements,
new List<AppFlavor> { AppFlavor.LastenradBayern, AppFlavor.MeinKonrad }
},
{
new Version(3, 0, 340),
AppResources.ChangeLog_MinorBugFixes,
new List<AppFlavor> { AppFlavor.ShareeBike }
} }
}; };

View file

@ -645,6 +645,15 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to A few small things have been changed in the design..
/// </summary>
public static string ChangeLog_MinorDesignImprovements {
get {
return ResourceManager.GetString("ChangeLog_MinorDesignImprovements", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Updated to latest lock firmware.. /// Looks up a localized string similar to Updated to latest lock firmware..
/// </summary> /// </summary>

View file

@ -1031,4 +1031,7 @@ Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben:
<data name="ChangeLog3_0_339_SB_LB" xml:space="preserve"> <data name="ChangeLog3_0_339_SB_LB" xml:space="preserve">
<value>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!</value> <value>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!</value>
</data> </data>
<data name="ChangeLog_MinorDesignImprovements" xml:space="preserve">
<value>Es wurden ein paar Kleinigkeiten im Design verändert.</value>
</data>
</root> </root>

View file

@ -1123,4 +1123,7 @@ You can now see at a glance which app version you have installed: in the menu at
<data name="ChangeLog3_0_339_SB_LB" xml:space="preserve"> <data name="ChangeLog3_0_339_SB_LB" xml:space="preserve">
<value>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!</value> <value>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!</value>
</data> </data>
<data name="ChangeLog_MinorDesignImprovements" xml:space="preserve">
<value>A few small things have been changed in the design.</value>
</data>
</root> </root>

View file

@ -1400,6 +1400,10 @@ Sie können nun auf einen Blick sehen, welche App-Version Sie installiert haben:
<source>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!</source> <source>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!</source>
<target state="translated">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!</target> <target state="translated">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!</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog_MinorDesignImprovements" translate="yes" xml:space="preserve">
<source>A few small things have been changed in the design.</source>
<target state="translated">Es wurden ein paar Kleinigkeiten im Design verändert.</target>
</trans-unit>
</group> </group>
</body> </body>
</file> </file>

View file

@ -1,4 +1,4 @@

using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -6,6 +6,7 @@ using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.Logging; using TINK.Model.Logging;
using TINK.Repository.Exception; using TINK.Repository.Exception;
@ -172,10 +173,11 @@ namespace TINK.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto location, LocationDto location,
double batteryLevel) => double batteryLevel,
IVersionInfo versionInfo) =>
await DoUpdateLockingStateAsync( await DoUpdateLockingStateAsync(
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri, operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
requestBuilder.UpateLockingState(bikeId, state, location, batteryLevel), requestBuilder.UpateLockingState(bikeId, state, location, batteryLevel, versionInfo),
UserAgent); UserAgent);
/// <summary> Gets booking request request. </summary> /// <summary> Gets booking request request. </summary>

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository.Request; using TINK.Repository.Request;
using TINK.Repository.Response; using TINK.Repository.Response;
@ -1636,7 +1637,8 @@ namespace TINK.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryLevel) => null; double batteryLevel,
IVersionInfo versionInfo) => null;
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
=> null; => null;

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using MonkeyCache.FileStore; using MonkeyCache.FileStore;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository.Request; using TINK.Repository.Request;
@ -171,7 +172,8 @@ namespace TINK.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryLevel) double batteryLevel,
IVersionInfo versionInfo)
=> throw new System.Exception("Aktualisierung des Schlossstatuses im Offlinemodus nicht möglich!"); => throw new System.Exception("Aktualisierung des Schlossstatuses im Offlinemodus nicht möglich!");
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository.Request; using TINK.Repository.Request;
using TINK.Repository.Response; using TINK.Repository.Response;
@ -69,7 +70,8 @@ namespace TINK.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto location = null, LocationDto location = null,
double batteryPercentage = double.NaN); double batteryPercentage = double.NaN,
IVersionInfo versionInfo = null);
/// <summary> Books a bluetooth bike. </summary> /// <summary> Books a bluetooth bike. </summary>
/// <param name="bikeId">Id of the bike to book.</param> /// <param name="bikeId">Id of the bike to book.</param>

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
namespace TINK.Repository.Request namespace TINK.Repository.Request
@ -63,14 +64,16 @@ namespace TINK.Repository.Request
/// <summary> Gets the request for updating lock state for a booked bike. </summary> /// <summary> Gets the request for updating lock state for a booked bike. </summary>
/// <param name="bikeId">Id of the bike to update locking state for.</param> /// <param name="bikeId">Id of the bike to update locking state for.</param>
/// <param name="location">Geolocation of lock when state change occurred.</param>
/// <param name="state">New locking state.</param> /// <param name="state">New locking state.</param>
/// <param name="location">Geolocation of lock when state change occurred.</param>
/// <param name="versionInfo">Information about lock (firmware version, hardware version, ...).</param>
/// <returns>Request to update locking state.</returns> /// <returns>Request to update locking state.</returns>
string UpateLockingState( string UpateLockingState(
string bikeId, string bikeId,
lock_state state, lock_state state,
LocationDto location = null, LocationDto location = null,
double batteryPercentage = double.NaN); double batteryPercentage = double.NaN,
IVersionInfo versionInfo = null);
/// <summary> Gets the booking request (synonym: booking == renting == mieten). </summary> /// <summary> Gets the booking request (synonym: booking == renting == mieten). </summary>
/// <param name="bikeId">Id of the bike to book.</param> /// <param name="bikeId">Id of the bike to book.</param>

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository.Exception; using TINK.Repository.Exception;
@ -101,7 +102,11 @@ namespace TINK.Repository.Request
public string StartReturningBike(string bikeId) public string StartReturningBike(string bikeId)
=> throw new NotSupportedException(); => throw new NotSupportedException();
public string UpateLockingState(string bikeId, lock_state state, LocationDto geolocation, double batteryPercentage) /// <summary>
/// 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.
/// </summary>
/// <exception cref="NotSupportedException"></exception>
public string UpateLockingState(string bikeId, lock_state state, LocationDto geolocation, double batteryPercentage, IVersionInfo versionInfo)
=> throw new NotSupportedException(); => throw new NotSupportedException();
public string DoBook(string bikeId, Guid guid, double batteryPercentage) public string DoBook(string bikeId, Guid guid, double batteryPercentage)

View file

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository.Exception; using TINK.Repository.Exception;
using TINK.Services.Logging; using TINK.Services.Logging;
@ -129,17 +130,20 @@ namespace TINK.Repository.Request
/// <remarks> Operator specific call.</remarks> /// <remarks> Operator specific call.</remarks>
/// <param name="bikeId">Id of the bike to update locking state for.</param> /// <param name="bikeId">Id of the bike to update locking state for.</param>
/// <param name="state">New locking state.</param> /// <param name="state">New locking state.</param>
/// <param name="versionInfo">Information about lock (firmware version, hardware version, ...).</param>
/// <returns>Request to update locking state.</returns> /// <returns>Request to update locking state.</returns>
public string UpateLockingState( public string UpateLockingState(
string bikeId, string bikeId,
lock_state state, lock_state state,
LocationDto geolocation, LocationDto geolocation,
double batteryPercentage) double batteryPercentage,
IVersionInfo versionInfo)
=> "request=booking_update" + => "request=booking_update" +
GetBikeIdParameter(bikeId) + GetBikeIdParameter(bikeId) +
GetLocationParameters(geolocation) + GetLocationParameters(geolocation) +
GetLockStateParameter(state) + GetLockStateParameter(state) +
GetBatteryPercentageParameters(batteryPercentage) + GetBatteryPercentageParameters(batteryPercentage) +
GetVersionInfoParameter(versionInfo) +
AuthCookieParameter + AuthCookieParameter +
UiIsoLanguageNameParameter; UiIsoLanguageNameParameter;
@ -272,6 +276,10 @@ namespace TINK.Repository.Request
? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}" ? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}"
: string.Empty; : 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;
/// <summary> Gets the geolocation parameter. </summary> /// <summary> Gets the geolocation parameter. </summary>
/// <param name="geolocation">Geolocation or null.</param> /// <param name="geolocation">Geolocation or null.</param>
private static string GetLocationParameters(LocationDto geolocation) private static string GetLocationParameters(LocationDto geolocation)

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector.Updater; using TINK.Model.Connector.Updater;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository; using TINK.Repository;
@ -235,13 +236,15 @@ namespace TINK.Model.Services.CopriApi
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto location, LocationDto location,
double batteryLevel) double batteryLevel,
IVersionInfo versionInfo)
=> await HttpsServer.UpdateLockingStateAsync( => await HttpsServer.UpdateLockingStateAsync(
bikeId, bikeId,
state, state,
operatorUri, operatorUri,
location, location,
batteryLevel); batteryLevel,
versionInfo);
/// <summary> Books a bike. </summary> /// <summary> Books a bike. </summary>
/// <param name="bikeId">Id of the bike to book.</param> /// <param name="bikeId">Id of the bike to book.</param>
@ -303,4 +306,4 @@ namespace TINK.Model.Services.CopriApi
=> await HttpsServer.DoSubmitMiniSurvey(answers); => await HttpsServer.DoSubmitMiniSurvey(answers);
} }
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Request; using TINK.Repository.Request;
@ -53,13 +54,15 @@ namespace TINK.Model.Services.CopriApi
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryLevel) double batteryLevel,
IVersionInfo versionInfo)
=> await monkeyStore.UpdateLockingStateAsync( => await monkeyStore.UpdateLockingStateAsync(
bikeId, bikeId,
state, state,
operatorUri, operatorUri,
geolocation, geolocation,
batteryLevel); batteryLevel,
versionInfo);
public async Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public async Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
{ {

View file

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms" <ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.Themes.Konrad"> x:Class="TINK.Themes.Konrad">
<!--Main color-->
<Color x:Key="primary-back-title-color">#D21113</Color> <Color x:Key="primary-back-title-color">#D21113</Color>
<!--Secondary color-->
<Color x:Key="secondary-back-title-color">#FF0020</Color> <Color x:Key="secondary-back-title-color">#FF0020</Color>
<!--Primary Button-->
<Style TargetType="Button"> <Style TargetType="Button">
<Setter Property="WidthRequest" Value="400" /> <Setter Property="WidthRequest" Value="400" />
<Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Center" />
@ -28,6 +32,8 @@
</Trigger> </Trigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<!--Secondary Button-->
<Style x:Key="SecondaryButton" TargetType="Button"> <Style x:Key="SecondaryButton" TargetType="Button">
<Setter Property="WidthRequest" Value="400" /> <Setter Property="WidthRequest" Value="400" />
<Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="HorizontalOptions" Value="Center" />
@ -51,6 +57,7 @@
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<!--Switch-->
<Style TargetType="Switch"> <Style TargetType="Switch">
<Style.Triggers> <Style.Triggers>
<Trigger TargetType="Switch" <Trigger TargetType="Switch"
@ -65,17 +72,24 @@
</Trigger> </Trigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<!--Slider-->
<Style TargetType="Slider"> <Style TargetType="Slider">
<Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/> <Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Setter Property="Background" Value="LightGray"/> <Setter Property="Background" Value="LightGray"/>
</Style> </Style>
<!--Label-->
<Style TargetType="Label"> <Style TargetType="Label">
<Setter Property="FontSize" Value="Default"/> <Setter Property="FontSize" Value="Default"/>
</Style> </Style>
<!--Flyout Item-->
<Style TargetType="FlyoutItem"> <Style TargetType="FlyoutItem">
<Setter Property="Shell.BackgroundColor" Value="{DynamicResource Key=secondary-back-title-color}" /> <Setter Property="Shell.BackgroundColor" Value="{DynamicResource Key=secondary-back-title-color}" />
</Style> </Style>
<!--Navbar-->
<Style x:Key="Label-Navbar" TargetType="Label"> <Style x:Key="Label-Navbar" TargetType="Label">
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20"/>
<Setter Property="TextTransform" Value="Uppercase"/> <Setter Property="TextTransform" Value="Uppercase"/>
@ -90,4 +104,4 @@
<Setter Property="Grid.ColumnSpan" Value="2"/> <Setter Property="Grid.ColumnSpan" Value="2"/>
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

View file

@ -1,83 +1,92 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms" <ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.Themes.LastenradBayern"> x:Class="TINK.Themes.LastenradBayern">
<Color x:Key="primary-back-title-color">#009BDB</Color> <!--Main color-->
<Color x:Key="primary-back-title-color">#009BDB</Color>
<!--<Style TargetType="Button"> <!--Primary Button-->
<Setter Property="WidthRequest" Value="400" /> <!--<<Style TargetType="Button">
<Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="WidthRequest" Value="400" />
<Setter Property="BorderWidth" Value="1"/> <Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="BorderRadius" Value="10" /> <Setter Property="BorderWidth" Value="1"/>
<Setter Property="FontSize" Value="Medium"/> <Setter Property="BorderRadius" Value="10" />
<Setter Property="TextColor" Value="White"/> <Setter Property="FontSize" Value="Medium"/>
<Style.Triggers> <Setter Property="TextColor" Value="White"/>
<Trigger TargetType="Button" <Style.Triggers>
Property="IsEnabled" <Trigger TargetType="Button"
Value="True"> Property="IsEnabled"
<Setter Property="BorderColor" Value="{DynamicResource Key=primary-back-title-color}"/> Value="True">
<Setter Property="BackgroundColor" Value="{DynamicResource Key=primary-back-title-color}"/> <Setter Property="BorderColor" Value="{DynamicResource Key=primary-back-title-color}"/>
</Trigger> <Setter Property="BackgroundColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Trigger TargetType="Button" </Trigger>
Property="IsEnabled" <Trigger TargetType="Button"
Value="False"> Property="IsEnabled"
<Setter Property="BorderColor" Value="LightGray"/> Value="False">
<Setter Property="BackgroundColor" Value="LightGray"/> <Setter Property="BorderColor" Value="LightGray"/>
</Trigger> <Setter Property="BackgroundColor" Value="LightGray"/>
</Style.Triggers> </Trigger>
</Style> </Style.Triggers>
<Style x:Key="SecondaryButton" TargetType="Button"> </Style>-->
<Setter Property="WidthRequest" Value="400" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="BorderWidth" Value="1"/>
<Setter Property="BorderRadius" Value="10" />
<Setter Property="FontSize" Value="Medium"/>
<Setter Property="TextColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Style.Triggers>
<Trigger TargetType="Button"
Property="IsEnabled"
Value="True">
<Setter Property="BorderColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Setter Property="BackgroundColor" Value="White"/>
</Trigger>
<Trigger TargetType="Button"
Property="IsEnabled"
Value="False">
<Setter Property="BorderColor" Value="LightGray"/>
<Setter Property="BackgroundColor" Value="DimGray"/>
</Trigger>
</Style.Triggers>
</Style>
<!--Sedondary Button-->
<Style TargetType="Switch"> <!--<Style x:Key="SecondaryButton" TargetType="Button">
<Style.Triggers> <Setter Property="WidthRequest" Value="400" />
<Trigger TargetType="Switch" <Setter Property="HorizontalOptions" Value="Center" />
Property="IsToggled" <Setter Property="BorderWidth" Value="1"/>
Value="True"> <Setter Property="BorderRadius" Value="10" />
<Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/> <Setter Property="FontSize" Value="Medium"/>
</Trigger> <Setter Property="TextColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Trigger TargetType="Switch" <Style.Triggers>
Property="IsToggled" <Trigger TargetType="Button"
Value="False"> Property="IsEnabled"
<Setter Property="ThumbColor" Value="DimGray"/> Value="True">
</Trigger> <Setter Property="BorderColor" Value="{DynamicResource Key=primary-back-title-color}"/>
</Style.Triggers> <Setter Property="BackgroundColor" Value="White"/>
</Style> </Trigger>
<Style TargetType="Slider"> <Trigger TargetType="Button"
<Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/> Property="IsEnabled"
<Setter Property="Background" Value="LightGray"/> Value="False">
</Style> <Setter Property="BorderColor" Value="LightGray"/>
<Style TargetType="Label"> <Setter Property="BackgroundColor" Value="DimGray"/>
<Setter Property="FontSize" Value="Default"/> </Trigger>
</Style> </Style.Triggers>
</Style>--> </Style>-->
<!--Switch-->
<!--<Style TargetType="Switch">
<Style.Triggers>
<Trigger TargetType="Switch"
Property="IsToggled"
Value="True">
<Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/>
</Trigger>
<Trigger TargetType="Switch"
Property="IsToggled"
Value="False">
<Setter Property="ThumbColor" Value="DimGray"/>
</Trigger>
</Style.Triggers>
</Style>-->
<!--Slider-->
<!--<Style TargetType="Slider">
<Setter Property="ThumbColor" Value="{DynamicResource Key=primary-back-title-color}"/>
<Setter Property="Background" Value="LightGray"/>
</Style>-->
<!--Label-->
<!--<Style TargetType="Label">
<Setter Property="FontSize" Value="Default"/>
</Style>-->
<!--Flyout Item-->
<Style TargetType="FlyoutItem"> <Style TargetType="FlyoutItem">
<Setter Property="Shell.BackgroundColor" Value="{DynamicResource Key=primary-back-title-color}" /> <Setter Property="Shell.BackgroundColor" Value="{DynamicResource Key=primary-back-title-color}" />
</Style> </Style>
<!--Navbar-->
<Style x:Key="Label-Navbar" TargetType="Label"> <Style x:Key="Label-Navbar" TargetType="Label">
<Setter Property="FontSize" Value="20"/> <Setter Property="FontSize" Value="20"/>
<!--<Setter Property="TextTransform" Value="Uppercase"/>--> <!--<Setter Property="TextTransform" Value="Uppercase"/>-->
@ -92,4 +101,4 @@
<Setter Property="Grid.ColumnSpan" Value="2"/> <Setter Property="Grid.ColumnSpan" Value="2"/>
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

View file

@ -318,13 +318,15 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StopUpdatePeridically(); await ViewUpdateManager().StopUpdatePeridically();
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try 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) catch (Exception exception)
{ {
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
if (exception is OutOfReachException) if (exception is OutOfReachException)
{ {
@ -389,7 +391,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -69,8 +69,10 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StopUpdatePeridically(); await ViewUpdateManager().StopUpdatePeridically();
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try try
{ {
btLock = LockService[SelectedBike.LockInfo.Id];
SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected; SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].OpenAsync())?.GetLockingState() ?? LockingState.UnknownDisconnected;
} }
catch (Exception exception) catch (Exception exception)
@ -140,7 +142,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
@ -58,7 +58,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{ {
BikesViewModel.IsIdle = false; BikesViewModel.IsIdle = false;
// Ask whether to really book bike? // Ask whether to really reserve bike?
var alertResult = await ViewService.DisplayAlert( var alertResult = await ViewService.DisplayAlert(
string.Empty, string.Empty,
string.Format(AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes), string.Format(AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes),
@ -257,9 +257,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Unlock bike. // Unlock bike.
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try 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) catch (Exception exception)
{ {
@ -336,7 +338,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
@ -222,9 +222,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Unlock bike. // Unlock bike.
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try 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) catch (Exception exception)
{ {
@ -301,7 +303,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
@ -246,7 +246,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
} }
else else
{ {
Log.ForContext<BookedDisconnected>().Error("Lock can not be found. {Exception}", exception); Log.ForContext<ReservedDisconnected>().Error("Lock can not be found. {Exception}", exception);
string message; string message;
if (retryCount < 2) if (retryCount < 2)
@ -384,9 +384,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Unlock bike. // Unlock bike.
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try 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) catch (Exception exception)
{ {
@ -463,7 +465,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -65,9 +65,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StopUpdatePeridically(); await ViewUpdateManager().StopUpdatePeridically();
BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock;
ILockService btLock;
try 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) catch (Exception exception)
{ {
@ -136,7 +138,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try try
{ {
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync(); SelectedBike.LockInfo.BatteryPercentage = await btLock.GetBatteryPercentageAsync();
} }
catch (Exception exception) 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. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; 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(); IsConnected = IsConnectedDelegate();
try try

View file

@ -1,9 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model; using TINK.Model;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Request; using TINK.Repository.Request;
@ -258,7 +259,8 @@ namespace TestFramework.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryLevel) double batteryLevel,
IVersionInfo versionInfo)
=> null; => null;
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Request; using TINK.Repository.Request;
@ -59,7 +60,8 @@ namespace TestFramework.Repository
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryPercentage) double batteryPercentage,
IVersionInfo versionInfo)
=> throw new NotImplementedException(); => throw new NotImplementedException();
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TestFramework.Repository; using TestFramework.Repository;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository.Request; using TINK.Repository.Request;
@ -79,7 +80,8 @@ namespace TestFramework.Services.CopriApi.Connector
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryPercentage) double batteryPercentage,
IVersionInfo versionInfo)
=> throw new NotImplementedException(); => throw new NotImplementedException();
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using TINK.Repository.Exception; using TINK.Repository.Exception;
@ -185,7 +185,7 @@ namespace TestShareeLib.Repository.Request
{ {
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie"); var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That( 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")); 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"); var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That( 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")); 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"); var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That( 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")); 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"); var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That( 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")); 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"); var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That( 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")); 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] [Test]
public void TestDoReturnGeolocationIsNull() public void TestDoReturnGeolocationIsNull()
{ {

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository; using TINK.Repository;
@ -84,7 +85,8 @@ namespace TestTINKLib.Mocks.Connector
lock_state state, lock_state state,
Uri operatorUri, Uri operatorUri,
LocationDto geolocation, LocationDto geolocation,
double batteryPercentage) double batteryPercentage,
IVersionInfo versionInfo)
=> throw new NotImplementedException(); => throw new NotImplementedException();
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri) public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)