mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-21 21:46:27 +02:00
Code updated to 3.0.238
This commit is contained in:
parent
3302d80678
commit
9c6a1fa92b
257 changed files with 7763 additions and 2861 deletions
|
@ -21,13 +21,13 @@ namespace TINK.Model.Bike.BC
|
|||
/// <summary> Constructs a bike object.</summary>
|
||||
protected BikeInfo(
|
||||
IStateInfo stateInfo,
|
||||
int id,
|
||||
string id,
|
||||
bool? isDemo = DEFAULTVALUEISDEMO,
|
||||
IEnumerable<string> group = null,
|
||||
WheelType? wheelType = null,
|
||||
TypeOfBike? typeOfBike = null,
|
||||
string description = null,
|
||||
int? currentStationId = null,
|
||||
string currentStationId = null,
|
||||
Uri operatorUri = null,
|
||||
TariffDescription tariffDescription = null)
|
||||
{
|
||||
|
@ -63,8 +63,8 @@ namespace TINK.Model.Bike.BC
|
|||
/// <param name="tariffDescription">Hold tariff description of bike.</param>
|
||||
/// <param name="wheelType"></param>
|
||||
public BikeInfo(
|
||||
int id,
|
||||
int? currentStationId,
|
||||
string id,
|
||||
string currentStationId,
|
||||
Uri operatorUri = null,
|
||||
TariffDescription tariffDescription = null,
|
||||
bool? isDemo = DEFAULTVALUEISDEMO,
|
||||
|
@ -99,13 +99,13 @@ namespace TINK.Model.Bike.BC
|
|||
/// <param name="code">Booking code.</param>
|
||||
/// <param name="p_oDateTimeNowProvider">Date time provider to calculate reaining time.</param>
|
||||
public BikeInfo(
|
||||
int id,
|
||||
string id,
|
||||
bool? isDemo,
|
||||
IEnumerable<string> group,
|
||||
WheelType? wheelType,
|
||||
TypeOfBike? typeOfBike,
|
||||
string description,
|
||||
int? stationId,
|
||||
string stationId,
|
||||
Uri operatorUri,
|
||||
TariffDescription tariffDescription,
|
||||
DateTime requestedAt,
|
||||
|
@ -142,13 +142,13 @@ namespace TINK.Model.Bike.BC
|
|||
/// <param name="mailAddress">Mail address of user which booked bike.</param>
|
||||
/// <param name="code">Booking code.</param>
|
||||
public BikeInfo(
|
||||
int id,
|
||||
string id,
|
||||
bool? isDemo,
|
||||
IEnumerable<string> group,
|
||||
WheelType? wheelType,
|
||||
TypeOfBike? typeOfBike,
|
||||
string description,
|
||||
int? currentStationId,
|
||||
string currentStationId,
|
||||
Uri operatorUri,
|
||||
TariffDescription tariffDescription,
|
||||
DateTime bookedAt,
|
||||
|
@ -179,7 +179,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// <summary>
|
||||
/// Station a which bike is located, null otherwise.
|
||||
/// </summary>
|
||||
public int? CurrentStation { get; }
|
||||
public string CurrentStation { get; }
|
||||
|
||||
/// <summary> Holds description about the tarif. </summary>
|
||||
public TariffDescription TariffDescription { get; }
|
||||
|
@ -192,7 +192,7 @@ namespace TINK.Model.Bike.BC
|
|||
get { return m_oStateInfo; }
|
||||
}
|
||||
|
||||
public int Id => Bike.Id;
|
||||
public string Id => Bike.Id;
|
||||
|
||||
public WheelType? WheelType => Bike.WheelType;
|
||||
|
||||
|
@ -210,7 +210,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// </summary>
|
||||
public new string ToString()
|
||||
{
|
||||
return $"Id={Bike.Id}{(Bike.WheelType != null ? $", wheel(s)={Bike.WheelType}" : string.Empty)}{(Bike.TypeOfBike != null ? $"type={Bike.TypeOfBike}" : "")}, state={State}, location={(CurrentStation.HasValue ? $"Station {CurrentStation}" : "On the road")}, is demo={IsDemo}.";
|
||||
return $"Id={Bike.Id}{(Bike.WheelType != null ? $", wheel(s)={Bike.WheelType}" : string.Empty)}{(Bike.TypeOfBike != null ? $"type={Bike.TypeOfBike}" : "")}, state={State}, location={(!string.IsNullOrEmpty(CurrentStation)? $"Station {CurrentStation}" : "On the road")}, is demo={IsDemo}.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ namespace TINK.Model.Bike.BC
|
|||
/// <param name="tariffDescription">Hold tariff description of bike.</param>
|
||||
/// <param name="stateInfo">Bike state info.</param>
|
||||
protected BikeInfoMutable(
|
||||
int id,
|
||||
string id,
|
||||
bool isDemo = BikeInfo.DEFAULTVALUEISDEMO,
|
||||
IEnumerable<string> group = null,
|
||||
WheelType? wheelType = null,
|
||||
TypeOfBike? typeOfBike = null,
|
||||
string description = null,
|
||||
int? currentStationId = null,
|
||||
string currentStationId = null,
|
||||
Uri operatorUri = null,
|
||||
TariffDescription tariffDescription = null,
|
||||
Func<DateTime> dateTimeProvider = null,
|
||||
|
@ -71,7 +71,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// Station a which bike is located, null otherwise.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int? CurrentStation { get; }
|
||||
public string CurrentStation { get; }
|
||||
|
||||
/// <summary> Holds description about the tarif. </summary>
|
||||
[DataMember]
|
||||
|
@ -94,7 +94,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// <summary> Unused member. </summary>
|
||||
IStateInfoMutable IBikeInfoMutable.State => m_oStateInfo;
|
||||
|
||||
public int Id => m_oBike.Id;
|
||||
public string Id => m_oBike.Id;
|
||||
|
||||
public bool IsDemo { get; }
|
||||
|
||||
|
@ -118,7 +118,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// <returns></returns>
|
||||
public new string ToString()
|
||||
{
|
||||
return $"Id={Id}{(WheelType != null ? $", wheel(s)={WheelType}" : string.Empty)}{(TypeOfBike != null ? $", type={TypeOfBike}" : "")}, demo={IsDemo}, state={State.ToString()}, location={(CurrentStation.HasValue ? $"Station {CurrentStation}" : "On the road")}.";
|
||||
return $"Id={Id}{(WheelType != null ? $", wheel(s)={WheelType}" : string.Empty)}{(TypeOfBike != null ? $", type={TypeOfBike}" : "")}, demo={IsDemo}, state={State.ToString()}, location={(!string.IsNullOrEmpty(CurrentStation) ? $"Station {CurrentStation}" : "On the road")}.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// <summary>
|
||||
/// Holds the unique id of the bike;
|
||||
/// </summary>
|
||||
int Id { get; }
|
||||
string Id { get; }
|
||||
|
||||
/// <summary> True if bike is a demo bike. </summary>
|
||||
bool IsDemo { get; }
|
||||
|
@ -37,7 +37,7 @@ namespace TINK.Model.Bike.BC
|
|||
/// <summary>
|
||||
/// Station a which bike is located, null otherwise.
|
||||
/// </summary>
|
||||
int? CurrentStation { get; }
|
||||
string CurrentStation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Uri of the operator or null, in case of single operator setup.
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace TINK.Model.Bikes.Bike.BC
|
|||
/// <summary>
|
||||
/// Holds the unique id of the bike;
|
||||
/// </summary>
|
||||
int Id { get; }
|
||||
string Id { get; }
|
||||
|
||||
/// <summary> True if bike is a demo bike. </summary>
|
||||
bool IsDemo { get; }
|
||||
|
@ -35,7 +35,7 @@ namespace TINK.Model.Bikes.Bike.BC
|
|||
/// <summary>
|
||||
/// Station a which bike is located, null otherwise.
|
||||
/// </summary>
|
||||
int? CurrentStation { get; }
|
||||
string CurrentStation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the rent state of the bike.
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace TINK.Model.Bike
|
|||
/// <param name="p_iId">Unique id of bike.</param>
|
||||
/// <param name="p_strCurrentStationName">Name of station where bike is located, null if bike is on the road.</param>
|
||||
public Bike(
|
||||
int p_iId,
|
||||
string p_iId,
|
||||
WheelType? wheelType = null,
|
||||
TypeOfBike? typeOfBike = null,
|
||||
string description = null)
|
||||
|
@ -43,7 +43,7 @@ namespace TINK.Model.Bike
|
|||
/// <summary>
|
||||
/// Holds the unique id of the bike;
|
||||
/// </summary>
|
||||
public int Id { get; }
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the count of wheels.
|
||||
|
|
|
@ -18,10 +18,10 @@ namespace TINK.Model.Bike.BluetoothLock
|
|||
/// <param name="tariffDescription">Hold tariff description of bike.</param>
|
||||
/// <param name="wheelType">Trike, two wheels, mono, ....</param>
|
||||
public BikeInfo(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
int lockId,
|
||||
Guid lockGuid,
|
||||
int? currentStationId,
|
||||
string currentStationId,
|
||||
Uri operatorUri = null,
|
||||
TariffDescription tariffDescription = null,
|
||||
bool? isDemo = DEFAULTVALUEISDEMO,
|
||||
|
@ -58,7 +58,7 @@ namespace TINK.Model.Bike.BluetoothLock
|
|||
/// <param name="p_oDateTimeNowProvider">Date time provider to calculate reaining time.</param>
|
||||
/// <param name="wheelType"></param>
|
||||
public BikeInfo(
|
||||
int id,
|
||||
string id,
|
||||
int lockId,
|
||||
Guid lockGuid,
|
||||
byte[] userKey,
|
||||
|
@ -66,7 +66,7 @@ namespace TINK.Model.Bike.BluetoothLock
|
|||
byte[] seed,
|
||||
DateTime requestedAt,
|
||||
string mailAddress,
|
||||
int? currentStationId,
|
||||
string currentStationId,
|
||||
Uri operatorUri,
|
||||
TariffDescription tariffDescription,
|
||||
Func<DateTime> dateTimeProvider,
|
||||
|
@ -106,7 +106,7 @@ namespace TINK.Model.Bike.BluetoothLock
|
|||
/// <param name="tariffDescription">Hold tariff description of bike.</param>
|
||||
/// <param name="wheelType"></param>
|
||||
public BikeInfo(
|
||||
int id,
|
||||
string id,
|
||||
int lockId,
|
||||
Guid lockGuid,
|
||||
byte[] userKey,
|
||||
|
@ -114,7 +114,7 @@ namespace TINK.Model.Bike.BluetoothLock
|
|||
byte[] seed,
|
||||
DateTime bookedAt,
|
||||
string mailAddress,
|
||||
int? currentStationId,
|
||||
string currentStationId,
|
||||
Uri operatorUri,
|
||||
TariffDescription tariffDescription = null,
|
||||
bool? isDemo = DEFAULTVALUEISDEMO,
|
||||
|
|
|
@ -5,8 +5,9 @@ namespace TINK.Model.Bikes.Bike
|
|||
/// <summary>
|
||||
/// Holds tariff info for a single bike.
|
||||
/// </summary>
|
||||
#if USCSHARP9
|
||||
public record TariffDescription
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the tariff.
|
||||
/// </summary>
|
||||
|
@ -37,4 +38,38 @@ namespace TINK.Model.Bikes.Bike
|
|||
/// </summary>
|
||||
public double MaxFeeEuroPerDay { get; init; }
|
||||
}
|
||||
#else
|
||||
public class TariffDescription
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the tariff.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of the tariff.
|
||||
/// </summary>
|
||||
public int? Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Costs per hour in euro.
|
||||
/// </summary>
|
||||
public double FeeEuroPerHour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Costs of the abo per month.
|
||||
/// </summary>
|
||||
public double AboEuroPerMonth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Costs per hour in euro.
|
||||
/// </summary>
|
||||
public TimeSpan FreeTimePerSession { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Max. costs per day in euro.
|
||||
/// </summary>
|
||||
public double MaxFeeEuroPerDay { get; set; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,37 +11,37 @@ namespace TINK.Model.Bike
|
|||
public class BikeCollection : IBikeDictionary<BikeInfo>
|
||||
{
|
||||
/// <summary> Holds the bike dictionary object.</summary>
|
||||
private Dictionary<int, BikeInfo> BikeDictionary { get; }
|
||||
private Dictionary<string, BikeInfo> BikeDictionary { get; }
|
||||
|
||||
/// <summary>Constructs an empty bike info dictionary object.</summary>
|
||||
public BikeCollection()
|
||||
{
|
||||
BikeDictionary = new Dictionary<int, BikeInfo>();
|
||||
BikeDictionary = new Dictionary<string, BikeInfo>();
|
||||
}
|
||||
|
||||
/// <summary> Constructs a bike collection object.</summary>
|
||||
/// <param name="bikeDictionary"></param>
|
||||
public BikeCollection(Dictionary<int, BikeInfo> bikeDictionary)
|
||||
public BikeCollection(Dictionary<string, BikeInfo> bikeDictionary)
|
||||
{
|
||||
BikeDictionary = bikeDictionary ??
|
||||
throw new ArgumentNullException(nameof(bikeDictionary), "Can not construct BikeCollection object.");
|
||||
}
|
||||
|
||||
/// <summary> Gets a bike by its id.</summary>
|
||||
/// <param name="p_iId">Id of the bike to get.</param>
|
||||
/// <param name="id">Id of the bike to get.</param>
|
||||
/// <returns></returns>
|
||||
public BikeInfo GetById(int p_iId)
|
||||
public BikeInfo GetById(string id)
|
||||
{
|
||||
return BikeDictionary.FirstOrDefault(x => x.Key == p_iId).Value;
|
||||
return BikeDictionary.FirstOrDefault(x => x.Key == id).Value;
|
||||
}
|
||||
|
||||
/// <summary> Gets the count of bikes. </summary>
|
||||
public int Count => BikeDictionary.Count;
|
||||
|
||||
/// <summary> Gets if a bike with given id exists.</summary>
|
||||
/// <param name="p_iId">Id of bike.</param>
|
||||
/// <param name="id">Id of bike.</param>
|
||||
/// <returns>True if bike is contained, false otherwise.</returns>
|
||||
public bool ContainsKey(int p_iId) => BikeDictionary.Keys.Contains(p_iId);
|
||||
public bool ContainsKey(string id) => BikeDictionary.Keys.Contains(id);
|
||||
|
||||
/// <summary> Gets the enumerator. </summary>
|
||||
/// <returns>Enumerator object.</returns>
|
||||
|
|
|
@ -14,11 +14,11 @@ namespace TINK.Model
|
|||
/// <returns>BikeCollection holding bikes at given station or empty BikeCollection, if there are no bikes.</returns>
|
||||
public static BikeCollection GetAtStation(
|
||||
this BikeCollection bikesAtAnyStation,
|
||||
int? selectedStation)
|
||||
string selectedStation)
|
||||
{
|
||||
return new BikeCollection(bikesAtAnyStation?
|
||||
.Where(bike => selectedStation.HasValue && bike.CurrentStation == selectedStation.Value)
|
||||
.ToDictionary(x => x.Id) ?? new Dictionary<int, BikeInfo>());
|
||||
.Where(bike => !string.IsNullOrEmpty(selectedStation) && bike.CurrentStation == selectedStation)
|
||||
.ToDictionary(x => x.Id) ?? new Dictionary<string, BikeInfo>());
|
||||
}
|
||||
|
||||
/// <summary> Filters bikes by bike type. </summary>
|
||||
|
@ -28,7 +28,7 @@ namespace TINK.Model
|
|||
{
|
||||
return new BikeCollection(bcAndLockItBikes?
|
||||
.Where(bike => bike is Bike.BluetoothLock.BikeInfo)
|
||||
.ToDictionary(x => x.Id) ?? new Dictionary<int, BikeInfo>());
|
||||
.ToDictionary(x => x.Id) ?? new Dictionary<string, BikeInfo>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace TINK.Model.Bike
|
|||
// Update bike.
|
||||
GetById(bikeInfo.Id).State.Load(bikeInfo.State);
|
||||
|
||||
if (bikesToBeRemoved.Contains<int>(bikeInfo.Id))
|
||||
if (bikesToBeRemoved.Contains<string>(bikeInfo.Id))
|
||||
{
|
||||
// Remove list from obsolete list.
|
||||
bikesToBeRemoved.Remove(bikeInfo.Id);
|
||||
|
@ -86,20 +86,20 @@ namespace TINK.Model.Bike
|
|||
private set;
|
||||
}
|
||||
|
||||
public void SetSelectedBike(int p_intId)
|
||||
public void SetSelectedBike(string id)
|
||||
{
|
||||
SelectedBike = GetById(p_intId);
|
||||
SelectedBike = GetById(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a bike by its id.
|
||||
/// </summary>
|
||||
/// <param name="p_iId"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public BikeInfoMutable GetById(int p_iId)
|
||||
public BikeInfoMutable GetById(string id)
|
||||
{
|
||||
{
|
||||
return this.FirstOrDefault(bike => bike.Id == p_iId);
|
||||
return this.FirstOrDefault(bike => bike.Id == id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,18 +108,18 @@ namespace TINK.Model.Bike
|
|||
/// </summary>
|
||||
/// <param name="p_strKey">Key to check.</param>
|
||||
/// <returns>True if bike exists.</returns>
|
||||
public bool ContainsKey(int p_iId)
|
||||
public bool ContainsKey(string id)
|
||||
{
|
||||
return GetById(p_iId) != null;
|
||||
return GetById(id) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a bike by its id.
|
||||
/// </summary>
|
||||
/// <param name="p_iId">Id of bike to be removed.</param>
|
||||
public void RemoveById(int p_iId)
|
||||
/// <param name="id">Id of bike to be removed.</param>
|
||||
public void RemoveById(string id)
|
||||
{
|
||||
var l_oBike = GetById(p_iId);
|
||||
var l_oBike = GetById(id);
|
||||
if (l_oBike == null)
|
||||
{
|
||||
// Nothing to do if bike does not exists.
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace TINK.Model.Bike
|
|||
IEnumerable<BluetoothLock.LockInfo> locksInfo)
|
||||
{
|
||||
|
||||
var updatedBikesCollection = new Dictionary<int, BC.BikeInfo>();
|
||||
var updatedBikesCollection = new Dictionary<string, BC.BikeInfo>();
|
||||
|
||||
foreach (var bikeInfo in bikes)
|
||||
{
|
||||
|
|
|
@ -7,29 +7,29 @@ namespace TINK.Model.Bike
|
|||
/// <summary>
|
||||
/// Gets a bike by its id.
|
||||
/// </summary>
|
||||
/// <param name="p_iId"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
T GetById(int p_iId);
|
||||
T GetById(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Deteermines whether a bike by given key exists.
|
||||
/// </summary>
|
||||
/// <param name="p_strKey">Key to check.</param>
|
||||
/// <returns>True if bike exists.</returns>
|
||||
bool ContainsKey(int p_iId);
|
||||
bool ContainsKey(string id);
|
||||
}
|
||||
public interface IBikeDictionaryMutable<T> : IBikeDictionary<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes a bike by its id.
|
||||
/// </summary>
|
||||
/// <param name="p_iId">Id of bike to be removed.</param>
|
||||
void RemoveById(int p_iId);
|
||||
/// <param name="id">Id of bike to be removed.</param>
|
||||
void RemoveById(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new element to dictinary.
|
||||
/// </summary>
|
||||
/// <param name="p_oNewElement">New element to add.</param>
|
||||
void Add(T p_oNewElement);
|
||||
/// <param name="newElement">New element to add.</param>
|
||||
void Add(T newElement);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.User.Account;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -122,7 +123,8 @@ namespace TINK.Model.Connector
|
|||
|
||||
public async Task DoReturn(
|
||||
Bikes.Bike.BluetoothLock.IBikeInfoMutable bike,
|
||||
LocationDto location)
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected returning request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
|
@ -132,7 +134,11 @@ namespace TINK.Model.Connector
|
|||
/// Submits feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="userFeedback">Feedback to submit.</param>
|
||||
#if USCSHARP9
|
||||
public async Task DoSubmitFeedback(ICommand.IUserFeedback userFeedback, Uri opertorUri)
|
||||
#else
|
||||
public async Task DoSubmitFeedback(IUserFeedback userFeedback, Uri opertorUri)
|
||||
#endif
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected submit feedback request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.User.Account;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -30,7 +31,7 @@ namespace TINK.Model.Connector
|
|||
/// Logs user in.
|
||||
/// If log in succeeds either and session might be updated if it was no more valid (logged in by an different device).
|
||||
/// If log in fails (password modified) session cookie is set to empty.
|
||||
/// If communication fails an TINK.Model.Repository.Exception is thrown.
|
||||
/// If communication fails an TINK.Repository.Exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="p_oAccount">Account to use for login.</param>
|
||||
public Task<IAccount> DoLogin(string p_strMail, string p_strPassword, string p_strDeviceId)
|
||||
|
@ -242,12 +243,13 @@ namespace TINK.Model.Connector
|
|||
}
|
||||
|
||||
/// <summary> Request to return a bike.</summary>
|
||||
/// <param name="latitude">Latitude of the bike.</param>
|
||||
/// <param name="longitude">Longitude of the bike.</param>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <param name="locaton">Position of the bike.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
public async Task DoReturn(
|
||||
Bikes.Bike.BluetoothLock.IBikeInfoMutable bike,
|
||||
LocationDto location)
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
|
@ -257,7 +259,7 @@ namespace TINK.Model.Connector
|
|||
ReservationCancelReturnResponse l_oResponse;
|
||||
try
|
||||
{
|
||||
l_oResponse = (await CopriServer.DoReturn(bike.Id, location, bike.OperatorUri)).GetIsReturnBikeResponseOk(bike.Id);
|
||||
l_oResponse = (await CopriServer.DoReturn(bike.Id, location, smartDevice, bike.OperatorUri)).GetIsReturnBikeResponseOk(bike.Id);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
@ -272,8 +274,12 @@ namespace TINK.Model.Connector
|
|||
/// Submits feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="userFeedback">Feedback to submit.</param>
|
||||
#if USCSHARP9
|
||||
public async Task DoSubmitFeedback(ICommand.IUserFeedback userFeedback, Uri opertorUri)
|
||||
=> await CopriServer.DoSubmitFeedback(userFeedback.Message, userFeedback.IsBikeBroken, opertorUri);
|
||||
|
||||
=> await CopriServer.DoSubmitFeedback(userFeedback.BikeId, userFeedback.Message, userFeedback.IsBikeBroken, opertorUri);
|
||||
#else
|
||||
public async Task DoSubmitFeedback(IUserFeedback userFeedback, Uri opertorUri)
|
||||
=> await CopriServer.DoSubmitFeedback(userFeedback.BikeId, userFeedback.Message, userFeedback.IsBikeBroken, opertorUri);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Model.User.Account;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -44,9 +45,10 @@ namespace TINK.Model.Connector
|
|||
Task DoBook(Bikes.Bike.BluetoothLock.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Request to return a bike.</summary>
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
Task DoReturn(Bikes.Bike.BluetoothLock.IBikeInfoMutable bike, LocationDto geolocation = null);
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
Task DoReturn(Bikes.Bike.BluetoothLock.IBikeInfoMutable bike, LocationDto geolocation = null, ISmartDevice smartDevice = null);
|
||||
|
||||
/// <summary> True if connector has access to copri server, false if cached values are used. </summary>
|
||||
bool IsConnected { get; }
|
||||
|
@ -55,12 +57,15 @@ namespace TINK.Model.Connector
|
|||
string SessionCookie { get; }
|
||||
|
||||
Task DoSubmitFeedback(IUserFeedback userFeedback, Uri opertorUri);
|
||||
|
||||
#if USCSHARP9
|
||||
/// <summary>
|
||||
/// Feedback given by user when returning bike.
|
||||
/// </summary>
|
||||
public interface IUserFeedback
|
||||
{
|
||||
/// <summary> Id of the bike to which the feedback is related to.</summary>
|
||||
string BikeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds whether bike is broken or not.
|
||||
/// </summary>
|
||||
|
@ -74,12 +79,37 @@ namespace TINK.Model.Connector
|
|||
/// </summary>
|
||||
string Message { get; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Defines delegate to be raised whenever login state changes.</summary>
|
||||
/// <param name="p_oEventArgs">Holds session cookie and mail address if user logged in successfully.</param>
|
||||
public delegate void LoginStateChangedEventHandler(object p_oSender, LoginStateChangedEventArgs p_oEventArgs);
|
||||
|
||||
#if !USCSHARP9
|
||||
/// <summary>
|
||||
/// Feedback given by user when returning bike.
|
||||
/// </summary>
|
||||
public interface IUserFeedback
|
||||
{
|
||||
/// <summary> Id of the bike to which the feedback is related to.</summary>
|
||||
string BikeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds whether bike is broken or not.
|
||||
/// </summary>
|
||||
bool IsBikeBroken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds either
|
||||
/// - general feedback
|
||||
/// - error description of broken bike
|
||||
/// or both.
|
||||
/// </summary>
|
||||
string Message { get; }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary> Event arguments to notify about changes of logged in state.</summary>
|
||||
public class LoginStateChangedEventArgs : EventArgs
|
||||
{
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
#if USCSHARP9
|
||||
public record UserFeedbackDto : ICommand.IUserFeedback
|
||||
{
|
||||
public string BikeId { get; init; }
|
||||
public bool IsBikeBroken { get; init; }
|
||||
public string Message { get; init; }
|
||||
}
|
||||
#else
|
||||
#if USCSHARP9
|
||||
public class UserFeedbackDto : ICommand.IUserFeedback
|
||||
#else
|
||||
public class UserFeedbackDto : IUserFeedback
|
||||
#endif
|
||||
{
|
||||
public string BikeId { get; set; }
|
||||
|
||||
public bool IsBikeBroken { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace TINK.Model.Connector.Filter
|
||||
{
|
||||
public static class GroupFilterFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates filter object.
|
||||
/// </summary>
|
||||
/// <param name="group">if value consists
|
||||
/// - list of strings entries are used to filter (intersect) with or if value is
|
||||
/// - null or an empty list null filter is applied, i.e. filtering is off.</param>
|
||||
/// <returns>Filtering object.</returns>
|
||||
/// <remarks>
|
||||
/// Tread group values of null and empty lists as marker to turn filtering off to handle COPRI responses maximal flexible.
|
||||
/// </remarks>
|
||||
public static IGroupFilter Create(IEnumerable<string> group)
|
||||
{
|
||||
return group != null ? (IGroupFilter) new IntersectGroupFilter(group) : new NullGroupFilter();
|
||||
return group != null && group.Count() > 0
|
||||
? (IGroupFilter) new IntersectGroupFilter(group) :
|
||||
new NullGroupFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,29 +86,33 @@ namespace TINK.Model.Connector
|
|||
/// <returns></returns>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var result = await m_oInnerQuery.GetBikesAndStationsAsync();
|
||||
// Bikes and stations from COPRI or cache
|
||||
var providerBikesAndStations = await m_oInnerQuery.GetBikesAndStationsAsync();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
result.Source,
|
||||
new StationsAndBikesContainer(
|
||||
new StationDictionary(result.Response.StationsAll.CopriVersion, DoFilter(result.Response.StationsAll, Filter)),
|
||||
new BikeCollection(DoFilter(result.Response.Bikes, Filter))),
|
||||
result.Exception);
|
||||
// Do filtering.
|
||||
var filteredStationsDictionary = new StationDictionary(providerBikesAndStations.Response.StationsAll.CopriVersion, DoFilter(providerBikesAndStations.Response.StationsAll, Filter));
|
||||
var filteredBikesDictionary = new BikeCollection(DoFilter(providerBikesAndStations.Response.Bikes, Filter));
|
||||
var filteredBikesAndStations = new Result<StationsAndBikesContainer>(
|
||||
providerBikesAndStations.Source,
|
||||
new StationsAndBikesContainer(filteredStationsDictionary, filteredBikesDictionary),
|
||||
providerBikesAndStations.Exception); ;
|
||||
|
||||
return filteredBikesAndStations;
|
||||
}
|
||||
|
||||
/// <summary> Filter bikes by group. </summary>
|
||||
/// <param name="p_oBikes">Bikes to filter.</param>
|
||||
/// <param name="bikes">Bikes to filter.</param>
|
||||
/// <returns>Filtered bikes.</returns>
|
||||
private static Dictionary<int, BikeInfo> DoFilter(BikeCollection p_oBikes, IGroupFilter filter)
|
||||
private static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IGroupFilter filter)
|
||||
{
|
||||
return p_oBikes.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
|
||||
return bikes.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
|
||||
}
|
||||
|
||||
/// <summary> Filter stations by broup. </summary>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<int, Station.Station> DoFilter(StationDictionary p_oStations, IGroupFilter filter)
|
||||
private static Dictionary<string, IStation> DoFilter(StationDictionary stations, IGroupFilter filter)
|
||||
{
|
||||
return p_oStations.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary((x => x.Id));
|
||||
return stations.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,18 +90,18 @@ namespace TINK.Model.Connector
|
|||
}
|
||||
|
||||
/// <summary> Filter bikes by group. </summary>
|
||||
/// <param name="p_oBikes">Bikes to filter.</param>
|
||||
/// <param name="bikes">Bikes to filter.</param>
|
||||
/// <returns>Filtered bikes.</returns>
|
||||
public static Dictionary<int, BikeInfo> DoFilter(BikeCollection p_oBikes, IEnumerable<string> p_oFilter)
|
||||
public static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IEnumerable<string> filter)
|
||||
{
|
||||
return p_oBikes.Where(x => x.Group.Intersect(p_oFilter).Count() > 0).ToDictionary(x => x.Id);
|
||||
return bikes.Where(x => x.Group.Intersect(filter).Count() > 0).ToDictionary(x => x.Id);
|
||||
}
|
||||
|
||||
/// <summary> Filter stations by broup. </summary>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<int, Station.Station> DoFilter(StationDictionary p_oStations, IEnumerable<string> p_oFilter)
|
||||
public static Dictionary<string, IStation> DoFilter(StationDictionary stations, IEnumerable<string> p_oFilter)
|
||||
{
|
||||
return p_oStations.Where(x => x.Group.Intersect(p_oFilter).Count() > 0).ToDictionary((x => x.Id));
|
||||
return stations.Where(x => x.Group.Intersect(p_oFilter).Count() > 0).ToDictionary(x => x.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
|
@ -70,7 +70,7 @@ namespace TINK.Model.Connector
|
|||
Log.ForContext<CachedQuery>().Error("Unexpected call to get be bikes occpied detected. No user is logged in.");
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<int, BikeInfo>())),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<string, BikeInfo>())),
|
||||
new System.Exception("Abfrage der reservierten/ gebuchten Räder nicht möglich. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using MonkeyCache.FileStore;
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -31,73 +30,74 @@ namespace TINK.Model.Connector
|
|||
/// <summary> Gets all stations including postions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var resultStations = await server.GetStations();
|
||||
var stationsResponse = await server.GetStations();
|
||||
|
||||
if (resultStations.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| resultStations.Exception != null)
|
||||
if (stationsResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| stationsResponse.Exception != null)
|
||||
{
|
||||
// Stations were read from cache ==> get bikes availbalbe and occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
stationsResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
stationsResponse.Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
(await server.GetBikesAvailable(true)).Response,
|
||||
(await server.GetBikesOccupied(true)).Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
resultStations.Exception);
|
||||
stationsResponse.Exception);
|
||||
}
|
||||
|
||||
var l_oBikesAvailableResponse = await server.GetBikesAvailable();
|
||||
if (l_oBikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesAvailableResponse.Exception != null)
|
||||
var bikesAvailableResponse = await server.GetBikesAvailable();
|
||||
if (bikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes avilable were read from cache ==> get bikes occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
l_oBikesAvailableResponse.Source,
|
||||
bikesAvailableResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(l_oBikesAvailableResponse.Response,
|
||||
UpdaterJSON.GetBikesAll(bikesAvailableResponse.Response,
|
||||
(await server.GetBikesOccupied(true)).Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
l_oBikesAvailableResponse.Exception);
|
||||
bikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
var l_oBikesOccupiedResponse = await server.GetBikesOccupied();
|
||||
if (l_oBikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesOccupiedResponse.Exception != null)
|
||||
var bikesOccupiedResponse = await server.GetBikesOccupied();
|
||||
if (bikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
l_oBikesOccupiedResponse.Source,
|
||||
bikesOccupiedResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
(await server.GetBikesAvailable(true)).Response,
|
||||
l_oBikesOccupiedResponse.Response,
|
||||
bikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
l_oBikesOccupiedResponse.Exception);
|
||||
bikesOccupiedResponse.Exception);
|
||||
}
|
||||
|
||||
// Both types bikes could read from copri => update cache
|
||||
server.AddToCache(resultStations);
|
||||
server.AddToCache(l_oBikesAvailableResponse);
|
||||
server.AddToCache(l_oBikesOccupiedResponse);
|
||||
server.AddToCache(stationsResponse);
|
||||
server.AddToCache(bikesAvailableResponse);
|
||||
server.AddToCache(bikesOccupiedResponse);
|
||||
|
||||
var exceptions = new[] { resultStations?.Exception, l_oBikesAvailableResponse?.Exception, l_oBikesOccupiedResponse?.Exception }.Where(x => x != null).ToArray();
|
||||
var exceptions = new[] { stationsResponse?.Exception, bikesAvailableResponse?.Exception, bikesOccupiedResponse?.Exception }.Where(x => x != null).ToArray();
|
||||
|
||||
var stationsMutable = stationsResponse.Response.GetStationsAllMutable();
|
||||
var bikesMutable = UpdaterJSON.GetBikesAll(
|
||||
bikesAvailableResponse.Response,
|
||||
bikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
l_oBikesAvailableResponse.Response,
|
||||
l_oBikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
stationsResponse.Source,
|
||||
new StationsAndBikesContainer(stationsMutable, bikesMutable),
|
||||
exceptions.Length > 0 ? new AggregateException(exceptions) : null);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
|
@ -44,7 +44,7 @@ namespace TINK.Model.Connector
|
|||
Log.ForContext<Query>().Error("Unexpected call to get be bikes occpied detected. No user is logged in.");
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<int, BikeInfo>())),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<string, BikeInfo>())),
|
||||
new System.Exception("Abfrage der reservierten/ gebuchten Räder fehlgeschlagen. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
|
|
@ -5,8 +5,8 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using TINK.Model.State;
|
||||
|
||||
|
@ -51,14 +51,16 @@ namespace TINK.Model.Connector
|
|||
/// <summary> Gets the position from StationInfo object. </summary>
|
||||
/// <param name="p_oAuthorizationResponse">Object to get information from.</param>
|
||||
/// <returns>Position information.</returns>
|
||||
public static IEnumerable<string> GetGroup(this string p_oGroup)
|
||||
public static IEnumerable<string> GetGroup(this string[] group)
|
||||
{
|
||||
if (string.IsNullOrEmpty(p_oGroup))
|
||||
if (group == null || group.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("Can not get goup form string. Group text can not be null.");
|
||||
// If not logged in stations groups are empty form COPRI version v4.1.
|
||||
Log.Debug("Can not get goup form string. Group text can not be null.");
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return new HashSet<string>(p_oGroup.Split(',')).ToList();
|
||||
return new HashSet<string>(group).ToList();
|
||||
}
|
||||
|
||||
/// <summary> Gets the position from StationInfo object. </summary>
|
||||
|
@ -78,9 +80,9 @@ namespace TINK.Model.Connector
|
|||
{
|
||||
return p_oStationInfo.station_group.GetGroup();
|
||||
}
|
||||
catch (System.Exception l_oException)
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
throw new System.Exception($"Can not get group of stations from text \"{p_oStationInfo.station_group}\".", l_oException);
|
||||
throw new Exception($"Can not get group of stations from text \"{p_oStationInfo.station_group}\".", l_oException);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,24 +312,19 @@ namespace TINK.Model.Connector
|
|||
/// </summary>
|
||||
/// <param name="p_strGps">Text to extract positon from.</param>
|
||||
/// <returns>Position object.</returns>
|
||||
public static Station.Position GetPosition(string p_strGps)
|
||||
public static Station.Position GetPosition(GpsInfo gps)
|
||||
{
|
||||
if (p_strGps == null)
|
||||
if (gps == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var l_oPosition = p_strGps.Split(',');
|
||||
|
||||
if (l_oPosition.Length != 2)
|
||||
return null;
|
||||
|
||||
double l_oLatitude;
|
||||
if (!double.TryParse(l_oPosition[0], NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLatitude))
|
||||
if (!double.TryParse(gps.latitude, NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLatitude))
|
||||
return null;
|
||||
|
||||
double l_oLongitude;
|
||||
if (!double.TryParse(l_oPosition[1], NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLongitude))
|
||||
if (!double.TryParse(gps.longitude, NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLongitude))
|
||||
return null;
|
||||
|
||||
return new Station.Position(l_oLatitude, l_oLongitude);
|
||||
|
@ -354,5 +351,15 @@ namespace TINK.Model.Connector
|
|||
? new Uri($"{bikeInfo.uri_operator}/{CopriServerUriList.REST_RESOURCE_ROOT}")
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary> Gets the copriversion from.</summary>
|
||||
/// <param name="response">Response to get version info from.</param>
|
||||
/// <returns>COPRI version</returns>
|
||||
public static Version GetCopriVersion(this CopriVersion response)
|
||||
=> response!= null
|
||||
&& !string.IsNullOrEmpty(response.copri_version)
|
||||
&& Version.TryParse(response.copri_version, out Version copriVersion)
|
||||
? copriVersion
|
||||
: throw new InvalidResponseException($"Can not get version info from copri response {response?.copri_version}.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
using System;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Station;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.User.Account;
|
||||
using System.Collections.Generic;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using Serilog;
|
||||
|
||||
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||
|
@ -190,8 +190,8 @@ namespace TINK.Model.Connector
|
|||
string p_strMail,
|
||||
Func<DateTime> p_oDateTimeProvider)
|
||||
{
|
||||
var l_oBikesDictionary = new Dictionary<int, BikeInfo>();
|
||||
var l_oDuplicates = new Dictionary<int, BikeInfo>();
|
||||
var l_oBikesDictionary = new Dictionary<string, BikeInfo>();
|
||||
var l_oDuplicates = new Dictionary<string, BikeInfo>();
|
||||
|
||||
// Get bikes from Copri/ file/ memory, ....
|
||||
if (p_oBikesAvailableResponse != null
|
||||
|
@ -295,7 +295,7 @@ namespace TINK.Model.Connector
|
|||
return null;
|
||||
}
|
||||
|
||||
if (bikeInfo.station == null)
|
||||
if (string.IsNullOrEmpty(bikeInfo.station))
|
||||
{
|
||||
// Bike available must always have a station id because bikes can only be returned at a station.
|
||||
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. No station info set.");
|
||||
|
@ -485,7 +485,11 @@ namespace TINK.Model.Connector
|
|||
return new Bikes.Bike.TariffDescription
|
||||
{
|
||||
Name = tariffDesciption?.name,
|
||||
#if USCSHARP9
|
||||
Number = int.TryParse(tariffDesciption?.number, out int number) ? number : null,
|
||||
#else
|
||||
Number = int.TryParse(tariffDesciption?.number, out int number) ? number : (int?) null,
|
||||
#endif
|
||||
FreeTimePerSession = double.TryParse(tariffDesciption?.free_hours, NumberStyles.Any, CultureInfo.InvariantCulture, out double freeHours) ? TimeSpan.FromHours(freeHours) : TimeSpan.Zero,
|
||||
FeeEuroPerHour = double.TryParse(tariffDesciption?.eur_per_hour, NumberStyles.Any, CultureInfo.InvariantCulture, out double euroPerHour) ? euroPerHour : double.NaN,
|
||||
AboEuroPerMonth = double.TryParse(tariffDesciption?.abo_eur_per_month, NumberStyles.Any, CultureInfo.InvariantCulture, out double aboEuroPerMonth) ? aboEuroPerMonth : double.NaN,
|
||||
|
|
21
TINKLib/Model/Device/ISmartDevice.cs
Normal file
21
TINKLib/Model/Device/ISmartDevice.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
namespace TINK.Model.Device
|
||||
{
|
||||
public interface ISmartDevice
|
||||
{
|
||||
/// <summary> Gets unitque device identifier. </summary>
|
||||
/// <returns>Gets the identifies specifying device.</returns>
|
||||
string Identifier { get; }
|
||||
|
||||
/// <summary> Manufacturer (Samsung). </summary>
|
||||
string Manufacturer { get; }
|
||||
|
||||
/// <summary> Device Model (SMG-950U, iPhone10,6). </summary>
|
||||
string Model { get; }
|
||||
|
||||
/// <summary> Platform (Android). </summary>
|
||||
string PlatformText { get; }
|
||||
|
||||
/// <summary> Operating System Version Number (7.0) as text</summary>
|
||||
string VersionText { get; }
|
||||
}
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
using Plugin.Permissions.Abstractions;
|
||||
using Serilog.Events;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Settings;
|
||||
using TINK.ViewModel.Map;
|
||||
using TINK.ViewModel.Settings;
|
||||
using TINK.Services;
|
||||
using TINK.Model.Station;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TINK.Model
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ namespace TINK.Model
|
|||
IFilteredConnector GetConnector(bool isConnected);
|
||||
|
||||
/// <summary> Name of the station which is selected. </summary>
|
||||
int? SelectedStation { get; set; }
|
||||
IStation SelectedStation { get; set; }
|
||||
|
||||
/// <summary>Polling periode.</summary>
|
||||
PollingParameters Polling { get; set; }
|
||||
|
@ -67,6 +67,10 @@ namespace TINK.Model
|
|||
/// <summary> Gets the minimum logging level. </summary>
|
||||
LogEventLevel MinimumLogEventLevel { get; set; }
|
||||
|
||||
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
|
||||
bool IsReportLevelVerbose { get; set; }
|
||||
|
||||
|
||||
/// <summary> Updates logging level. </summary>
|
||||
/// <param name="p_oNewLevel">New level to set.</param>
|
||||
void UpdateLoggingLevel(LogEventLevel p_oNewLevel);
|
||||
|
@ -77,22 +81,19 @@ namespace TINK.Model
|
|||
/// <summary> Holds the different lock service implementations.</summary>
|
||||
LocksServicesContainerMutable LocksServices { get; }
|
||||
|
||||
/// <summary> Holds the different geo location service implementations.</summary>
|
||||
ServicesContainerMutable<IGeolocation> GeolocationServices { get; }
|
||||
|
||||
/// <summary> Holds available app themes.</summary>
|
||||
ServicesContainerMutable<object> Themes { get; }
|
||||
|
||||
/// <summary> Reference of object which provides device information. </summary>
|
||||
IDevice Device { get; }
|
||||
|
||||
/// <summary> Os permission.</summary>
|
||||
IPermissions Permissions { get; }
|
||||
ISmartDevice SmartDevice { get; }
|
||||
|
||||
/// <summary> Holds the folder where settings files are stored. </summary>
|
||||
string SettingsFileFolder { get; }
|
||||
|
||||
/// <summary> Holds the external path. </summary>
|
||||
string ExternalFolder { get; }
|
||||
|
||||
/// <summary> Holds the stations availalbe. </summary>
|
||||
IEnumerable<IStation> Stations {get; set;}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
|
||||
namespace TINK.Model.Logging
|
||||
{
|
||||
|
|
|
@ -18,61 +18,61 @@ namespace TINK.Model.Logging
|
|||
public static class LoggerConfigurationHelper
|
||||
{
|
||||
/// <summary> Holds the log file name. </summary>
|
||||
private static ILoggingDirectoryManager m_oDirectoryManager = new EmptyDirectoryLoggingManger();
|
||||
private static ILoggingDirectoryManager DirectoryManager { get; set; } = new EmptyDirectoryLoggingManger();
|
||||
|
||||
/// <summary> Sets up logging to file.</summary>
|
||||
/// <param name="p_oLoggerConfiguration">Object to set up logging with.</param>
|
||||
/// <param name="loggerConfiguration">Object to set up logging with.</param>
|
||||
/// <param name="p_oDevice">Object to get file informaton from.</param>
|
||||
/// <param name="p_oRollingInterval">Specifies rolling type.</param>
|
||||
/// <param name="p_iRetainedFilesCountLimit">Count of file being retained.</param>
|
||||
/// <param name="rollingInterval">Specifies rolling type.</param>
|
||||
/// <param name="retainedFilesCountLimit">Count of file being retained.</param>
|
||||
/// <returns>Logger object.</returns>
|
||||
public static LoggerConfiguration File(
|
||||
this LoggerSinkConfiguration p_oLoggerConfiguration,
|
||||
string p_strLogFileFolder,
|
||||
RollingInterval p_oRollingInterval = RollingInterval.Session,
|
||||
int p_iRetainedFilesCountLimit = 10)
|
||||
this LoggerSinkConfiguration loggerConfiguration,
|
||||
string logFileFolder,
|
||||
RollingInterval rollingInterval = RollingInterval.Session,
|
||||
int retainedFilesCountLimit = 10)
|
||||
{
|
||||
if (m_oDirectoryManager is EmptyDirectoryLoggingManger)
|
||||
if (DirectoryManager is EmptyDirectoryLoggingManger)
|
||||
{
|
||||
// Roll file only once per app session.
|
||||
try
|
||||
{
|
||||
m_oDirectoryManager = new LoggingDirectoryManager(
|
||||
DirectoryManager = new LoggingDirectoryManager(
|
||||
Directory.GetFiles,
|
||||
Directory.Exists,
|
||||
(path) => Directory.CreateDirectory(path),
|
||||
System.IO.File.Delete,
|
||||
p_strLogFileFolder,
|
||||
logFileFolder,
|
||||
Path.DirectorySeparatorChar,
|
||||
p_iRetainedFilesCountLimit);
|
||||
retainedFilesCountLimit);
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
Log.Error("Log directory manager could not be instanciated successfully. {@l_oException}", l_oException);
|
||||
m_oDirectoryManager = new EmptyDirectoryLoggingManger();
|
||||
DirectoryManager = new EmptyDirectoryLoggingManger();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
m_oDirectoryManager.DeleteObsoleteLogs();
|
||||
DirectoryManager.DeleteObsoleteLogs();
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
Log.Error("Not all obsolte log files could be deleted successfully. {@l_oException}", l_oException);
|
||||
}
|
||||
|
||||
if (p_oLoggerConfiguration == null)
|
||||
if (loggerConfiguration == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return p_oLoggerConfiguration.File(
|
||||
return loggerConfiguration.File(
|
||||
new JsonFormatter(),
|
||||
m_oDirectoryManager.LogFileName,
|
||||
DirectoryManager.LogFileName,
|
||||
/*shared: true, // Leads to exception if activated.*/
|
||||
rollingInterval: Serilog.RollingInterval.Infinite,
|
||||
retainedFileCountLimit: p_iRetainedFilesCountLimit);
|
||||
retainedFileCountLimit: retainedFilesCountLimit);
|
||||
}
|
||||
|
||||
/// <summary> Gets all log files in logging directory. </summary>
|
||||
|
@ -82,7 +82,7 @@ namespace TINK.Model.Logging
|
|||
{
|
||||
try
|
||||
{
|
||||
return m_oDirectoryManager.GetLogFiles();
|
||||
return DirectoryManager.GetLogFiles();
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ namespace TINK.Model.Logging
|
|||
public static string GetLogFilePath(
|
||||
this ILogger p_oLogger)
|
||||
{
|
||||
return m_oDirectoryManager.LogFilePath;
|
||||
return DirectoryManager.LogFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace TINK.Model.Logging
|
|||
|
||||
if (string.IsNullOrEmpty(LogFileTitle))
|
||||
{
|
||||
LogFileTitle = $"{ DateTime.Now:yyyy_MM_dd_HH_mm_ss}.jsnl";
|
||||
LogFileTitle = $"{DateTime.Now:yyyy_MM_dd_HH_mm_ss}.jsnl";
|
||||
}
|
||||
|
||||
// Create directory if direcotry does not exist.
|
||||
|
@ -74,7 +74,6 @@ namespace TINK.Model.Logging
|
|||
|
||||
throw new FileOperationException($"Logging directory {LogFilePath} could not be created successfully.", l_oException);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace TINK.Model.Settings
|
|||
/// <summary> Key of the logging level entry. </summary>
|
||||
public const string MINLOGGINGLEVELKEY = "MinimumLoggingLevel";
|
||||
|
||||
/// <summary> Key of the logging level entry. </summary>
|
||||
public const string ISREPORTLEVELVERBOSEKEY = "IsReportLevelVerbose";
|
||||
|
||||
/// <summary> Key of the center to ... entry. </summary>
|
||||
public const string CENTERMAPTOCURRENTLOCATION = "CenterMapToCurrentLocation";
|
||||
|
||||
|
@ -273,6 +276,16 @@ namespace TINK.Model.Settings
|
|||
return (LogEventLevel)int.Parse(JsonConvert.DeserializeObject<string>(l_strLevel));
|
||||
}
|
||||
|
||||
/// <summary> Gets a value indicating whether report level is verbose or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static bool? GetIsReportLevelVerbose(Dictionary<string, string> settingsJSON) => GetNullableEntry<bool>(ISREPORTLEVELVERBOSEKEY, settingsJSON);
|
||||
|
||||
/// <summary> Sets a value indicating whether report level is verbose or not.</summary>
|
||||
/// <param name="p_oSettingsJSON">Dictionary to get value from.</param>
|
||||
public static Dictionary<string, string> SetIsReportLevelVerbose(this IDictionary<string, string> targetDictionary, bool isReportLevelVerbose)
|
||||
=> SetEntry(isReportLevelVerbose, ISREPORTLEVELVERBOSEKEY, targetDictionary);
|
||||
|
||||
|
||||
/// <summary> Sets the logging level.</summary>
|
||||
/// <param name="p_oSettingsJSON">Dictionary to get logging level from.</param>
|
||||
public static Dictionary<string, string> SetMinimumLoggingLevel(this IDictionary<string, string> p_oTargetDictionary, LogEventLevel p_oLevel)
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace TINK.Model.Settings
|
|||
{
|
||||
public const LogEventLevel DEFAULTLOGGINLEVEL = LogEventLevel.Error;
|
||||
|
||||
public const bool DEFAULTREPOTLEVEL = false;
|
||||
|
||||
// Default value of the expires after entry. Controls the expiration time of the cache values.
|
||||
private TimeSpan DEFAULTEXPIRESAFTER = TimeSpan.FromSeconds(1);
|
||||
|
||||
|
@ -24,6 +26,7 @@ namespace TINK.Model.Settings
|
|||
/// <param name="activeUri"></param>
|
||||
/// <param name="pollingParameters"></param>
|
||||
/// <param name="minimumLogEventLevel">Minimum logging level to be applied.</param>
|
||||
/// <param name="isReportLevelVerbose">True if logging level is verbose.</param>
|
||||
/// <param name="expiresAfter">Holds the expires after value.</param>
|
||||
/// <param name="activeLockService">Gets the name of the lock service to use.</param>
|
||||
/// <param name="connectTimeout">Timeout to apply when connecting to bluetooth lock</param>
|
||||
|
@ -34,6 +37,7 @@ namespace TINK.Model.Settings
|
|||
Uri activeUri = null,
|
||||
PollingParameters pollingParameters = null,
|
||||
LogEventLevel? minimumLogEventLevel = null,
|
||||
bool? isReportLevelVerbose = null,
|
||||
TimeSpan? expiresAfter = null,
|
||||
string activeLockService = null,
|
||||
TimeSpan? connectTimeout = null,
|
||||
|
@ -48,6 +52,7 @@ namespace TINK.Model.Settings
|
|||
ActiveUri = GetActiveUri(activeUri);
|
||||
PollingParameters = pollingParameters ?? PollingParameters.Default;
|
||||
MinimumLogEventLevel = minimumLogEventLevel ?? DEFAULTLOGGINLEVEL;
|
||||
IsReportLevelVerbose = isReportLevelVerbose ?? DEFAULTREPOTLEVEL;
|
||||
ExpiresAfter = expiresAfter ?? DEFAULTEXPIRESAFTER;
|
||||
ActiveLockService = activeLockService ?? LocksServicesContainerMutable.DefaultLocksservice;
|
||||
ConnectTimeout = connectTimeout ?? new TimeSpan(0, 0, TimeOutProvider.DEFAULT_BLUETOOTHCONNECT_TIMEOUTSECONDS); // Try one sec. to connect.
|
||||
|
@ -93,6 +98,9 @@ namespace TINK.Model.Settings
|
|||
|
||||
public string ActiveTheme { get; }
|
||||
|
||||
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
|
||||
public bool IsReportLevelVerbose { get; }
|
||||
|
||||
public static Uri GetActiveUri(Uri activeUri) => activeUri ?? Services.CopriApi.ServerUris.CopriServerUriList.DefaultActiveUri;
|
||||
|
||||
public static bool GetCenterMapToCurrentLocation(Uri activeUri)
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace TINK.Model.Station
|
|||
public interface IStation
|
||||
{
|
||||
/// <summary> Holds the unique id of the station.c</summary>
|
||||
int Id { get; }
|
||||
string Id { get; }
|
||||
|
||||
/// <summary> Holds the group to which the station belongs.</summary>
|
||||
IEnumerable<string> Group { get; }
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace TINK.Model.Station
|
|||
public class NullStation : IStation
|
||||
{
|
||||
/// <summary> Holds the unique id of the station.c</summary>
|
||||
public int Id => -1;
|
||||
public string Id => null;
|
||||
|
||||
/// <summary> Holds the group to which the station belongs.</summary>
|
||||
public IEnumerable<string> Group => new List<string>();
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace TINK.Model.Station
|
|||
/// <param name="p_oPosition">GPS- position of the station.</param>
|
||||
/// <param name="p_strStationName">Name of the station.</param>
|
||||
public Station(
|
||||
int p_iId,
|
||||
string p_iId,
|
||||
IEnumerable<string> p_oGroup,
|
||||
Position p_oPosition,
|
||||
string p_strStationName = "")
|
||||
|
@ -24,7 +24,7 @@ namespace TINK.Model.Station
|
|||
}
|
||||
|
||||
/// <summary> Holds the unique id of the station.c</summary>
|
||||
public int Id { get; }
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary> Holds the group to which the station belongs.</summary>
|
||||
public IEnumerable<string> Group { get; }
|
||||
|
|
|
@ -4,10 +4,10 @@ using System.Collections.Generic;
|
|||
|
||||
namespace TINK.Model.Station
|
||||
{
|
||||
public class StationDictionary : IEnumerable<Station>
|
||||
public class StationDictionary : IEnumerable<IStation>
|
||||
{
|
||||
/// <summary> Holds the list of stations. </summary>
|
||||
private readonly IDictionary<int, Station> m_oStationDictionary;
|
||||
private readonly IDictionary<string, IStation> m_oStationDictionary;
|
||||
|
||||
/// <summary> Count of stations. </summary>
|
||||
public int Count { get { return m_oStationDictionary.Count; } }
|
||||
|
@ -16,16 +16,16 @@ namespace TINK.Model.Station
|
|||
|
||||
/// <summary> Constructs a station dictionary object. </summary>
|
||||
/// <param name="p_oVersion">Version of copri- service.</param>
|
||||
public StationDictionary(Version p_oVersion = null, IDictionary<int, Station> p_oStations = null)
|
||||
public StationDictionary(Version p_oVersion = null, IDictionary<string, IStation> p_oStations = null)
|
||||
{
|
||||
m_oStationDictionary = p_oStations ?? new Dictionary<int, Station>();
|
||||
m_oStationDictionary = p_oStations ?? new Dictionary<string, IStation>();
|
||||
|
||||
CopriVersion = p_oVersion != null
|
||||
? new Version(p_oVersion.Major, p_oVersion.Minor, p_oVersion.Revision, p_oVersion.Build)
|
||||
: new Version(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public IEnumerator<Station> GetEnumerator()
|
||||
public IEnumerator<IStation> GetEnumerator()
|
||||
{
|
||||
return m_oStationDictionary.Values.GetEnumerator();
|
||||
}
|
||||
|
@ -33,41 +33,41 @@ namespace TINK.Model.Station
|
|||
/// <summary>
|
||||
/// Deteermines whether a station by given key exists.
|
||||
/// </summary>
|
||||
/// <param name="p_strKey">Key to check.</param>
|
||||
/// <param name="key">Key to check.</param>
|
||||
/// <returns>True if station exists.</returns>
|
||||
public bool ContainsKey(int p_strKey)
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return m_oStationDictionary.ContainsKey(p_strKey);
|
||||
return m_oStationDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a station by station id.
|
||||
/// </summary>
|
||||
/// <param name="p_iId"></param>
|
||||
public void RemoveById(int p_iId)
|
||||
/// <param name="id"></param>
|
||||
public void RemoveById(string id)
|
||||
{
|
||||
if (!m_oStationDictionary.ContainsKey(p_iId))
|
||||
if (!m_oStationDictionary.ContainsKey(id))
|
||||
{
|
||||
// Nothing to do if there is no station with given name.
|
||||
return;
|
||||
}
|
||||
|
||||
m_oStationDictionary.Remove(p_iId);
|
||||
m_oStationDictionary.Remove(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a station by station name.
|
||||
/// </summary>
|
||||
/// <param name="p_iId"></param>
|
||||
public Station GetById(int p_iId)
|
||||
/// <param name="id"></param>
|
||||
public IStation GetById(string id)
|
||||
{
|
||||
if (!m_oStationDictionary.ContainsKey(p_iId))
|
||||
if (!m_oStationDictionary.ContainsKey(id))
|
||||
{
|
||||
// Nothing to do if there is no station with given name.
|
||||
return null;
|
||||
}
|
||||
|
||||
return m_oStationDictionary[p_iId];
|
||||
return m_oStationDictionary[id];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -22,6 +22,7 @@ using TINK.ViewModel.Settings;
|
|||
using TINK.Services;
|
||||
using TINK.Services.BluetoothLock.BLE;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Model.Station;
|
||||
|
||||
namespace TINK.Model
|
||||
{
|
||||
|
@ -34,7 +35,7 @@ namespace TINK.Model
|
|||
/// <returns>True if setting credentials succeeded.</returns>
|
||||
public delegate bool SetCredentialsDelegate(string p_strMailAddress, string p_strPassword);
|
||||
|
||||
/// <summary>Returns the id of the app to be identified by copri.</summary>
|
||||
/// <summary>Returns the id of the app (sharee.bike) to be identified by copri.</summary>
|
||||
public static string MerchantId => "oiF2kahH";
|
||||
|
||||
/// <summary>
|
||||
|
@ -67,6 +68,9 @@ namespace TINK.Model
|
|||
/// <summary> Gets the minimum logging level. </summary>
|
||||
public LogEventLevel MinimumLogEventLevel { get; set; }
|
||||
|
||||
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
|
||||
public bool IsReportLevelVerbose { get; set; }
|
||||
|
||||
/// <summary> Holds the uri which is applied after restart. </summary>
|
||||
public Uri NextActiveUri { get; set; }
|
||||
|
||||
|
@ -81,6 +85,7 @@ namespace TINK.Model
|
|||
.SetGroupFilterSettings(FilterGroupSetting)
|
||||
.SetAppVersion(AppVersion)
|
||||
.SetMinimumLoggingLevel(MinimumLogEventLevel)
|
||||
.SetIsReportLevelVerbose(IsReportLevelVerbose)
|
||||
.SetExpiresAfter(ExpiresAfter)
|
||||
.SetWhatsNew(AppVersion)
|
||||
.SetActiveLockService(LocksServices.Active.GetType().FullName)
|
||||
|
@ -115,7 +120,11 @@ namespace TINK.Model
|
|||
/// <summary>
|
||||
/// Holds the default polling value.
|
||||
/// </summary>
|
||||
#if USCSHARP9
|
||||
public TimeSpan DefaultPolling => new (0, 0, 10);
|
||||
#else
|
||||
public TimeSpan DefaultPolling => new TimeSpan(0, 0, 10);
|
||||
#endif
|
||||
|
||||
/// <summary> Constructs TinkApp object. </summary>
|
||||
/// <param name="settings"></param>
|
||||
|
@ -139,10 +148,9 @@ namespace TINK.Model
|
|||
Settings.Settings settings,
|
||||
IStore accountStore,
|
||||
Func<bool, Uri, string, string, TimeSpan, IConnector> connectorFactory,
|
||||
IGeolocation geolocationService,
|
||||
IGeolodationDependent geolodationServiceDependent,
|
||||
IServicesContainer<IGeolocation> geolocationServicesContainer,
|
||||
ILocksService locksService,
|
||||
IDevice device,
|
||||
ISmartDevice device,
|
||||
ISpecialFolder specialFolder,
|
||||
ICipher cipher,
|
||||
IPermissions permissions = null,
|
||||
|
@ -188,16 +196,8 @@ namespace TINK.Model
|
|||
new HashSet<object> { new Themes.Konrad() , new Themes.ShareeBike() },
|
||||
settings.ActiveTheme);
|
||||
|
||||
GeolocationServices = new ServicesContainerMutable<IGeolocation>(
|
||||
geolocationService == null
|
||||
? new HashSet<IGeolocation> { new LastKnownGeolocationService(geolodationServiceDependent), new SimulatedGeolocationService(geolodationServiceDependent), new GeolocationService(geolodationServiceDependent) }
|
||||
: new HashSet<IGeolocation> { geolocationService },
|
||||
geolocationService == null
|
||||
? (lastVersion >= new Version(3, 0, 173) ? settings.ActiveGeolocationService : typeof(LastKnownGeolocationService).FullName)
|
||||
: geolocationService.GetType().FullName);
|
||||
|
||||
// Load filters from settings or apply defaults if no settings are available
|
||||
var l_oAccount = accountStore.Load();
|
||||
GeolocationServices = geolocationServicesContainer
|
||||
?? throw new ArgumentException($"Can not instantiate {nameof(TinkApp)}- object. No geolocation services container object available.");
|
||||
|
||||
if (settings.ActiveUri == new Uri(CopriServerUriList.TINK_LIVE) ||
|
||||
settings.ActiveUri == new Uri(CopriServerUriList.TINK_DEVEL))
|
||||
|
@ -217,7 +217,7 @@ namespace TINK.Model
|
|||
|
||||
CenterMapToCurrentLocation = settings.CenterMapToCurrentLocation;
|
||||
|
||||
Device = device
|
||||
SmartDevice = device
|
||||
?? throw new ArgumentException("Can not instantiate TinkApp- object. No device information provider available.");
|
||||
|
||||
if (specialFolder == null)
|
||||
|
@ -236,12 +236,10 @@ namespace TINK.Model
|
|||
|
||||
SettingsFileFolder = specialFolder.GetInternalPersonalDir();
|
||||
|
||||
SelectedStation = null;
|
||||
|
||||
ActiveUser = new User.User(
|
||||
accountStore,
|
||||
l_oAccount,
|
||||
device.GetIdentifier());
|
||||
accountStore.GetType().Name == "StoreLegacy" ? new Store() : accountStore,
|
||||
accountStore.Load().Result,
|
||||
device.Identifier);
|
||||
|
||||
this.isConnectedFunc = isConnectedFunc ?? (() => CrossConnectivity.Current.IsConnected);
|
||||
|
||||
|
@ -249,7 +247,7 @@ namespace TINK.Model
|
|||
|
||||
// Create filtered connector for offline mode.
|
||||
m_oConnector = FilteredConnectorFactory.Create(
|
||||
FilterGroupSetting.DoFilter(l_oAccount.DoFilter(GroupFilterMapPage.DoFilter())),
|
||||
FilterGroupSetting.DoFilter(GroupFilterMapPage.DoFilter()),
|
||||
ConnectorFactory(GetIsConnected(), settings.ActiveUri, ActiveUser.SessionCookie, ActiveUser.Mail, ExpiresAfter));
|
||||
|
||||
// Get uris from file.
|
||||
|
@ -266,8 +264,7 @@ namespace TINK.Model
|
|||
|
||||
MinimumLogEventLevel = settings.MinimumLogEventLevel;
|
||||
|
||||
Permissions = permissions ??
|
||||
throw new ArgumentException("Can not instantiate TinkApp- object. Permissions object must never be null.");
|
||||
IsReportLevelVerbose = settings.IsReportLevelVerbose;
|
||||
|
||||
WhatsNew = new WhatsNew(AppVersion, lastVersion, whatsNewShownInVersion);
|
||||
|
||||
|
@ -299,13 +296,10 @@ namespace TINK.Model
|
|||
public User.User ActiveUser { get; }
|
||||
|
||||
/// <summary> Reference of object which provides device information. </summary>
|
||||
public IDevice Device { get; }
|
||||
|
||||
/// <summary> Os permission.</summary>
|
||||
public IPermissions Permissions { get; }
|
||||
public ISmartDevice SmartDevice { get; }
|
||||
|
||||
/// <summary> Holds delegate to determine whether device is connected or not.</summary>
|
||||
private Func<bool> isConnectedFunc;
|
||||
private readonly Func<bool> isConnectedFunc;
|
||||
|
||||
/// <summary> Gets whether device is connected to internet or not. </summary>
|
||||
public bool GetIsConnected() => isConnectedFunc();
|
||||
|
@ -328,13 +322,16 @@ namespace TINK.Model
|
|||
public ICipher Cipher { get; }
|
||||
|
||||
/// <summary> Name of the station which is selected. </summary>
|
||||
public int? SelectedStation { get; set; }
|
||||
public IStation SelectedStation { get; set; } = new Station.Station(null, new List<string>(), null);
|
||||
|
||||
/// <summary> Holds the stations availalbe. </summary>
|
||||
public IEnumerable<IStation> Stations { get; set; } = new List<Station.Station>();
|
||||
|
||||
/// <summary> Action to post to GUI thread.</summary>
|
||||
public Action<SendOrPostCallback, object> PostAction { get; }
|
||||
|
||||
/// <summary> Function which creates a connector depending on connected status.</summary>
|
||||
private Func<bool, Uri, string, string, TimeSpan, IConnector> ConnectorFactory { get; }
|
||||
private Func<bool, Uri, string /*userAgent*/, string /*sessionCookie*/, TimeSpan, IConnector> ConnectorFactory { get; }
|
||||
|
||||
/// <summary> Holds the object which provides offline data.</summary>
|
||||
private IFilteredConnector m_oConnector;
|
||||
|
@ -362,14 +359,11 @@ namespace TINK.Model
|
|||
return m_oConnector;
|
||||
}
|
||||
|
||||
/// <summary> Query geolocation. </summary>
|
||||
public IGeolocation Geolocation => GeolocationServices.Active;
|
||||
|
||||
/// <summary> Manages the different types of LocksService objects.</summary>
|
||||
public LocksServicesContainerMutable LocksServices { get; set; }
|
||||
|
||||
/// <summary> Holds available app themes.</summary>
|
||||
public ServicesContainerMutable<IGeolocation> GeolocationServices { get; }
|
||||
public IServicesContainer<IGeolocation> GeolocationServices { get; }
|
||||
|
||||
/// <summary> Manages the different types of LocksService objects.</summary>
|
||||
public ServicesContainerMutable<object> Themes { get; }
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace TINK.Model.User.Account
|
|||
PickLoggingLevel = 64, // Allows to select the logging level.
|
||||
ShowDiagnostics = 128, // Turns on display of diagnostics.
|
||||
SwitchNoSiteCaching = 1024, // Allows to turn off/ on caching of sites displayed in app hosted by COPRI
|
||||
ReportLevel = 2048, // Allows extent to show error messages.
|
||||
All = PickCopriServer +
|
||||
ManageCopriCacheExpiration +
|
||||
ManagePolling +
|
||||
|
@ -24,7 +25,8 @@ namespace TINK.Model.User.Account
|
|||
PickLocationServiceImplementation +
|
||||
PickLoggingLevel +
|
||||
ShowDiagnostics +
|
||||
SwitchNoSiteCaching,
|
||||
SwitchNoSiteCaching +
|
||||
ReportLevel,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -48,24 +50,24 @@ namespace TINK.Model.User.Account
|
|||
public class Account : IAccount
|
||||
{
|
||||
/// <summary> Constructs an account object.</summary>
|
||||
/// <param name="p_oMail">Mail addresss.</param>
|
||||
/// <param name="p_Pwd">Password.</param>
|
||||
/// <param name="p_oSessionCookie">Session cookie from copri.</param>
|
||||
/// <param name="p_strGroup">Group holdig info about Group (TINK, Konrad, ...)</param>
|
||||
/// <param name="mail">Mail addresss.</param>
|
||||
/// <param name="password">Password.</param>
|
||||
/// <param name="sessionCookie">Session cookie from copri.</param>
|
||||
/// <param name="group">Group holdig info about Group (TINK, Konrad, ...)</param>
|
||||
/// <param name="p_iDebugLevel">Flag which controls display of debug settings.</param>
|
||||
public Account(
|
||||
string p_oMail,
|
||||
string p_Pwd,
|
||||
string p_oSessionCookie,
|
||||
IEnumerable<string> p_strGroup,
|
||||
string mail,
|
||||
string password,
|
||||
string sessionCookie,
|
||||
IEnumerable<string> group,
|
||||
Permissions debugLevel = Permissions.None)
|
||||
{
|
||||
Mail = p_oMail;
|
||||
Pwd = p_Pwd;
|
||||
SessionCookie = p_oSessionCookie;
|
||||
Mail = mail;
|
||||
Pwd = password;
|
||||
SessionCookie = sessionCookie;
|
||||
DebugLevel = debugLevel;
|
||||
Group = p_strGroup != null
|
||||
? new HashSet<string>(p_strGroup).ToList()
|
||||
Group = group != null
|
||||
? new HashSet<string>(group).ToList()
|
||||
: throw new ArgumentException("Can not instantiate account object. Reference to group list must not be empty.");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
namespace TINK.Model.User.Account
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TINK.Model.User.Account
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to manage an account store.
|
||||
/// </summary>
|
||||
/// <summary>Interface to manage an account store.</summary>
|
||||
public interface IStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads mail address and password from account store.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IAccount Load();
|
||||
Task<IAccount> Load();
|
||||
|
||||
/// <summary>
|
||||
/// Writes mail address and password to account store.
|
||||
/// </summary>
|
||||
/// <param name="p_oMailAndPwd"></param>
|
||||
void Save(IAccount p_oMailAndPwd);
|
||||
/// <param name="mailAndPwd"></param>
|
||||
Task Save(IAccount mailAndPwd);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes mail address and password from account store.
|
||||
/// </summary>
|
||||
/// <returns> Empty account instance if deleting succeeded.</returns>
|
||||
IAccount Delete(IAccount p_oMailAndPwd);
|
||||
IAccount Delete(IAccount mailAndPwd);
|
||||
}
|
||||
}
|
||||
|
|
67
TINKLib/Model/User/Account/Store.cs
Normal file
67
TINKLib/Model/User/Account/Store.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Essentials;
|
||||
|
||||
namespace TINK.Model.User.Account
|
||||
{
|
||||
public class Store : IStore
|
||||
{
|
||||
/// <summary> Holds id of the debug level key. </summary>
|
||||
private const string KEY_DEBUGLEVEL = "DebugLevel";
|
||||
|
||||
/// <summary> Holds the id of the session. </summary>
|
||||
private const string KEY_SESSIONCOOKIE = "SessionCookie";
|
||||
|
||||
/// <summary> Holds id of the mail address key. </summary>
|
||||
private const string KEY_MAILADDRESS = "MailAddress";
|
||||
|
||||
public IAccount Delete(IAccount account)
|
||||
{
|
||||
SecureStorage.RemoveAll();
|
||||
return new EmptyAccount();
|
||||
}
|
||||
|
||||
public async Task<IAccount> Load()
|
||||
{
|
||||
|
||||
var mail = string.Empty;
|
||||
var sessionCookie = string.Empty;
|
||||
var debugLevel = Permissions.None;
|
||||
|
||||
try
|
||||
{
|
||||
mail = await SecureStorage.GetAsync(KEY_MAILADDRESS);
|
||||
sessionCookie = await SecureStorage.GetAsync(KEY_SESSIONCOOKIE);
|
||||
Enum.TryParse(await SecureStorage.GetAsync(KEY_DEBUGLEVEL), out debugLevel);
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<Store>().Error("Loading account from store failed. {Exception}", exception);
|
||||
}
|
||||
|
||||
return new Account(
|
||||
mail,
|
||||
string.Empty,
|
||||
sessionCookie,
|
||||
new List<string>(),
|
||||
debugLevel);
|
||||
}
|
||||
|
||||
public async Task Save(IAccount mailAndPwd)
|
||||
{
|
||||
try
|
||||
{
|
||||
await SecureStorage.SetAsync(KEY_MAILADDRESS, mailAndPwd.Mail);
|
||||
await SecureStorage.SetAsync(KEY_SESSIONCOOKIE, mailAndPwd.SessionCookie);
|
||||
await SecureStorage.SetAsync(KEY_DEBUGLEVEL, mailAndPwd.DebugLevel.ToString());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<Store>().Error("Saving account from store failed. {Exception}", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.User.Account;
|
||||
|
||||
namespace TINK.Model.User
|
||||
|
@ -29,14 +30,14 @@ namespace TINK.Model.User
|
|||
/// </summary>
|
||||
/// <param name="p_oAccountStore"> Object to use for loading and saving user data.</param>
|
||||
public User(
|
||||
IStore p_oAccountStore,
|
||||
IAccount p_oAccount,
|
||||
string p_strDeviceId)
|
||||
IStore accountStore,
|
||||
IAccount account,
|
||||
string deviceId)
|
||||
{
|
||||
m_oStore = p_oAccountStore
|
||||
m_oStore = accountStore
|
||||
?? throw new ArgumentException("Can not instantiate user- object. No store functionality available.");
|
||||
DeviceId = p_strDeviceId;
|
||||
m_oAccount = new AccountMutable(p_oAccount);
|
||||
DeviceId = deviceId;
|
||||
m_oAccount = new AccountMutable(account);
|
||||
}
|
||||
|
||||
/// <summary> Is fired wheneverlogin state changes. </summary>
|
||||
|
@ -109,13 +110,13 @@ namespace TINK.Model.User
|
|||
/// <param name="p_oAccount">Account to use for login.</param>
|
||||
/// <param name="p_str_DeviceId">Holds the Id to identify the device.</param>
|
||||
/// <param name="isConnected">True if connector has access to copri server, false if cached values are used.</param>
|
||||
public void Login(IAccount account)
|
||||
public async Task Login(IAccount account)
|
||||
{
|
||||
// Update account instance from copri data.
|
||||
m_oAccount.Copy(account);
|
||||
|
||||
// Save data to store.
|
||||
m_oStore.Save(m_oAccount);
|
||||
await m_oStore.Save(m_oAccount);
|
||||
|
||||
// Nothing to do because state did not change.
|
||||
StateChanged?.Invoke(this, new EventArgs());
|
||||
|
|
|
@ -316,7 +316,7 @@ namespace TINK.Model
|
|||
},
|
||||
{
|
||||
new Version(3, 0, 208),
|
||||
AppResources.ChangeLog3_0_208
|
||||
AppResources.ChangeLog3_0_208 // Minor fixes.
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 209),
|
||||
|
@ -340,7 +340,7 @@ namespace TINK.Model
|
|||
},
|
||||
{
|
||||
new Version(3, 0, 218),
|
||||
AppResources.ChangeLog3_0_218
|
||||
AppResources.ChangeLog3_0_208
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 219),
|
||||
|
@ -353,8 +353,61 @@ namespace TINK.Model
|
|||
{
|
||||
new Version(3, 0, 222),
|
||||
AppResources.ChangeLog3_0_222
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 223),
|
||||
AppResources.ChangeLog3_0_208
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 224),
|
||||
AppResources.ChangeLog3_0_224
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 225),
|
||||
AppResources.ChangeLog3_0_208
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 226),
|
||||
AppResources.ChangeLog3_0_226
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 227),
|
||||
AppResources.ChangeLog3_0_227
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 228),
|
||||
AppResources.ChangeLog3_0_208
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 231),
|
||||
AppResources.ChangeLog3_0_231
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 232),
|
||||
AppResources.ChangeLog3_0_232
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 234),
|
||||
AppResources.ChangeLog3_0_234
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 235),
|
||||
AppResources.ChangeLog3_0_235
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 236),
|
||||
AppResources.ChangeLog3_0_236
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 237),
|
||||
AppResources.ChangeLog3_0_237
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 238),
|
||||
AppResources.ChangeLog3_0_231
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/// <summary> Manges the whats new information.</summary>
|
||||
|
|
207
TINKLib/MultilingualResources/AppResources.Designer.cs
generated
207
TINKLib/MultilingualResources/AppResources.Designer.cs
generated
|
@ -222,6 +222,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Offline..
|
||||
/// </summary>
|
||||
public static string ActivityTextConnectionStateOffline {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextConnectionStateOffline", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Disconnecting lock....
|
||||
/// </summary>
|
||||
|
@ -322,11 +331,20 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection error. Code: {0}..
|
||||
/// Looks up a localized string similar to Connection error. Status code: {0}..
|
||||
/// </summary>
|
||||
public static string ActivityTextErrorWebException {
|
||||
public static string ActivityTextErrorWebExceptionGeneralError {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextErrorWebException", resourceCulture);
|
||||
return ResourceManager.GetString("ActivityTextErrorWebExceptionGeneralError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection error. Status description: {0}..
|
||||
/// </summary>
|
||||
public static string ActivityTextErrorWebExceptionProtocolError {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextErrorWebExceptionProtocolError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +357,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cache used..
|
||||
/// </summary>
|
||||
public static string ActivityTextException {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextException", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Loading Stations and Bikes....
|
||||
/// </summary>
|
||||
|
@ -456,6 +483,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Updateing.....
|
||||
/// </summary>
|
||||
public static string ActivityTextUpdating {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextUpdating", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Updated to latest lock firmware..
|
||||
/// </summary>
|
||||
|
@ -557,15 +593,6 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Minor fixes..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_218 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_218", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Icons added to flyout menu..
|
||||
/// </summary>
|
||||
|
@ -602,6 +629,92 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Updated for latest server version..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_224 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_224", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Fixes
|
||||
///- station markers are updated correctly after login/ logout if required
|
||||
///- routing from "bikes at station" to "login" page and other routings corrected.
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_226 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_226", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Feedback dialog added which is shown after returning bike..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_227 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_227", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Minor improvements..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_231 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_231", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Menu modified..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_232 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_232", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tariff info page is displayed correctly again.
|
||||
///Error handling improved..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_234 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_234", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Obsolete object replaced with up-to-date one..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_235 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_235", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Stations names instead descriptions shown on page title.
|
||||
///Error message when opening lock fails improved.
|
||||
///Layout of bike names and id display improved..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_236 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_236", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hard- and software information send to backend when returning bike..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_237 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_237", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Lock of rented bike can not be found..
|
||||
/// </summary>
|
||||
|
@ -688,9 +801,18 @@ namespace TINK.MultilingualResources {
|
|||
/// <summary>
|
||||
/// Looks up a localized string similar to Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again..
|
||||
/// </summary>
|
||||
public static string ErrorOpenLockMessage {
|
||||
public static string ErrorOpenLockBoldBlockedMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorOpenLockMessage", resourceCulture);
|
||||
return ResourceManager.GetString("ErrorOpenLockBoldBlockedMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Lock was blocked and might still be. Please ensure that no obstacle prevents lock from opening and try again..
|
||||
/// </summary>
|
||||
public static string ErrorOpenLockBoldWasBlockedMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorOpenLockBoldWasBlockedMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,6 +837,15 @@ namespace TINK.MultilingualResources {
|
|||
/// <summary>
|
||||
/// Looks up a localized string similar to Lock can not be opened!.
|
||||
/// </summary>
|
||||
public static string ErrorOpenLockStillOpenTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorOpenLockStillOpenTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error while opening lock!.
|
||||
/// </summary>
|
||||
public static string ErrorOpenLockTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorOpenLockTitle", resourceCulture);
|
||||
|
@ -770,6 +901,24 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Your feedback could not be send to server successfully..
|
||||
/// </summary>
|
||||
public static string ErrorReturnSubmitFeedbackMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorReturnSubmitFeedbackMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Submitting feedback failed!.
|
||||
/// </summary>
|
||||
public static string ErrorReturnSubmitFeedbackTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorReturnSubmitFeedbackTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Attachment could not be created..
|
||||
/// </summary>
|
||||
|
@ -871,15 +1020,6 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bike Location {0}.
|
||||
/// </summary>
|
||||
public static string MarkingBikesAtStationTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("MarkingBikesAtStationTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Contact.
|
||||
/// </summary>
|
||||
|
@ -1207,6 +1347,16 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This version of the {0} App is not compatible with server detected.
|
||||
///Please contact the support for help..
|
||||
/// </summary>
|
||||
public static string MessageCopriVersionIsOutdated {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageCopriVersionIsOutdated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Attention: Lock is closed!
|
||||
///{0}
|
||||
|
@ -1247,7 +1397,7 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error during login!.
|
||||
/// Looks up a localized string similar to Error while logging in!.
|
||||
/// </summary>
|
||||
public static string MessageLoginErrorTitle {
|
||||
get {
|
||||
|
@ -1300,6 +1450,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error while logging out!.
|
||||
/// </summary>
|
||||
public static string MessageLogoutErrorTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageLogoutErrorTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Session has expired.
|
||||
///Either there are more than 8 devices in use or the user's account is no longer valid.
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<value>Kein Benutzer angemeldet.</value>
|
||||
</data>
|
||||
<data name="MessageAppVersionIsOutdated" xml:space="preserve">
|
||||
<value>Diese version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</value>
|
||||
<value>Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</value>
|
||||
</data>
|
||||
<data name="QuestionSupportmailSubject" xml:space="preserve">
|
||||
<value>Betrifft die Anfrage/ Anmerkung die {0}-App oder ein allgemeines Thema?</value>
|
||||
|
@ -99,9 +99,6 @@
|
|||
<data name="MarkingTabFees" xml:space="preserve">
|
||||
<value>Tarife</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockMessage" xml:space="preserve">
|
||||
<value>Schloss ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</value>
|
||||
</data>
|
||||
<data name="ErrorCloseLockBoldBlockedMessage" xml:space="preserve">
|
||||
<value>Schloss ist blockiert. Bitte sicherstellen, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und Vorgang wiederholen.</value>
|
||||
</data>
|
||||
|
@ -190,9 +187,6 @@ Entweder es sind mehr als 8 Geräte in Benutzung oder das Konto ist nicht mehr g
|
|||
Die Nutzung der App ist auf maximal 8 Geräten pro Konto möglich.
|
||||
Bitte erneut in App anmelden. Sollte dies fehlschlagen bitte auf Website prüfen, ob das Konto noch gültig ist.</value>
|
||||
</data>
|
||||
<data name="MarkingBikesAtStationTitle" xml:space="preserve">
|
||||
<value>Fahrradstandort {0}</value>
|
||||
</data>
|
||||
<data name="StatusTextReservationExpiredCodeMaxReservationTime" xml:space="preserve">
|
||||
<value>Code ist {0}, max. Reservierungszeit von {1} Min. abgelaufen.
|
||||
</value>
|
||||
|
@ -296,9 +290,6 @@ Bitte erneut in App anmelden. Sollte dies fehlschlagen bitte auf Website prüfen
|
|||
<data name="ErrorOpenLockOutOfReadMessage" xml:space="preserve">
|
||||
<value>Schloss kann erst geöffnet werden, wenn Rad in der Nähe ist.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockTitle" xml:space="preserve">
|
||||
<value>Schloss kann nicht geöffnet werden!</value>
|
||||
</data>
|
||||
<data name="ErrorCloseLockOutOfReachMessage" xml:space="preserve">
|
||||
<value>Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. </value>
|
||||
</data>
|
||||
|
@ -480,9 +471,6 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
|
|||
<data name="ActivityTextErrorWebConnectFailureException" xml:space="preserve">
|
||||
<value>Verbindung unterbrochen, Server nicht erreichbar.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebException" xml:space="preserve">
|
||||
<value>Verbindungsfehler. Code: {0}.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebForbiddenException" xml:space="preserve">
|
||||
<value>Verbindung unterbrochen, Server beschäftigt.</value>
|
||||
</data>
|
||||
|
@ -528,9 +516,6 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
|
|||
<data name="ChangeLog3_0_217" xml:space="preserve">
|
||||
<value>Pakete aktualisiert.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_218" xml:space="preserve">
|
||||
<value>Kleine Verbesserungen.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_219" xml:space="preserve">
|
||||
<value>Icons zum Flyout-Menü hinzugefügt.</value>
|
||||
</data>
|
||||
|
@ -543,4 +528,77 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
|
|||
<data name="ChangeLog3_0_222" xml:space="preserve">
|
||||
<value>Kleine Fehlerbehebungen und Verbesserungen.</value>
|
||||
</data>
|
||||
<data name="MessageLogoutErrorTitle" xml:space="preserve">
|
||||
<value>Fehler beim Abmelden!</value>
|
||||
</data>
|
||||
<data name="MessageCopriVersionIsOutdated" xml:space="preserve">
|
||||
<value>Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server.
|
||||
Bitte kontaktieren sie den Support!</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_224" xml:space="preserve">
|
||||
<value>Aktualisiert auf aktuelle Serverversion.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_226" xml:space="preserve">
|
||||
<value>Fehlerbehebungen
|
||||
- Stationssymbole werden nach dem An-/ Abmelden aktualisiert
|
||||
- Navigation von "Fahrradstandort X" auf "Anmelen"- Seite und andere Verknüpfungen korrigiert
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebExceptionProtocolError" xml:space="preserve">
|
||||
<value>Verbindungsfehler. Statusbeschreibung: {0}.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebExceptionGeneralError" xml:space="preserve">
|
||||
<value>Verbindungsfehler. Status statucode: {0}.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_227" xml:space="preserve">
|
||||
<value>Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</value>
|
||||
</data>
|
||||
<data name="ActivityTextConnectionStateOffline" xml:space="preserve">
|
||||
<value>Offline.</value>
|
||||
</data>
|
||||
<data name="ActivityTextException" xml:space="preserve">
|
||||
<value>Cache Daten.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnSubmitFeedbackMessage" xml:space="preserve">
|
||||
<value>Ihre Rückmeldung konnte nicht an den Server übermittelt werden.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnSubmitFeedbackTitle" xml:space="preserve">
|
||||
<value>Übermittlung der Rückmeldung fehlgeschlagen!</value>
|
||||
</data>
|
||||
<data name="ActivityTextUpdating" xml:space="preserve">
|
||||
<value>Aktualisiere....</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_231" xml:space="preserve">
|
||||
<value>Kleine Verbesserungen.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_232" xml:space="preserve">
|
||||
<value>Menu geändert.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_234" xml:space="preserve">
|
||||
<value>Tarifinfo-Seite wird wieder korrekt angezeigt.
|
||||
Fehlerhandling verbessert.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_235" xml:space="preserve">
|
||||
<value>Veraltetes Objekt durch aktuelles ersetzt.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockBoldBlockedMessage" xml:space="preserve">
|
||||
<value>Schloss ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockBoldWasBlockedMessage" xml:space="preserve">
|
||||
<value>Schloss war oder ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockTitle" xml:space="preserve">
|
||||
<value>Fehler beim Schlossöffnen!</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockStillOpenTitle" xml:space="preserve">
|
||||
<value>Schloss kann nicht geöffnet werden!</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_236" xml:space="preserve">
|
||||
<value>Anzeige von Stationsnamen statt Nummern.
|
||||
Fehlermeldung beim Öffnen von Schloss verbessert.
|
||||
Layout Anzeige Radnamen und nummern verbessert.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_237" xml:space="preserve">
|
||||
<value>Hard- und software information werden an Backend übermittelt bei Radrückgabe.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -156,9 +156,6 @@
|
|||
<data name="ErrorCloseLockMovingMessage" xml:space="preserve">
|
||||
<value>Lock can only be closed if bike is not moving. Please park bike and try again.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockMessage" xml:space="preserve">
|
||||
<value>Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.</value>
|
||||
</data>
|
||||
<data name="ErrorReservedSearchMessage" xml:space="preserve">
|
||||
<value>Lock of reserved bike can not be found.</value>
|
||||
</data>
|
||||
|
@ -193,9 +190,6 @@ Bike can only be returned if bike is in reach and location information is avail
|
|||
<data name="MarkingAccount" xml:space="preserve">
|
||||
<value>Account</value>
|
||||
</data>
|
||||
<data name="MarkingBikesAtStationTitle" xml:space="preserve">
|
||||
<value>Bike Location {0}</value>
|
||||
</data>
|
||||
<data name="MarkingFeedbackAndContact" xml:space="preserve">
|
||||
<value>Contact</value>
|
||||
</data>
|
||||
|
@ -378,7 +372,7 @@ Please login to app once again. In case this fails please check on website if th
|
|||
<value>Connection error during registration!</value>
|
||||
</data>
|
||||
<data name="MessageLoginErrorTitle" xml:space="preserve">
|
||||
<value>Error during login!</value>
|
||||
<value>Error while logging in!</value>
|
||||
</data>
|
||||
<data name="MessageLoginRecoverPassword" xml:space="preserve">
|
||||
<value>Please connect to Internet to recover the password.</value>
|
||||
|
@ -396,7 +390,7 @@ Please login to app once again. In case this fails please check on website if th
|
|||
<value>Lock cannot be opened until bike is near.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockTitle" xml:space="preserve">
|
||||
<value>Lock can not be opened!</value>
|
||||
<value>Error while opening lock!</value>
|
||||
</data>
|
||||
<data name="ErrorCloseLockOutOfReachMessage" xml:space="preserve">
|
||||
<value>Lock cannot be closed until bike is near.</value>
|
||||
|
@ -577,8 +571,8 @@ Please restart app in order to get bike info.</value>
|
|||
<data name="ActivityTextErrorWebConnectFailureException" xml:space="preserve">
|
||||
<value>Connection interrupted, server unreachable.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebException" xml:space="preserve">
|
||||
<value>Connection error. Code: {0}.</value>
|
||||
<data name="ActivityTextErrorWebExceptionGeneralError" xml:space="preserve">
|
||||
<value>Connection error. Status code: {0}.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebForbiddenException" xml:space="preserve">
|
||||
<value>Connection interrupted, server busy.</value>
|
||||
|
@ -625,9 +619,6 @@ Please restart app in order to get bike info.</value>
|
|||
<data name="ChangeLog3_0_217" xml:space="preserve">
|
||||
<value>Packages updated.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_218" xml:space="preserve">
|
||||
<value>Minor fixes.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_219" xml:space="preserve">
|
||||
<value>Icons added to flyout menu.</value>
|
||||
</data>
|
||||
|
@ -640,4 +631,70 @@ Please restart app in order to get bike info.</value>
|
|||
<data name="ChangeLog3_0_222" xml:space="preserve">
|
||||
<value>Minor bugfix and improvements.</value>
|
||||
</data>
|
||||
<data name="MessageLogoutErrorTitle" xml:space="preserve">
|
||||
<value>Error while logging out!</value>
|
||||
</data>
|
||||
<data name="MessageCopriVersionIsOutdated" xml:space="preserve">
|
||||
<value>This version of the {0} App is not compatible with server detected.
|
||||
Please contact the support for help.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_224" xml:space="preserve">
|
||||
<value>Updated for latest server version.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_226" xml:space="preserve">
|
||||
<value>Fixes
|
||||
- station markers are updated correctly after login/ logout if required
|
||||
- routing from "bikes at station" to "login" page and other routings corrected</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorWebExceptionProtocolError" xml:space="preserve">
|
||||
<value>Connection error. Status description: {0}.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_227" xml:space="preserve">
|
||||
<value>Feedback dialog added which is shown after returning bike.</value>
|
||||
</data>
|
||||
<data name="ActivityTextConnectionStateOffline" xml:space="preserve">
|
||||
<value>Offline.</value>
|
||||
</data>
|
||||
<data name="ActivityTextException" xml:space="preserve">
|
||||
<value>Cache used.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnSubmitFeedbackMessage" xml:space="preserve">
|
||||
<value>Your feedback could not be send to server successfully.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnSubmitFeedbackTitle" xml:space="preserve">
|
||||
<value>Submitting feedback failed!</value>
|
||||
</data>
|
||||
<data name="ActivityTextUpdating" xml:space="preserve">
|
||||
<value>Updateing....</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_231" xml:space="preserve">
|
||||
<value>Minor improvements.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_232" xml:space="preserve">
|
||||
<value>Menu modified.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_234" xml:space="preserve">
|
||||
<value>Tariff info page is displayed correctly again.
|
||||
Error handling improved.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_235" xml:space="preserve">
|
||||
<value>Obsolete object replaced with up-to-date one.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockBoldBlockedMessage" xml:space="preserve">
|
||||
<value>Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockBoldWasBlockedMessage" xml:space="preserve">
|
||||
<value>Lock was blocked and might still be. Please ensure that no obstacle prevents lock from opening and try again.</value>
|
||||
</data>
|
||||
<data name="ErrorOpenLockStillOpenTitle" xml:space="preserve">
|
||||
<value>Lock can not be opened!</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_236" xml:space="preserve">
|
||||
<value>Stations names instead descriptions shown on page title.
|
||||
Error message when opening lock fails improved.
|
||||
Layout of bike names and id display improved.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_237" xml:space="preserve">
|
||||
<value>Hard- and software information send to backend when returning bike.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -72,7 +72,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="MessageAppVersionIsOutdated" translate="yes" xml:space="preserve">
|
||||
<source>This version of the {0} App is outdated. Please update to the latest version.</source>
|
||||
<target state="translated">Diese version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</target>
|
||||
<target state="translated">Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="QuestionSupportmailSubject" translate="yes" xml:space="preserve">
|
||||
<source>Does your request/ comment relate to the {0}-app or to a more general subject?</source>
|
||||
|
@ -122,10 +122,6 @@
|
|||
<source>Pricing</source>
|
||||
<target state="translated">Tarife</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockMessage" translate="yes" xml:space="preserve">
|
||||
<source>Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.</source>
|
||||
<target state="translated">Schloss ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorCloseLockBoldBlockedMessage" translate="yes" xml:space="preserve">
|
||||
<source>Lock is blocked. Please ensure that no spoke or any other obstacle prevents the lock from closing and try again.</source>
|
||||
<target state="translated">Schloss ist blockiert. Bitte sicherstellen, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und Vorgang wiederholen.</target>
|
||||
|
@ -248,10 +244,6 @@ Entweder es sind mehr als 8 Geräte in Benutzung oder das Konto ist nicht mehr g
|
|||
Die Nutzung der App ist auf maximal 8 Geräten pro Konto möglich.
|
||||
Bitte erneut in App anmelden. Sollte dies fehlschlagen bitte auf Website prüfen, ob das Konto noch gültig ist.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MarkingBikesAtStationTitle" translate="yes" xml:space="preserve">
|
||||
<source>Bike Location {0}</source>
|
||||
<target state="translated">Fahrradstandort {0}</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="StatusTextReservationExpiredCodeMaxReservationTime" translate="yes" xml:space="preserve">
|
||||
<source>Code {0}, max. reservation time of {1} minutes expired.</source>
|
||||
<target state="translated">Code ist {0}, max. Reservierungszeit von {1} Min. abgelaufen.
|
||||
|
@ -365,7 +357,7 @@ Bitte erneut in App anmelden. Sollte dies fehlschlagen bitte auf Website prüfen
|
|||
<target state="translated">Verbindungsfehler beim Registrieren!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageLoginErrorTitle" translate="yes" xml:space="preserve">
|
||||
<source>Error during login!</source>
|
||||
<source>Error while logging in!</source>
|
||||
<target state="translated">Fehler bei der Anmeldung!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageLoginRecoverPassword" translate="yes" xml:space="preserve">
|
||||
|
@ -388,10 +380,6 @@ Bitte erneut in App anmelden. Sollte dies fehlschlagen bitte auf Website prüfen
|
|||
<source>Lock cannot be opened until bike is near.</source>
|
||||
<target state="translated">Schloss kann erst geöffnet werden, wenn Rad in der Nähe ist.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockTitle" translate="yes" xml:space="preserve">
|
||||
<source>Lock can not be opened!</source>
|
||||
<target state="translated">Schloss kann nicht geöffnet werden!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorCloseLockOutOfReachMessage" translate="yes" xml:space="preserve">
|
||||
<source>Lock cannot be closed until bike is near.</source>
|
||||
<target state="translated">Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. </target>
|
||||
|
@ -640,10 +628,6 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
|
|||
<source>Connection interrupted, server unreachable.</source>
|
||||
<target state="translated">Verbindung unterbrochen, Server nicht erreichbar.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorWebException" translate="yes" xml:space="preserve">
|
||||
<source>Connection error. Code: {0}.</source>
|
||||
<target state="translated">Verbindungsfehler. Code: {0}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorWebForbiddenException" translate="yes" xml:space="preserve">
|
||||
<source>Connection interrupted, server busy.</source>
|
||||
<target state="translated">Verbindung unterbrochen, Server beschäftigt.</target>
|
||||
|
@ -704,10 +688,6 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
|
|||
<source>Packages updated.</source>
|
||||
<target state="translated">Pakete aktualisiert.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_218" translate="yes" xml:space="preserve">
|
||||
<source>Minor fixes.</source>
|
||||
<target state="translated">Kleine Verbesserungen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_219" translate="yes" xml:space="preserve">
|
||||
<source>Icons added to flyout menu.</source>
|
||||
<target state="translated">Icons zum Flyout-Menü hinzugefügt.</target>
|
||||
|
@ -724,6 +704,107 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
|
|||
<source>Minor bugfix and improvements.</source>
|
||||
<target state="translated">Kleine Fehlerbehebungen und Verbesserungen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageLogoutErrorTitle" translate="yes" xml:space="preserve">
|
||||
<source>Error while logging out!</source>
|
||||
<target state="translated">Fehler beim Abmelden!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageCopriVersionIsOutdated" translate="yes" xml:space="preserve">
|
||||
<source>This version of the {0} App is not compatible with server detected.
|
||||
Please contact the support for help.</source>
|
||||
<target state="translated">Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server.
|
||||
Bitte kontaktieren sie den Support!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_224" translate="yes" xml:space="preserve">
|
||||
<source>Updated for latest server version.</source>
|
||||
<target state="translated">Aktualisiert auf aktuelle Serverversion.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_226" translate="yes" xml:space="preserve">
|
||||
<source>Fixes
|
||||
- station markers are updated correctly after login/ logout if required
|
||||
- routing from "bikes at station" to "login" page and other routings corrected</source>
|
||||
<target state="translated">Fehlerbehebungen
|
||||
- Stationssymbole werden nach dem An-/ Abmelden aktualisiert
|
||||
- Navigation von "Fahrradstandort X" auf "Anmelen"- Seite und andere Verknüpfungen korrigiert
|
||||
</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorWebExceptionProtocolError" translate="yes" xml:space="preserve">
|
||||
<source>Connection error. Status description: {0}.</source>
|
||||
<target state="translated">Verbindungsfehler. Statusbeschreibung: {0}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorWebExceptionGeneralError" translate="yes" xml:space="preserve">
|
||||
<source>Connection error. Status code: {0}.</source>
|
||||
<target state="translated">Verbindungsfehler. Status statucode: {0}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_227" translate="yes" xml:space="preserve">
|
||||
<source>Feedback dialog added which is shown after returning bike.</source>
|
||||
<target state="translated">Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextConnectionStateOffline" translate="yes" xml:space="preserve">
|
||||
<source>Offline.</source>
|
||||
<target state="translated">Offline.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextException" translate="yes" xml:space="preserve">
|
||||
<source>Cache used.</source>
|
||||
<target state="translated">Cache Daten.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorReturnSubmitFeedbackMessage" translate="yes" xml:space="preserve">
|
||||
<source>Your feedback could not be send to server successfully.</source>
|
||||
<target state="translated">Ihre Rückmeldung konnte nicht an den Server übermittelt werden.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorReturnSubmitFeedbackTitle" translate="yes" xml:space="preserve">
|
||||
<source>Submitting feedback failed!</source>
|
||||
<target state="translated">Übermittlung der Rückmeldung fehlgeschlagen!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextUpdating" translate="yes" xml:space="preserve">
|
||||
<source>Updateing....</source>
|
||||
<target state="translated">Aktualisiere....</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_231" translate="yes" xml:space="preserve">
|
||||
<source>Minor improvements.</source>
|
||||
<target state="translated">Kleine Verbesserungen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_232" translate="yes" xml:space="preserve">
|
||||
<source>Menu modified.</source>
|
||||
<target state="translated">Menu geändert.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_234" translate="yes" xml:space="preserve">
|
||||
<source>Tariff info page is displayed correctly again.
|
||||
Error handling improved.</source>
|
||||
<target state="translated">Tarifinfo-Seite wird wieder korrekt angezeigt.
|
||||
Fehlerhandling verbessert.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_235" translate="yes" xml:space="preserve">
|
||||
<source>Obsolete object replaced with up-to-date one.</source>
|
||||
<target state="translated">Veraltetes Objekt durch aktuelles ersetzt.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockBoldBlockedMessage" translate="yes" xml:space="preserve">
|
||||
<source>Lock is blocked. Please ensure that no obstacle prevents lock from opening and try again.</source>
|
||||
<target state="translated">Schloss ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockBoldWasBlockedMessage" translate="yes" xml:space="preserve">
|
||||
<source>Lock was blocked and might still be. Please ensure that no obstacle prevents lock from opening and try again.</source>
|
||||
<target state="translated">Schloss war oder ist blockiert. Bitte Ursache von Blockierung beheben und Vorgang wiederholen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockTitle" translate="yes" xml:space="preserve">
|
||||
<source>Error while opening lock!</source>
|
||||
<target state="translated">Fehler beim Schlossöffnen!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorOpenLockStillOpenTitle" translate="yes" xml:space="preserve">
|
||||
<source>Lock can not be opened!</source>
|
||||
<target state="translated">Schloss kann nicht geöffnet werden!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_236" translate="yes" xml:space="preserve">
|
||||
<source>Stations names instead descriptions shown on page title.
|
||||
Error message when opening lock fails improved.
|
||||
Layout of bike names and id display improved.</source>
|
||||
<target state="translated">Anzeige von Stationsnamen statt Nummern.
|
||||
Fehlermeldung beim Öffnen von Schloss verbessert.
|
||||
Layout Anzeige Radnamen und nummern verbessert.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_237" translate="yes" xml:space="preserve">
|
||||
<source>Hard- and software information send to backend when returning bike.</source>
|
||||
<target state="translated">Hard- und software information werden an Backend übermittelt bei Radrückgabe.</target>
|
||||
</trans-unit>
|
||||
</group>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -5,13 +5,13 @@ using System.IO;
|
|||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Model.Logging;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.Logging;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Repository
|
||||
namespace TINK.Repository
|
||||
{
|
||||
/// <summary> Object which manages calls to copri. </summary>
|
||||
public class CopriCallsHttps : ICopriServer
|
||||
|
@ -20,17 +20,17 @@ namespace TINK.Model.Repository
|
|||
private IRequestBuilder requestBuilder;
|
||||
|
||||
/// <summary> Initializes a instance of the copri calls https object. </summary>
|
||||
/// <param name="p_oCopriHost">Host to connect to. </param>
|
||||
/// <param name="p_strMerchantId">Id of the merchant.</param>
|
||||
/// <param name="copriHost">Host to connect to. </param>
|
||||
/// <param name="merchantId">Id of the merchant.</param>
|
||||
/// <param name="userAgent">Holds the name and version of the TINKApp.</param>
|
||||
/// <param name="sessionCookie">Session cookie if user is logged in, null otherwise.</param>
|
||||
public CopriCallsHttps(
|
||||
Uri p_oCopriHost,
|
||||
string p_strMerchantId,
|
||||
Uri copriHost,
|
||||
string merchantId,
|
||||
string userAgent,
|
||||
string sessionCookie = null)
|
||||
{
|
||||
m_oCopriHost = p_oCopriHost
|
||||
m_oCopriHost = copriHost
|
||||
?? throw new System.Exception($"Can not construct {GetType().ToString()}- object. Uri of copri host must not be null.");
|
||||
|
||||
UserAgent = !string.IsNullOrEmpty(userAgent)
|
||||
|
@ -38,8 +38,8 @@ namespace TINK.Model.Repository
|
|||
: throw new System.Exception($"Can not construct {GetType().ToString()}- object. User agent must not be null or empty.");
|
||||
|
||||
requestBuilder = string.IsNullOrEmpty(sessionCookie)
|
||||
? new RequestBuilder(p_strMerchantId) as IRequestBuilder
|
||||
: new RequestBuilderLoggedIn(p_strMerchantId, sessionCookie);
|
||||
? new RequestBuilder(merchantId) as IRequestBuilder
|
||||
: new RequestBuilderLoggedIn(merchantId, sessionCookie);
|
||||
}
|
||||
|
||||
/// <summary> Holds the URL for rest calls.</summary>
|
||||
|
@ -108,14 +108,15 @@ namespace TINK.Model.Repository
|
|||
/// <returns>List of files.</returns>
|
||||
public async Task<StationsAllResponse> GetStationsAsync()
|
||||
{
|
||||
return await GetStationsAsync(m_oCopriHost.AbsoluteUri, requestBuilder.GetStations(), UserAgent);
|
||||
var stations = await GetStationsAsync(m_oCopriHost.AbsoluteUri, requestBuilder.GetStations(), UserAgent);
|
||||
return stations;
|
||||
}
|
||||
|
||||
/// <summary> Get authentication keys. </summary>
|
||||
/// <param name="bikeId">Id of the bike to get keys for.</param>
|
||||
/// <returns>Response holding authentication keys.</returns>
|
||||
public async Task<ReservationBookingResponse> GetAuthKeys(int bikeId)
|
||||
=> await GetAuthKeysAsync(m_oCopriHost.AbsoluteUri, requestBuilder.CalculateAuthKeys(bikeId), UserAgent);
|
||||
public async Task<ReservationBookingResponse> GetAuthKeys(string bikeId)
|
||||
=> await GetAuthKeysAsync(m_oCopriHost.AbsoluteUri, requestBuilder.CalculateAuthParameters(bikeId), UserAgent);
|
||||
|
||||
|
||||
/// <summary> Gets booking request response.</summary>
|
||||
|
@ -123,7 +124,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Booking response.</returns>
|
||||
public async Task<ReservationBookingResponse> DoReserveAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri)
|
||||
{
|
||||
return await DoReserveAsync(
|
||||
|
@ -137,7 +138,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on cancel booking request.</returns>
|
||||
public async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri)
|
||||
{
|
||||
return await DoCancelReservationAsync(
|
||||
|
@ -151,11 +152,11 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response holding authentication keys.</returns>
|
||||
public async Task<ReservationBookingResponse> CalculateAuthKeysAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri)
|
||||
=> await GetAuthKeysAsync(
|
||||
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
|
||||
requestBuilder.CalculateAuthKeys(bikeId),
|
||||
requestBuilder.CalculateAuthParameters(bikeId),
|
||||
UserAgent);
|
||||
|
||||
/// <summary> Updates lock state for a booked bike. </summary>
|
||||
|
@ -166,7 +167,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on updating locking state.</returns>
|
||||
public async Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
lock_state state,
|
||||
double batteryLevel,
|
||||
|
@ -185,7 +186,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Requst on booking request.</returns>
|
||||
public async Task<ReservationBookingResponse> DoBookAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Guid guid,
|
||||
double batteryPercentage,
|
||||
Uri operatorUri)
|
||||
|
@ -199,31 +200,35 @@ namespace TINK.Model.Repository
|
|||
/// <summary> Returns a bike. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="location">Geolocation of lock.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on returning request.</returns>
|
||||
public async Task<ReservationCancelReturnResponse> DoReturn(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri)
|
||||
{
|
||||
return await DoReturn(
|
||||
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
|
||||
requestBuilder.DoReturn(bikeId, location),
|
||||
requestBuilder.DoReturn(bikeId, location, smartDevice),
|
||||
UserAgent);
|
||||
}
|
||||
|
||||
/// <summary> Submits feedback to copri server. </summary>
|
||||
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on submitting feedback request.</returns>
|
||||
public async Task<SubmitFeedbackResponse> DoSubmitFeedback(
|
||||
string bikeId,
|
||||
string message,
|
||||
bool isBikeBroken,
|
||||
Uri operatorUri) =>
|
||||
await DoSubmitFeedback(
|
||||
operatorUri?.AbsoluteUri ?? m_oCopriHost.AbsoluteUri,
|
||||
requestBuilder.DoSubmitFeedback(message, isBikeBroken),
|
||||
requestBuilder.DoSubmitFeedback(bikeId, message, isBikeBroken),
|
||||
UserAgent);
|
||||
|
||||
/// <summary> Logs user in. </summary>
|
||||
|
@ -238,10 +243,10 @@ namespace TINK.Model.Repository
|
|||
{
|
||||
#if !WINDOWS_UWP
|
||||
/// Extract session cookie from response.
|
||||
string l_oResponseText = string.Empty;
|
||||
string response = string.Empty;
|
||||
try
|
||||
{
|
||||
l_oResponseText = await PostAsync(
|
||||
response = await PostAsync(
|
||||
copriHost,
|
||||
command,
|
||||
userAgent,
|
||||
|
@ -262,7 +267,7 @@ namespace TINK.Model.Repository
|
|||
throw;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<AuthorizationResponse>>(l_oResponseText)?.tinkjson;
|
||||
return CopriCallsStatic.DeserializeResponse<AuthorizationResponse>(response, (version) => new UnsupportedCopriVersionDetectedException());
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -299,7 +304,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
/// Extract session cookie from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<AuthorizationoutResponse>>(l_oLogoutResponse)?.tinkjson;
|
||||
return CopriCallsStatic.DeserializeResponse<AuthorizationoutResponse>(l_oLogoutResponse, (version) => new UnsupportedCopriVersionDetectedException());
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -317,10 +322,10 @@ namespace TINK.Model.Repository
|
|||
string userAgent = null)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
string l_oStationsAllResponse;
|
||||
string response;
|
||||
try
|
||||
{
|
||||
l_oStationsAllResponse = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
|
||||
response = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
|
||||
}
|
||||
catch (System.Exception l_oException)
|
||||
{
|
||||
|
@ -338,7 +343,9 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<StationsAllResponse>>(l_oStationsAllResponse)?.tinkjson;
|
||||
return CopriCallsStatic.DeserializeResponse(
|
||||
response,
|
||||
(version) => CopriCallsMonkeyStore.GetEmptyStationsAllResponse(version));
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -354,10 +361,10 @@ namespace TINK.Model.Repository
|
|||
string userAgent = null)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
string l_oBikesAvaialbeResponse;
|
||||
string response;
|
||||
try
|
||||
{
|
||||
l_oBikesAvaialbeResponse = await PostAsync(p_strCopriHost, l_oCommand, userAgent);
|
||||
response = await PostAsync(p_strCopriHost, l_oCommand, userAgent);
|
||||
}
|
||||
catch (System.Exception l_oException)
|
||||
{
|
||||
|
@ -375,7 +382,10 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return CopriCallsStatic.DeserializeBikesAvailableResponse(l_oBikesAvaialbeResponse);
|
||||
return CopriCallsStatic.DeserializeResponse(
|
||||
response,
|
||||
(version) => CopriCallsMonkeyStore.GetEmptyBikesAvailableResponse(version));
|
||||
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -391,10 +401,10 @@ namespace TINK.Model.Repository
|
|||
string userAgent = null)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
string l_oBikesOccupiedResponse;
|
||||
string response;
|
||||
try
|
||||
{
|
||||
l_oBikesOccupiedResponse = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
|
||||
response = await PostAsync(p_strCopriHost, p_oCommand, userAgent);
|
||||
}
|
||||
catch (System.Exception l_oException)
|
||||
{
|
||||
|
@ -412,7 +422,9 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return CopriCallsStatic.DeserializeBikesOccupiedResponse(l_oBikesOccupiedResponse);
|
||||
return CopriCallsStatic.DeserializeResponse(
|
||||
response,
|
||||
(version) => CopriCallsMonkeyStore.GetEmptyBikesReservedOccupiedResponse(version));
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -449,7 +461,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -485,7 +497,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -522,7 +534,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -555,7 +567,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -588,7 +600,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationBookingResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -621,7 +633,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(l_oBikesAvaialbeResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<ReservationCancelReturnResponse>>(l_oBikesAvaialbeResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -654,7 +666,7 @@ namespace TINK.Model.Repository
|
|||
}
|
||||
|
||||
// Extract bikes from response.
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<SubmitFeedbackResponse>>(userFeedbackResponse)?.tinkjson;
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<SubmitFeedbackResponse>>(userFeedbackResponse)?.shareejson;
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
|
@ -775,9 +787,9 @@ namespace TINK.Model.Repository
|
|||
return null;
|
||||
#endif
|
||||
}
|
||||
catch (System.Exception l_oException)
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
Log.ForContext<CopriCallsHttps>().InformationOrError("Posting command {DisplayCommand} to host {URL} failed. {Exception}.", displayCommandFunc(), uRL, l_oException);
|
||||
Log.ForContext<CopriCallsHttps>().InformationOrError("Posting command {DisplayCommand} to host {URL} failed. {Exception}.", displayCommandFunc(), uRL, exception);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
1314
TINKLib/Repository/CopriCallsMemory.cs
Normal file
1314
TINKLib/Repository/CopriCallsMemory.cs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,12 @@
|
|||
using MonkeyCache.FileStore;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Repository
|
||||
namespace TINK.Repository
|
||||
{
|
||||
public class CopriCallsMonkeyStore : ICopriCache
|
||||
{
|
||||
|
@ -18,7 +17,7 @@ namespace TINK.Model.Repository
|
|||
private IRequestBuilder requestBuilder;
|
||||
|
||||
public const string BIKESAVAILABLE = @"{
|
||||
""copri_version"" : ""3.0.0.0"",
|
||||
""copri_version"" : ""4.1.0.0"",
|
||||
""bikes"" : {},
|
||||
""response_state"" : ""OK"",
|
||||
""apiserver"" : ""https://app.tink-konstanz.de"",
|
||||
|
@ -26,26 +25,78 @@ namespace TINK.Model.Repository
|
|||
""response"" : ""bikes_available""
|
||||
}";
|
||||
|
||||
/// <summary> Gets an empty response. </summary>
|
||||
/// <param name="copriVersion">Version of empty response.</param>
|
||||
/// <returns>Response.</returns>
|
||||
public static BikesAvailableResponse GetEmptyBikesAvailableResponse(string copriVersion)
|
||||
=> JsonConvertRethrow.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE.Replace("4.1.0.0", copriVersion));
|
||||
|
||||
#if !COPRIVERSION41
|
||||
public const string BIKESOCCUPIED = @"{
|
||||
""debuglevel"" : ""1"",
|
||||
""user_id"" : """",
|
||||
""response"" : ""user_bikes_occupied"",
|
||||
""user_group"" : ""Konrad,TINK"",
|
||||
""user_group"" : [ ""Konrad"", ""TINK"" ],
|
||||
""authcookie"" : """",
|
||||
""response_state"" : ""OK"",
|
||||
""bikes_occupied"" : {},
|
||||
""copri_version"" : ""3.0.0.0"",
|
||||
""copri_version"" : ""4.1.0.0"",
|
||||
""apiserver"" : ""https://app.tink-konstanz.de""
|
||||
}";
|
||||
#endif
|
||||
|
||||
public const string STATIONS = @"{
|
||||
""apiserver"" : ""https://app.tink-konstanz.de"",
|
||||
/// <summary> Gets an empty response. </summary>
|
||||
/// <param name="copriVersion">Version of empty response.</param>
|
||||
/// <returns>Response.</returns>
|
||||
public static BikesReservedOccupiedResponse GetEmptyBikesReservedOccupiedResponse(string copriVersion)
|
||||
=> JsonConvertRethrow.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED.Replace("4.1.0.0", copriVersion));
|
||||
|
||||
#if !COPRIVERSION41
|
||||
/// <summary> Version COPRI 4.0. or earlier</summary>
|
||||
public const string STATIONSALL = @"{
|
||||
""apiserver"" : """",
|
||||
""authcookie"" : """",
|
||||
""response"" : ""stations_all"",
|
||||
""copri_version"" : ""3.0.0.0"",
|
||||
""copri_version"" : ""4.1.0.0"",
|
||||
""stations"" : {},
|
||||
""response_state"" : ""OK""
|
||||
}";
|
||||
#else
|
||||
/// <summary> Version COPRI 4.1 or later. </summary>
|
||||
public const string STATIONSALL = @"{
|
||||
""uri_primary"": """"
|
||||
""uri_operator_array"": [ ]
|
||||
""authcookie"" : """",
|
||||
""response"" : ""stations_all"",
|
||||
""copri_version"" : ""4.1.0.0"",
|
||||
""stations"" : {},
|
||||
""response_state"" : ""OK""
|
||||
}";
|
||||
#endif
|
||||
|
||||
#if !COPRIVERSION41
|
||||
/// <summary> Version COPRI 4.0. or earlier</summary>
|
||||
public const string AUTHORIZATION = @"{
|
||||
""user_group"" : [ """" ],
|
||||
""response"" : ""authorization"",
|
||||
""response_state"" : ""OK"",
|
||||
""copri_version"" : ""4.1.0.0""
|
||||
}";
|
||||
#else
|
||||
/// <summary> Version COPRI 4.0. or earlier</summary>
|
||||
public const string AUTHORIZATION = @"{
|
||||
""user_group"" : [],
|
||||
""response"" : ""authorization"",
|
||||
""response_state"" : ""OK"",
|
||||
""copri_version"" : ""4.1.0.0""
|
||||
}";
|
||||
#endif
|
||||
|
||||
/// <summary> Gets an empty response. </summary>
|
||||
/// <param name="copriVersion">Version of empty response.</param>
|
||||
/// <returns>Response.</returns>
|
||||
public static StationsAllResponse GetEmptyStationsAllResponse(string copriVersion)
|
||||
=> JsonConvertRethrow.DeserializeObject<StationsAllResponse>(STATIONSALL.Replace("4.1.0.0", copriVersion));
|
||||
|
||||
/// <summary>
|
||||
/// Holds the seconds after which station and bikes info is considered to be invalid.
|
||||
|
@ -79,53 +130,57 @@ namespace TINK.Model.Repository
|
|||
// Ensure that store holds valid entries.
|
||||
if (!Barrel.Current.Exists(requestBuilder.GetBikesAvailable()))
|
||||
{
|
||||
AddToCache(JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), new TimeSpan(0));
|
||||
AddToCache(JsonConvertRethrow.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), new TimeSpan(0));
|
||||
}
|
||||
|
||||
// Do not query bikes occupied if no user is logged in (leads to not implemented exception)
|
||||
if (!string.IsNullOrEmpty(sessionCookie) && !Barrel.Current.Exists(requestBuilder.GetBikesOccupied()))
|
||||
{
|
||||
AddToCache(JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED), new TimeSpan(0));
|
||||
AddToCache(JsonConvertRethrow.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED), new TimeSpan(0));
|
||||
}
|
||||
|
||||
if (!Barrel.Current.Exists(requestBuilder.GetStations()))
|
||||
{
|
||||
AddToCache(JsonConvert.DeserializeObject<StationsAllResponse>(STATIONS), new TimeSpan(0));
|
||||
AddToCache(JsonConvertRethrow.DeserializeObject<StationsAllResponse>(STATIONSALL), new TimeSpan(0));
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ReservationBookingResponse> DoReserveAsync(int bikeId, Uri operatorUri)
|
||||
public Task<ReservationBookingResponse> DoReserveAsync(string bikeId, Uri operatorUri)
|
||||
{
|
||||
throw new System.Exception("Reservierung im Offlinemodus nicht möglich!");
|
||||
}
|
||||
|
||||
public Task<ReservationCancelReturnResponse> DoCancelReservationAsync(int p_iBikeId, Uri operatorUri)
|
||||
public Task<ReservationCancelReturnResponse> DoCancelReservationAsync(string bikeId, Uri operatorUri)
|
||||
{
|
||||
throw new System.Exception("Abbrechen einer Reservierung im Offlinemodus nicht möglich!");
|
||||
}
|
||||
|
||||
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(int bikeId, Uri operatorUri)
|
||||
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(string bikeId, Uri operatorUri)
|
||||
=> throw new System.Exception("Schlosssuche im Offlinemodus nicht möglich!");
|
||||
|
||||
public Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
lock_state state,
|
||||
double batteryLevel,
|
||||
Uri operatorUri)
|
||||
=> throw new System.Exception("Aktualisierung des Schlossstatuses im Offlinemodus nicht möglich!");
|
||||
|
||||
public Task<ReservationBookingResponse> DoBookAsync(int bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
public Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
{
|
||||
throw new System.Exception("Buchung im Offlinemodus nicht möglich!");
|
||||
}
|
||||
|
||||
public Task<ReservationCancelReturnResponse> DoReturn(int bikeId, LocationDto geolocation, Uri operatorUri)
|
||||
public Task<ReservationCancelReturnResponse> DoReturn(
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri)
|
||||
{
|
||||
throw new System.Exception("Rückgabe im Offlinemodus nicht möglich!");
|
||||
}
|
||||
|
||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string message, bool isBikeBroken, Uri operatorUri) =>
|
||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, string message, bool isBikeBroken, Uri operatorUri) =>
|
||||
throw new System.Exception("Übermittlung von Feedback im Offlinemodus nicht möglich!");
|
||||
|
||||
public Task<AuthorizationResponse> DoAuthorizationAsync(string p_strMailAddress, string p_strPassword, string p_strDeviceId)
|
||||
|
@ -207,7 +262,7 @@ namespace TINK.Model.Repository
|
|||
{
|
||||
Barrel.Current.Add(
|
||||
requestBuilder.GetStations(),
|
||||
JsonConvert.SerializeObject(stations),
|
||||
JsonConvertRethrow.SerializeObject(stations),
|
||||
expiresAfter);
|
||||
}
|
||||
}
|
||||
|
@ -239,8 +294,8 @@ namespace TINK.Model.Repository
|
|||
lock (monkeyLock)
|
||||
{
|
||||
Barrel.Current.Add(
|
||||
requestBuilder.GetBikesAvailable(),
|
||||
JsonConvert.SerializeObject(bikes),
|
||||
requestBuilder.GetBikesAvailable(),
|
||||
JsonConvertRethrow.SerializeObject(bikes),
|
||||
expiresAfter);
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +328,7 @@ namespace TINK.Model.Repository
|
|||
{
|
||||
Barrel.Current.Add(
|
||||
requestBuilder.GetBikesOccupied(),
|
||||
JsonConvert.SerializeObject(bikes),
|
||||
JsonConvertRethrow.SerializeObject(bikes),
|
||||
expiresAfter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,65 @@
|
|||
using TINK.Model.Repository.Response;
|
||||
using Serilog;
|
||||
using System;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Repository
|
||||
namespace TINK.Repository
|
||||
{
|
||||
public static class CopriCallsStatic
|
||||
{
|
||||
/// <summary>
|
||||
/// Deserializes JSON from response string.
|
||||
/// </summary>
|
||||
/// <param name="p_strResponse">Response to deserialize.</param>
|
||||
/// <returns></returns>
|
||||
public static BikesAvailableResponse DeserializeBikesAvailableResponse(string p_strResponse)
|
||||
#if !USCSHARP9
|
||||
private static Version UNSUPPORTEDFUTURECOPRIVERSIONLOWER = new Version(4, 1);
|
||||
#else
|
||||
private static Version UNSUPPORTEDFUTURECOPRIVERSIONLOWER = new(4, 1);
|
||||
#endif
|
||||
|
||||
#if !USCSHARP9
|
||||
private static Version UNSUPPORTEDFUTURECOPRIVERSIONUPPER = new Version(4, 2);
|
||||
#else
|
||||
private static Version UNSUPPORTEDFUTURECOPRIVERSIONUPPER = new(4, 2);
|
||||
#endif
|
||||
public static Version UnsupportedVersionLower => UNSUPPORTEDFUTURECOPRIVERSIONLOWER;
|
||||
|
||||
public static Version UnsupportedVersionUpper => UNSUPPORTEDFUTURECOPRIVERSIONUPPER;
|
||||
|
||||
/// <summary> Deserializes reponse JSON if response is of supported version or provides default response otherwise. </summary>
|
||||
/// <typeparam name="T">Type of response object.</typeparam>
|
||||
/// <param name="response">Response JSON.</param>
|
||||
/// <param name="emptyResponseFactory">Factory providing default delegate.</param>
|
||||
/// <returns>Response object.</returns>
|
||||
public static T DeserializeResponse<T>(this string response, Func<string, T> emptyResponseFactory) where T: class
|
||||
{
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<BikesAvailableResponse>>(p_strResponse)?.tinkjson;
|
||||
// Get COPRI version from respone.
|
||||
var bikeInfoBase = JsonConvertRethrow.DeserializeObject<VersionindependentResponse>(response)?.shareejson;
|
||||
|
||||
if (bikeInfoBase.GetCopriVersion() < UNSUPPORTEDFUTURECOPRIVERSIONLOWER
|
||||
|| bikeInfoBase.GetCopriVersion() >= UNSUPPORTEDFUTURECOPRIVERSIONUPPER)
|
||||
{
|
||||
return emptyResponseFactory?.Invoke(bikeInfoBase.copri_version) ?? null;
|
||||
}
|
||||
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<T>>(response)?.shareejson;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes JSON from response string.
|
||||
/// </summary>
|
||||
/// <param name="p_strResponse">Response to deserialize.</param>
|
||||
/// <returns></returns>
|
||||
public static BikesReservedOccupiedResponse DeserializeBikesOccupiedResponse(string p_strResponse)
|
||||
/// <summary> Deserializes reponse JSON if response is of supported version or throws an exception. </summary>
|
||||
/// <typeparam name="T">Type of response object.</typeparam>
|
||||
/// <param name="response">Response JSON.</param>
|
||||
/// <param name="unsupportedVersionExectpion">Exception to fire.</param>
|
||||
/// <returns>Response object.</returns>
|
||||
public static T DeserializeResponse<T>(this string response, Func<string, System.Exception> unsupportedVersionExectpion = null) where T : class
|
||||
{
|
||||
return JsonConvert.DeserializeObject<ResponseContainer<BikesReservedOccupiedResponse>>(p_strResponse)?.tinkjson;
|
||||
|
||||
// Get COPRI version from respone.
|
||||
var bikeInfoBase = JsonConvertRethrow.DeserializeObject<VersionindependentResponse>(response)?.shareejson;
|
||||
|
||||
if (bikeInfoBase.GetCopriVersion() < UNSUPPORTEDFUTURECOPRIVERSIONLOWER
|
||||
|| bikeInfoBase.GetCopriVersion() >= UNSUPPORTEDFUTURECOPRIVERSIONUPPER)
|
||||
{
|
||||
Log.Error($"Unsupported copri version {bikeInfoBase.copri_version} detected on attempt to log in.");
|
||||
throw unsupportedVersionExectpion?.Invoke(bikeInfoBase.copri_version) ?? new System.Exception($"Unsupported COPRI version {bikeInfoBase.copri_version} detected.");
|
||||
}
|
||||
|
||||
return JsonConvertRethrow.DeserializeObject<ResponseContainer<T>>(response)?.shareejson;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Is fired with reqest used a cookie which is not defined.
|
||||
|
@ -15,11 +15,25 @@
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether authcookie is defined or not.
|
||||
/// </summary>
|
||||
/// <param name="reponse">Response to check</param>
|
||||
/// <param name="actionText">Text holding contectin in which authcookie is checked.</param>
|
||||
/// <param name="exception">Exception thrown if cookie is not defined.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAuthcookieNotDefined(
|
||||
Response.ResponseBase reponse,
|
||||
string actionText,
|
||||
out AuthcookieNotDefinedException exception)
|
||||
{
|
||||
if (reponse == null || reponse.response_state == null)
|
||||
{
|
||||
// Empty response or response withoud response state is no authcookie not defined exeception.
|
||||
exception = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reponse.response_state.ToUpper().Contains(AUTH_FAILURE_QUERY_AUTHCOOKIENOTDEFIED.ToUpper())
|
||||
&& !reponse.response_state.ToUpper().Contains(AUTH_FAILURE_BOOK_AUTICOOKIENOTDEFIED.ToUpper())
|
||||
&& !reponse.response_state.ToUpper().Contains(AUTH_FAILURE_BIKESOCCUPIED_AUTICOOKIENOTDEFIED.ToUpper())
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class InvalidAuthorizationResponseException : InvalidResponseException<Response.ResponseBase>
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
/// <summary> Handles booking request which fail due to too many bikes requested/ booked.</summary>
|
||||
public class BookingDeclinedException : InvalidResponseException
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class CallNotRequiredException : System.Exception
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class CommunicationException : System.Exception
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using TINK.Model.Repository.Exception;
|
||||
|
||||
namespace TINK.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class DeserializationException : CommunicationException
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class InvalidResponseException<T> : InvalidResponseException
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using TINK.Model.Repository.Exception;
|
||||
|
||||
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class NoGPSDataException : InvalidResponseException
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class NotAtStationException : InvalidResponseException
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class UnsupportedCopriVersionDetectedException : System.Exception
|
||||
{
|
||||
public UnsupportedCopriVersionDetectedException() : base("Unsupported app version detected.")
|
||||
{}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class WebConnectFailureException : CommunicationException
|
||||
{
|
||||
|
|
|
@ -1,42 +1,53 @@
|
|||
using System.Net;
|
||||
|
||||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public static class WebExceptionHelper
|
||||
{
|
||||
/// <summary> Gets if a exception is caused by an error connecting to copri (LAN or mobile data off/ not reachable, proxy, ...).</summary>
|
||||
/// <param name="p_oException">Expection to check.</param>
|
||||
/// <param name="exception">Expection to check.</param>
|
||||
/// <returns>True if exception if caused by an connection error. </returns>
|
||||
public static bool GetIsConnectFailureException(this System.Exception p_oException)
|
||||
public static bool GetIsConnectFailureException(this System.Exception exception)
|
||||
{
|
||||
var l_oException = p_oException as WebException;
|
||||
if (l_oException == null)
|
||||
#if !USCSHARP9
|
||||
if (!(exception is WebException webException))
|
||||
#else
|
||||
if (exception is not WebException webException)
|
||||
#endif
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l_oException.Status == WebExceptionStatus.ConnectFailure // Happens if WLAN and mobile data is off/ Router denies internet access/ ...
|
||||
|| l_oException.Status == WebExceptionStatus.NameResolutionFailure // Happens sometimes when not WLAN and no mobil connection are available (bad connection in lift).
|
||||
|| l_oException.Status == WebExceptionStatus.ReceiveFailure; // Happened when modile was connected to WLAN
|
||||
return webException.Status == WebExceptionStatus.ConnectFailure // Happens if WLAN and mobile data is off/ Router denies internet access/ ...
|
||||
|| webException.Status == WebExceptionStatus.NameResolutionFailure // Happens sometimes when not WLAN and no mobil connection are available (bad connection in lift).
|
||||
|| webException.Status == WebExceptionStatus.ReceiveFailure; // Happened when modile was connected to WLAN
|
||||
}
|
||||
|
||||
/// <summary> Gets if a exception is caused by clicking too fast.</summary>
|
||||
/// <param name="p_oException">Expection to check.</param>
|
||||
/// <param name="exception">Expection to check.</param>
|
||||
/// <returns>True if exception if caused by a fast click sequence. </returns>
|
||||
public static bool GetIsForbiddenException(this System.Exception p_oException)
|
||||
public static bool GetIsForbiddenException(this System.Exception exception)
|
||||
{
|
||||
if (!(p_oException is WebException l_oException))
|
||||
#if !USCSHARP9
|
||||
if (!(exception is WebException webException))
|
||||
#else
|
||||
if (exception is not WebException webException)
|
||||
#endif
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(l_oException?.Response is HttpWebResponse l_oResponse))
|
||||
#if !USCSHARP9
|
||||
if (!(webException?.Response is HttpWebResponse response))
|
||||
#else
|
||||
if (webException?.Response is not HttpWebResponse response)
|
||||
#endif
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return l_oException.Status == WebExceptionStatus.ProtocolError
|
||||
&& l_oResponse.StatusCode == HttpStatusCode.Forbidden;
|
||||
return webException.Status == WebExceptionStatus.ProtocolError
|
||||
&& response.StatusCode == HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace TINK.Model.Repository.Exception
|
||||
namespace TINK.Repository.Exception
|
||||
{
|
||||
public class WebForbiddenException : CommunicationException
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Repository
|
||||
namespace TINK.Repository
|
||||
{
|
||||
/// <summary> Interface to communicate with copri server.</summary>
|
||||
public interface ICopriServerBase
|
||||
|
@ -28,7 +28,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on reserving request.</returns>
|
||||
Task<ReservationBookingResponse> DoReserveAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri);
|
||||
|
||||
/// <summary> Cancels reservation of bik. </summary>
|
||||
|
@ -36,7 +36,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on cancel reservation request.</returns>
|
||||
Task<ReservationCancelReturnResponse> DoCancelReservationAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri);
|
||||
|
||||
/// <summary> Get authentication keys. </summary>
|
||||
|
@ -44,7 +44,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response holding authentication keys.</returns>
|
||||
Task<ReservationBookingResponse> CalculateAuthKeysAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Uri operatorUri);
|
||||
|
||||
/// <summary> Updates COPRI lock state for a booked bike. </summary>
|
||||
|
@ -55,7 +55,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on updating locking state.</returns>
|
||||
Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
lock_state state,
|
||||
double batteryPercentage,
|
||||
|
@ -68,7 +68,7 @@ namespace TINK.Model.Repository
|
|||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on booking request.</returns>
|
||||
Task<ReservationBookingResponse> DoBookAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
Guid guid,
|
||||
double batteryPercentage,
|
||||
Uri operatorUri);
|
||||
|
@ -76,19 +76,23 @@ namespace TINK.Model.Repository
|
|||
/// <summary> Returns a bike. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="location">Geolocation of lock.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
|
||||
/// <returns>Response on returning request.</returns>
|
||||
Task<ReservationCancelReturnResponse> DoReturn(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri);
|
||||
|
||||
/// <summary>
|
||||
/// Submits feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to submit feedback for.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
Task<SubmitFeedbackResponse> DoSubmitFeedback(
|
||||
string bikeId,
|
||||
string message,
|
||||
bool isBikeBroken,
|
||||
Uri operatorUri);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.Model.Repository.Request
|
||||
namespace TINK.Repository.Request
|
||||
{
|
||||
/// <summary> Defines members to create requests.</summary>
|
||||
public interface IRequestBuilder
|
||||
|
@ -41,17 +42,17 @@ namespace TINK.Model.Repository.Request
|
|||
/// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
|
||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
||||
/// <returns>Requst to reserve bike.</returns>
|
||||
string DoReserve(int bikeId);
|
||||
string DoReserve(string bikeId);
|
||||
|
||||
/// <summary> Gets request to cancel reservation. </summary>
|
||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
||||
/// <returns>Requst on cancel booking request.</returns>
|
||||
string DoCancelReservation(int bikeId);
|
||||
string DoCancelReservation(string bikeId);
|
||||
|
||||
/// <summary> Request to get keys. </summary>
|
||||
/// <param name="bikeId">Id of the bike to get keys for.</param>
|
||||
/// <returns>Request to get keys.</returns>
|
||||
string CalculateAuthKeys(int bikeId);
|
||||
string CalculateAuthParameters(string bikeId);
|
||||
|
||||
/// <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>
|
||||
|
@ -59,7 +60,7 @@ namespace TINK.Model.Repository.Request
|
|||
/// <param name="state">New locking state.</param>
|
||||
/// <returns>Request to update locking state.</returns>
|
||||
string UpateLockingState(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
lock_state state,
|
||||
double batteryPercentage);
|
||||
|
@ -69,20 +70,21 @@ namespace TINK.Model.Repository.Request
|
|||
/// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
|
||||
/// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
|
||||
/// <returns>Request to booking bike.</returns>
|
||||
string DoBook(int bikeId, Guid guid, double batteryPercentage);
|
||||
string DoBook(string bikeId, Guid guid, double batteryPercentage);
|
||||
|
||||
/// <summary> Gets request for returning the bike. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <returns>Requst on returning request.</returns>
|
||||
string DoReturn(int bikeId, LocationDto location);
|
||||
string DoReturn(string bikeId, LocationDto location, ISmartDevice smartDevice);
|
||||
|
||||
/// <summary>
|
||||
/// Gets request for submiting feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
string DoSubmitFeedback(string message = null, bool isBikeBroken = false);
|
||||
string DoSubmitFeedback(string bikeId, string message = null, bool isBikeBroken = false);
|
||||
}
|
||||
|
||||
/// <summary> Copri locking states</summary>
|
||||
|
@ -92,6 +94,7 @@ namespace TINK.Model.Repository.Request
|
|||
unlocked
|
||||
}
|
||||
|
||||
/// <summary> Holds lockation info.</summary>
|
||||
public class LocationDto
|
||||
{
|
||||
public double Latitude { get; private set; }
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository.Exception;
|
||||
|
||||
namespace TINK.Model.Repository.Request
|
||||
namespace TINK.Repository.Request
|
||||
{
|
||||
/// <summary> Creates requests if no user is logged in.</summary>
|
||||
public class RequestBuilder : IRequestBuilder
|
||||
|
@ -80,32 +81,34 @@ namespace TINK.Model.Repository.Request
|
|||
public string GetBikesOccupied() => throw new NotSupportedException();
|
||||
|
||||
/// <summary> Gets booking request response. </summary>
|
||||
/// <param name="p_iBikeId">Id of the bike to book.</param>
|
||||
/// <param name="bikeId">Id of the bike to book.</param>
|
||||
/// <returns>Response on booking request.</returns>
|
||||
public string DoReserve(int p_iBikeId) => throw new NotSupportedException();
|
||||
public string DoReserve(string bikeId) => throw new NotSupportedException();
|
||||
|
||||
/// <summary> Gets cancel booking request response. </summary>
|
||||
/// <param name="p_iBikeId">Id of the bike to book.</param>
|
||||
/// <returns>Response on cancel booking request.</returns>
|
||||
public string DoCancelReservation(int p_iBikeId) => throw new NotSupportedException();
|
||||
public string DoCancelReservation(string p_iBikeId) => throw new NotSupportedException();
|
||||
|
||||
/// <summary> Request to calculate authentication keys. </summary>
|
||||
/// <param name="bikeId">Id of the bike to get keys for.</param>
|
||||
/// <returns>Response on request.</returns>
|
||||
public string CalculateAuthKeys(int bikeId) => throw new NotSupportedException();
|
||||
public string CalculateAuthParameters(string bikeId) => throw new NotSupportedException();
|
||||
|
||||
public string UpateLockingState(int bikeId, LocationDto geolocation, lock_state state, double batteryPercentage)
|
||||
public string UpateLockingState(string bikeId, LocationDto geolocation, lock_state state, double batteryPercentage)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public string DoBook(int bikeId, Guid guid, double batteryPercentage) => throw new NotSupportedException();
|
||||
public string DoBook(string bikeId, Guid guid, double batteryPercentage) => throw new NotSupportedException();
|
||||
|
||||
public string DoReturn(int bikeId, LocationDto geolocation) => throw new NotSupportedException();
|
||||
public string DoReturn(string bikeId, LocationDto geolocation, ISmartDevice smartDevice) => throw new NotSupportedException();
|
||||
|
||||
/// <summary> Gets submit feedback request. </summary>
|
||||
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
/// <returns>Submit feedback request.</returns>
|
||||
public string DoSubmitFeedback(
|
||||
string bikeId,
|
||||
string message = null,
|
||||
bool isBikeBroken = false) => throw new NotSupportedException();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository.Exception;
|
||||
|
||||
namespace TINK.Model.Repository.Request
|
||||
namespace TINK.Repository.Request
|
||||
{
|
||||
/// <summary> Creates requests if a user is logged in.</summary>
|
||||
public class RequestBuilderLoggedIn : IRequestBuilder
|
||||
|
@ -75,21 +76,21 @@ namespace TINK.Model.Repository.Request
|
|||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
||||
/// <returns>Requst to reserve bike.</returns>
|
||||
public string DoReserve(int bikeId)
|
||||
public string DoReserve(string bikeId)
|
||||
=> $"request=booking_request&bike={bikeId}&authcookie={SessionCookie}{MerchantId}";
|
||||
|
||||
/// <summary> Gets request to cancel reservation. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
||||
/// <returns>Requst on cancel booking request.</returns>
|
||||
public string DoCancelReservation(int p_iBikeId)
|
||||
public string DoCancelReservation(string p_iBikeId)
|
||||
=> $"request=booking_cancel&bike={p_iBikeId}&authcookie={SessionCookie}{MerchantId}";
|
||||
|
||||
/// <summary> Request to get keys. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to get keys for.</param>
|
||||
/// <returns>Request to get keys.</returns>
|
||||
public string CalculateAuthKeys(int bikeId)
|
||||
public string CalculateAuthParameters(string bikeId)
|
||||
=> $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&genkey=1";
|
||||
|
||||
/// <summary> Gets the request for updating lock state for a booked bike. </summary>
|
||||
|
@ -97,9 +98,9 @@ namespace TINK.Model.Repository.Request
|
|||
/// <param name="bikeId">Id of the bike to update locking state for.</param>
|
||||
/// <param name="state">New locking state.</param>
|
||||
/// <returns>Request to update locking state.</returns>
|
||||
public string UpateLockingState(int bikeId, LocationDto geolocation, lock_state state, double batteryPercentage)
|
||||
public string UpateLockingState(string bikeId, LocationDto geolocation, lock_state state, double batteryPercentage)
|
||||
{
|
||||
return $"request=booking_update&bike={bikeId}{GetLocationKey(geolocation)}&lock_state={state}{GetBatteryPercentageKey(batteryPercentage)}&authcookie={SessionCookie}{MerchantId}";
|
||||
return $"request=booking_update&bike={bikeId}{GetLocationParameters(geolocation)}&lock_state={state}{GetBatteryPercentageParameters(batteryPercentage)}&authcookie={SessionCookie}{MerchantId}";
|
||||
}
|
||||
|
||||
/// <summary> Gets booking request request (synonym: booking == renting == mieten). </summary>
|
||||
|
@ -108,55 +109,65 @@ namespace TINK.Model.Repository.Request
|
|||
/// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
|
||||
/// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
|
||||
/// <returns>Request to booking bike.</returns>
|
||||
public string DoBook(int bikeId, Guid guid, double batteryPercentage)
|
||||
=> $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&Ilockit_GUID={guid}&state=occupied&lock_state=unlocked{GetBatteryPercentageKey(batteryPercentage)}";
|
||||
public string DoBook(string bikeId, Guid guid, double batteryPercentage)
|
||||
=> $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&Ilockit_GUID={guid}&state=occupied&lock_state=unlocked{GetBatteryPercentageParameters(batteryPercentage)}";
|
||||
|
||||
/// <summary> Gets request for returning the bike. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of bike to return.</param>
|
||||
/// <param name="geolocation">Geolocation of lock when returning bike.</param>
|
||||
/// <returns>Requst on returning request.</returns>
|
||||
public string DoReturn(int bikeId, LocationDto geolocation)
|
||||
public string DoReturn(string bikeId, LocationDto geolocation, ISmartDevice smartDevice)
|
||||
{
|
||||
return $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&state=available{GetLocationKey(geolocation)}&lock_state=locked";
|
||||
return $"request=booking_update" +
|
||||
$"&bike={bikeId}" +
|
||||
$"&authcookie={SessionCookie}{MerchantId}" +
|
||||
$"&state=available" +
|
||||
$"{GetLocationParameters(geolocation)}" +
|
||||
$"&lock_state=locked" +
|
||||
$"{GetSmartDeviceParameters(smartDevice)}";
|
||||
}
|
||||
|
||||
/// <summary> Gets submit feedback request. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
/// <returns>Submit feedback request.</returns>
|
||||
public string DoSubmitFeedback(
|
||||
string bikeId,
|
||||
string message = null,
|
||||
bool isBikeBroken = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message) && !isBikeBroken)
|
||||
{
|
||||
// User just acknoledged biked returned message.
|
||||
return "request=user_feedback";
|
||||
return $"request=user_feedback&bike={bikeId}&authcookie={SessionCookie}{MerchantId}";
|
||||
}
|
||||
|
||||
if (isBikeBroken == false)
|
||||
{
|
||||
// Bike is ok and user entered a feedback message.
|
||||
return $"request=user_feedback&message={WebUtility.UrlEncode(message)}";
|
||||
return $"request=user_feedback&bike={bikeId}&message={WebUtility.UrlEncode(message)}&authcookie={SessionCookie}{MerchantId}";
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
// User just marked bike as broken without comment.
|
||||
return $"request=user_feedback&bike_broken=1";
|
||||
return $"request=user_feedback&bike={bikeId}&bike_broken=1&authcookie={SessionCookie}{MerchantId}";
|
||||
}
|
||||
|
||||
// Bike is marked as broken and user added a comment.
|
||||
return $"request=user_feedback&bike_broken=1&message={WebUtility.UrlEncode(message)}";
|
||||
return $"request=user_feedback&bike={bikeId}&bike_broken=1&message={WebUtility.UrlEncode(message)}&authcookie={SessionCookie}{MerchantId}";
|
||||
}
|
||||
|
||||
private string GetBatteryPercentageKey(double batteryPercentage) => !double.IsNaN(batteryPercentage)
|
||||
private string GetBatteryPercentageParameters(double batteryPercentage) => !double.IsNaN(batteryPercentage)
|
||||
? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}"
|
||||
: string.Empty;
|
||||
|
||||
private string GetLocationKey(LocationDto geolocation)
|
||||
/// <summary> Gets the geolocation parameter. </summary>
|
||||
/// <param name="geolocation">Geolocation or null.</param>
|
||||
private string GetLocationParameters(LocationDto geolocation)
|
||||
{
|
||||
if (geolocation == null)
|
||||
return string.Empty;
|
||||
|
@ -166,5 +177,16 @@ namespace TINK.Model.Repository.Request
|
|||
|
||||
return $"&gps={geolocation.Latitude.ToString(CultureInfo.InvariantCulture)},{geolocation.Longitude.ToString(CultureInfo.InvariantCulture)}&gps_accuracy={geolocation.Accuracy.Value.ToString(CultureInfo.InvariantCulture)}&gps_age={geolocation.Age.TotalSeconds}";
|
||||
}
|
||||
|
||||
/// <summary> Gets the geolocation parameter. </summary>
|
||||
/// <param name="geolocation">Geolocation or null.</param>
|
||||
private string GetSmartDeviceParameters(ISmartDevice smartDevice)
|
||||
=> smartDevice != null
|
||||
? $"{(!string.IsNullOrEmpty(smartDevice.Manufacturer) ? $"&user_device_manufaturer={smartDevice.Manufacturer})" : string.Empty)}" +
|
||||
$"{(!string.IsNullOrEmpty(smartDevice.Model) ? $"&user_device_model={smartDevice.Model}" : string.Empty)}" +
|
||||
$"{(!string.IsNullOrEmpty(smartDevice.PlatformText) ? $"&user_device_platform={smartDevice.PlatformText}" : string.Empty)}" +
|
||||
$"{(!string.IsNullOrEmpty(smartDevice.VersionText) ? $"&user_device_version={smartDevice.VersionText}" : string.Empty)}" +
|
||||
$"{(!string.IsNullOrEmpty(smartDevice.Identifier) ? $"&user_device_id={smartDevice.Identifier}" : string.Empty)}"
|
||||
: string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class AuthorizationResponse : ResponseBase
|
||||
|
@ -10,6 +10,6 @@ namespace TINK.Model.Repository.Response
|
|||
|
||||
/// <summary> Holds the group of the bike (TINK, Konrad, ...).</summary>
|
||||
[DataMember]
|
||||
public string user_group { get; private set; }
|
||||
public string[] user_group { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class AuthorizationoutResponse : ResponseBase
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class BikeInfoAvailable : BikeInfoBase
|
||||
|
@ -9,7 +9,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// Position of the bike.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string gps { get; private set; }
|
||||
public GpsInfo gps { get; private set; }
|
||||
|
||||
[DataMember]
|
||||
/// <summary> Full advertisement name.</summary>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds info about a single bike.
|
||||
|
@ -13,13 +12,13 @@ namespace TINK.Model.Repository.Response
|
|||
/// Id of the bike.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int bike { get; private set; }
|
||||
public string bike { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id of the station.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int? station { get; private set; }
|
||||
public string station { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the localized (german) description of the bike.
|
||||
|
@ -32,7 +31,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// Copri returns values "TINK", "Konrad".
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public string bike_group { get; private set; }
|
||||
public string[] bike_group { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rental state.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class BikeInfoReservedOrBooked : BikeInfoAvailable
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the information about all bikes and is used for deserialization of copri answer.
|
||||
|
@ -13,6 +13,6 @@ namespace TINK.Model.Repository.Response
|
|||
/// Dictionary of bikes.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<int, BikeInfoAvailable> bikes { get; private set; }
|
||||
public Dictionary<string, BikeInfoAvailable> bikes { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
public class BikesReservedOccupiedResponse : ResponseBase
|
||||
{
|
||||
|
@ -9,6 +9,6 @@ namespace TINK.Model.Repository.Response
|
|||
/// Dictionary of bikes.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<int, BikeInfoReservedOrBooked> bikes_occupied { get; private set; }
|
||||
public Dictionary<string, BikeInfoReservedOrBooked> bikes_occupied { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
11
TINKLib/Repository/Response/CopriVersion.cs
Normal file
11
TINKLib/Repository/Response/CopriVersion.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class CopriVersion
|
||||
{
|
||||
[DataMember]
|
||||
public string copri_version { get; private set; }
|
||||
}
|
||||
}
|
23
TINKLib/Repository/Response/GpsInfo.cs
Normal file
23
TINKLib/Repository/Response/GpsInfo.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds info about a single bike.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public class GpsInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Latitude position of the bike.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string latitude { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Longitude position of the bike.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string longitude { get; private set; }
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
public static class JsonConvert
|
||||
public static class JsonConvertRethrow
|
||||
{
|
||||
/// <summary>
|
||||
/// Deserializes COPRI responses in a consitent way for entire app.
|
|
@ -1,6 +1,6 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the information about a booking request and is used for deserialization of copri answer.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the information about a cancel booking request and is used for deserialization of copri answer.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class ResponseBase
|
||||
public class ResponseBase : CopriVersion
|
||||
{
|
||||
[DataMember]
|
||||
public string response_state { get; private set; }
|
||||
|
@ -17,9 +17,6 @@ namespace TINK.Model.Repository.Response
|
|||
[DataMember]
|
||||
public string authcookie { get; private set; }
|
||||
|
||||
[DataMember]
|
||||
public string copri_version { get; private set; }
|
||||
|
||||
/// <summary> Textual description of response. </summary>
|
||||
public new string ToString()
|
||||
{
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class ResponseContainer<T>
|
||||
{
|
||||
[DataMember]
|
||||
public T tinkjson { get; private set; }
|
||||
public T shareejson { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Serializes object to string.
|
||||
|
@ -14,12 +14,12 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (tinkjson == null)
|
||||
if (shareejson == null)
|
||||
{
|
||||
return "Response container does not hold no entry.";
|
||||
}
|
||||
|
||||
return tinkjson.ToString();
|
||||
return shareejson.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System.Linq;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.MultilingualResources;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.MultilingualResources;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
public static class ResponseHelper
|
||||
{
|
||||
|
@ -83,7 +82,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns></returns>
|
||||
public static BikeInfoReservedOrBooked GetIsReserveResponseOk(
|
||||
this ReservationBookingResponse bookingResponse,
|
||||
int bikeId)
|
||||
string bikeId)
|
||||
{
|
||||
GetIsResponseOk(bookingResponse, string.Format(AppResources.ExceptionTextReservationBikeFailedGeneral, bikeId));
|
||||
|
||||
|
@ -111,7 +110,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns></returns>
|
||||
public static BikeInfoReservedOrBooked GetIsBookingResponseOk(
|
||||
this ReservationBookingResponse bookingResponse,
|
||||
int bikeId)
|
||||
string bikeId)
|
||||
{
|
||||
GetIsResponseOk(bookingResponse, string.Format(AppResources.ExceptionTextRentingBikeFailedGeneral, bikeId));
|
||||
|
||||
|
@ -134,7 +133,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns>Verified response.</returns>
|
||||
public static T GetIsResponseOk<T>(this T response, string textOfAction) where T : ResponseBase
|
||||
{
|
||||
if (response == null)
|
||||
if (response == null || response.response_state == null)
|
||||
{
|
||||
throw new InvalidResponseException<T>(textOfAction, null);
|
||||
}
|
||||
|
@ -161,7 +160,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns>Verified response.</returns>
|
||||
public static ReservationCancelReturnResponse GetIsCancelReservationResponseOk(
|
||||
this ReservationCancelReturnResponse cancelBookingResponse,
|
||||
int bikeId)
|
||||
string bikeId)
|
||||
{
|
||||
GetIsResponseOk<ResponseBase>(cancelBookingResponse, BIKES_CANCELREQUEST_ACTIONTEXT);
|
||||
|
||||
|
@ -184,7 +183,7 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns>Verified response.</returns>
|
||||
public static ReservationCancelReturnResponse GetIsReturnBikeResponseOk(
|
||||
this ReservationCancelReturnResponse returnBikeResponse,
|
||||
int bikeId)
|
||||
string bikeId)
|
||||
{
|
||||
// Check if bike is at station.
|
||||
if (NotAtStationException.IsNotAtStation(returnBikeResponse.response_state.ToUpper(), out NotAtStationException notAtStationException))
|
||||
|
@ -219,22 +218,8 @@ namespace TINK.Model.Repository.Response
|
|||
/// <returns></returns>
|
||||
public static BikesReservedOccupiedResponse GetBikesOccupiedNone(string p_strSesstionCookie = null)
|
||||
{
|
||||
var l_oJson = BIKES_OCCUPIED_REQUEST_NONE_FILE.Replace(@"""authcookie"": """"", @"""authcookie"": """ + (p_strSesstionCookie ?? string.Empty) + @"""");
|
||||
return CopriCallsStatic.DeserializeBikesOccupiedResponse(l_oJson);
|
||||
var l_oJson = CopriCallsMonkeyStore.BIKESOCCUPIED.Replace(@"""authcookie"": """"", @"""authcookie"": """ + (p_strSesstionCookie ?? string.Empty) + @"""");
|
||||
return CopriCallsStatic.DeserializeResponse(@"{ ""shareejson"" : " + l_oJson + "}", (version) => new BikesReservedOccupiedResponse());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds an empty bikes occupied response.
|
||||
/// </summary>
|
||||
private const string BIKES_OCCUPIED_REQUEST_NONE_FILE = @"
|
||||
{
|
||||
""tinkjson"": {
|
||||
""response_state"": ""OK"",
|
||||
""bikes_occupied"": { },
|
||||
""authcookie"": """",
|
||||
""response"": ""user_bikes_occupied"",
|
||||
""apiserver"": ""https://tinkwwp.copri-bike.de""
|
||||
}
|
||||
}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Model.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the information about all stations and is used for deserialization of copri answer.
|
||||
|
@ -19,10 +19,10 @@ namespace TINK.Model.Repository.Response
|
|||
/// Unique id of the station.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public int station { get; private set; }
|
||||
public string station { get; private set; }
|
||||
|
||||
[DataMember]
|
||||
public string station_group { get; private set; }
|
||||
public string[] station_group { get; private set; }
|
||||
|
||||
[DataMember]
|
||||
public string description { get; private set; }
|
||||
|
@ -31,13 +31,13 @@ namespace TINK.Model.Repository.Response
|
|||
/// Position of the station.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string gps { get; private set; }
|
||||
public GpsInfo gps { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary of bikes.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<int, StationInfo> stations { get; private set; }
|
||||
public Dictionary<string, StationInfo> stations { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using TINK.Model.Repository.Response;
|
||||
|
||||
namespace TINK.Repository.Response
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
public class SubmitFeedbackResponse : ResponseBase
|
||||
{
|
||||
|
|
|
@ -6,7 +6,11 @@ namespace TINK.Repository.Response
|
|||
/// Holds tariff info for a single bike.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
#if USCSHARP9
|
||||
public record TariffDescription
|
||||
#else
|
||||
public class TariffDescription
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the tariff.
|
||||
|
|
22
TINKLib/Repository/Response/VersionindependentResponse.cs
Normal file
22
TINKLib/Repository/Response/VersionindependentResponse.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
[DataContract]
|
||||
public class VersionindependentResponse
|
||||
{
|
||||
private CopriVersion _shareejson;
|
||||
|
||||
/// <summary> Root element for versions 4.0 and older. </summary>
|
||||
[DataMember]
|
||||
public CopriVersion tinkjson { get; private set; }
|
||||
|
||||
/// <summary> Root element from 4.1 and later. </summary>
|
||||
[DataMember]
|
||||
public CopriVersion shareejson
|
||||
{
|
||||
get => _shareejson ?? tinkjson;
|
||||
private set { _shareejson = value; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Services.CopriApi
|
||||
|
@ -123,9 +123,12 @@ namespace TINK.Model.Services.CopriApi
|
|||
try
|
||||
{
|
||||
Log.ForContext<CopriProviderHttps>().Debug($"Querrying stations from copri.");
|
||||
|
||||
var stations = await HttpsServer.GetStationsAsync();
|
||||
|
||||
return new Result<StationsAllResponse>(
|
||||
typeof(CopriCallsHttps),
|
||||
(await HttpsServer.GetStationsAsync()).GetIsResponseOk("Abfrage der Stationen fehlsgeschlagen."));
|
||||
stations.GetIsResponseOk("Abfrage der Stationen fehlsgeschlagen."));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
@ -197,23 +200,23 @@ namespace TINK.Model.Services.CopriApi
|
|||
return await HttpsServer.DoAuthoutAsync();
|
||||
}
|
||||
|
||||
public async Task<ReservationBookingResponse> DoReserveAsync(int p_iBikeId, Uri operatorUri)
|
||||
public async Task<ReservationBookingResponse> DoReserveAsync(string bikeId, Uri operatorUri)
|
||||
{
|
||||
return await HttpsServer.DoReserveAsync(p_iBikeId, operatorUri);
|
||||
return await HttpsServer.DoReserveAsync(bikeId, operatorUri);
|
||||
}
|
||||
|
||||
public async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(int p_iBikeId, Uri operatorUri)
|
||||
public async Task<ReservationCancelReturnResponse> DoCancelReservationAsync(string bikeId, Uri operatorUri)
|
||||
{
|
||||
return await HttpsServer.DoCancelReservationAsync(p_iBikeId, operatorUri);
|
||||
return await HttpsServer.DoCancelReservationAsync(bikeId, operatorUri);
|
||||
}
|
||||
|
||||
public async Task<ReservationBookingResponse> CalculateAuthKeysAsync(int bikeId, Uri operatorUri)
|
||||
public async Task<ReservationBookingResponse> CalculateAuthKeysAsync(string bikeId, Uri operatorUri)
|
||||
{
|
||||
return await HttpsServer.CalculateAuthKeysAsync(bikeId, operatorUri);
|
||||
}
|
||||
|
||||
public async Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
lock_state state,
|
||||
double batteryLevel,
|
||||
|
@ -225,22 +228,27 @@ namespace TINK.Model.Services.CopriApi
|
|||
/// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
|
||||
/// <param name="batteryPercentage">Holds the filling level percentage of the battery.</param>
|
||||
/// <returns>Response on booking request.</returns>
|
||||
public async Task<ReservationBookingResponse> DoBookAsync(int bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
public async Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
{
|
||||
return await HttpsServer.DoBookAsync(bikeId, guid, batteryPercentage, operatorUri);
|
||||
}
|
||||
|
||||
public async Task<ReservationCancelReturnResponse> DoReturn(int bikeId, LocationDto location, Uri operatorUri)
|
||||
public async Task<ReservationCancelReturnResponse> DoReturn(
|
||||
string bikeId,
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri)
|
||||
{
|
||||
return await HttpsServer.DoReturn(bikeId, location, operatorUri);
|
||||
return await HttpsServer.DoReturn(bikeId, location, smartDevice, operatorUri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to submit feedback for.</param>
|
||||
/// <param name="message">General purpose message or error description.</param>
|
||||
/// <param name="isBikeBroken">True if bike is broken.</param>
|
||||
public async Task<SubmitFeedbackResponse> DoSubmitFeedback(string message, bool isBikeBroken, Uri opertorUri) =>
|
||||
await HttpsServer.DoSubmitFeedback(message, isBikeBroken, opertorUri);
|
||||
public async Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, string message, bool isBikeBroken, Uri opertorUri) =>
|
||||
await HttpsServer.DoSubmitFeedback(bikeId, message, isBikeBroken, opertorUri);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Services.CopriApi
|
||||
|
@ -30,34 +30,38 @@ namespace TINK.Model.Services.CopriApi
|
|||
/// <summary> Gets the merchant id.</summary>
|
||||
public string MerchantId => monkeyStore.MerchantId;
|
||||
|
||||
public Task<ReservationBookingResponse> DoReserveAsync(int p_iBikeId, Uri operatorUri)
|
||||
public Task<ReservationBookingResponse> DoReserveAsync(string bikeId, Uri operatorUri)
|
||||
=> throw new NotSupportedException($"{nameof(DoReserveAsync)} is not cachable.");
|
||||
|
||||
public Task<ReservationCancelReturnResponse> DoCancelReservationAsync(int p_iBikeId, Uri operatorUri)
|
||||
public Task<ReservationCancelReturnResponse> DoCancelReservationAsync(string bikeId, Uri operatorUri)
|
||||
=> throw new NotSupportedException($"{nameof(DoCancelReservationAsync)} is not cachable.");
|
||||
|
||||
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(int bikeId, Uri operatorUri)
|
||||
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(string bikeId, Uri operatorUri)
|
||||
=> throw new NotSupportedException($"{nameof(CalculateAuthKeysAsync)} is not cachable.");
|
||||
|
||||
public async Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||
int bikeId,
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
lock_state state,
|
||||
double batteryLevel,
|
||||
Uri operatorUri)
|
||||
=> await monkeyStore.UpdateLockingStateAsync(bikeId, geolocation, state, batteryLevel, operatorUri);
|
||||
|
||||
public async Task<ReservationBookingResponse> DoBookAsync(int bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
public async Task<ReservationBookingResponse> DoBookAsync(string bikeId, Guid guid, double batteryPercentage, Uri operatorUri)
|
||||
{
|
||||
return await monkeyStore.DoBookAsync(bikeId, guid, batteryPercentage, operatorUri);
|
||||
}
|
||||
|
||||
public async Task<ReservationCancelReturnResponse> DoReturn(int bikeId, LocationDto geolocation, Uri operatorUri)
|
||||
public async Task<ReservationCancelReturnResponse> DoReturn(
|
||||
string bikeId,
|
||||
LocationDto geolocation,
|
||||
ISmartDevice smartDevice,
|
||||
Uri operatorUri)
|
||||
{
|
||||
return await monkeyStore.DoReturn(bikeId, geolocation, operatorUri);
|
||||
return await monkeyStore.DoReturn(bikeId, geolocation, smartDevice, operatorUri);
|
||||
}
|
||||
|
||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string messge, bool bIsBikeBroke, Uri operatorUri) => throw new NotImplementedException();
|
||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, string messge, bool bIsBikeBroke, Uri operatorUri) => throw new NotImplementedException();
|
||||
|
||||
public async Task<AuthorizationResponse> DoAuthorizationAsync(string p_strMailAddress, string p_strPassword, string p_strDeviceId)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Services.CopriApi
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using TINK.Model.Repository;
|
||||
using TINK.Model.Repository.Response;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Services.CopriApi
|
||||
{
|
||||
|
|
|
@ -32,13 +32,13 @@ namespace TINK.Services.CopriApi.ServerUris
|
|||
|
||||
/// <summary> Get the agb resource name name depending on host name. </summary>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
/// <returns>AGB resource..</returns>
|
||||
/// <returns>AGB resource.</returns>
|
||||
public static string GetAGBResource(this string hostName)
|
||||
=> $"{hostName.GetSiteFolderName()}/{(hostName.GetIsCopri()? "konrad-TINK-AGB" : "agb.html")}";
|
||||
|
||||
/// <summary> Get the agb resource name name depending on host name. </summary>
|
||||
/// <summary> Get the privacy resource name name depending on host name. </summary>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
/// <returns>AGB resource..</returns>
|
||||
/// <returns>Privacy resource.</returns>
|
||||
public static string GetPrivacyResource(this string hostName)
|
||||
=> $"{hostName.GetSiteFolderName()}/{(hostName.GetIsCopri() ? "Datenschutz" : "privacy.html")}";
|
||||
}
|
||||
|
|
|
@ -73,7 +73,11 @@ namespace TINK.Model.Services.CopriApi.ServerUris
|
|||
public Uri ActiveUri { get; }
|
||||
|
||||
/// <summary> Gets the active uri. </summary>
|
||||
public static Uri DevelopUri => new(TINK_DEVEL);
|
||||
#if USCSHARP9
|
||||
public static Uri DevelopUri => new (TINK_DEVEL);
|
||||
#else
|
||||
public static Uri DevelopUri => new Uri(TINK_DEVEL);
|
||||
#endif
|
||||
|
||||
/// <summary> Gets the known uris. </summary>
|
||||
[JsonProperty]
|
||||
|
|
14
TINKLib/Services/IServicesContainer.cs
Normal file
14
TINKLib/Services/IServicesContainer.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace TINK.Services
|
||||
{
|
||||
public interface IServicesContainer<T> : IEnumerable<T>
|
||||
{
|
||||
/// <summary> Get the active service.</summary>
|
||||
T Active { get; }
|
||||
|
||||
/// <summary> Sets service as active service by name. </summary>
|
||||
/// <param name="active">Name of the new service obecs.</param>
|
||||
void SetActive(string active);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ namespace TINK.Services
|
|||
{
|
||||
/// <summary> Container of service objects (locks , geolocation, ...) where one service is active. </summary>
|
||||
/// <remarks> All service objects must be of different type. </remarks>
|
||||
public class ServicesContainerMutable<T>: IEnumerable<T>, INotifyPropertyChanged
|
||||
public class ServicesContainerMutable<T>: IEnumerable<T>, INotifyPropertyChanged, IServicesContainer<T>
|
||||
{
|
||||
private readonly Dictionary<string, T> serviceDict;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue