mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-19 03:27:29 +02:00
Version 3.0.381
This commit is contained in:
parent
f963c0a219
commit
3a363acf3a
1525 changed files with 60589 additions and 125098 deletions
187
SharedBusinessLogic/Model/Connector/Command/Command.cs
Normal file
187
SharedBusinessLogic/Model/Connector/Command/Command.cs
Normal file
|
@ -0,0 +1,187 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Device;
|
||||
using ShareeBike.Model.User.Account;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Repository.Request;
|
||||
using ShareeBike.Repository.Response;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
public class Command : Base, ICommand
|
||||
{
|
||||
/// <summary> True if connector has access to copri server, false if cached values are used. </summary>
|
||||
public bool IsConnected => CopriServer.IsConnected;
|
||||
|
||||
/// <summary> No user is logged in.</summary>
|
||||
public string SessionCookie => null;
|
||||
|
||||
/// <summary> Is raised whenever login state has changed.</summary>
|
||||
public event LoginStateChangedEventHandler LoginStateChanged;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
public Command(
|
||||
ICopriServerBase p_oCopriServer) : base(p_oCopriServer)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 exception is thrown.
|
||||
/// </summary>
|
||||
public async Task<IAccount> DoLogin(
|
||||
string mail,
|
||||
string password,
|
||||
string deviceId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(mail))
|
||||
{
|
||||
throw new ArgumentNullException("Can not login user. Mail address must not be null or empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
throw new ArgumentNullException("Can not login user. Password must not be null or empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(deviceId))
|
||||
{
|
||||
throw new ArgumentNullException("Can not login user. Device not be null or empty.");
|
||||
}
|
||||
|
||||
AuthorizationResponse response;
|
||||
try
|
||||
{
|
||||
response = (await CopriServer.DoAuthorizationAsync(mail, password, deviceId)).GetIsResponseOk(mail);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
var l_oAccount = response.GetAccount(MerchantId, mail, password);
|
||||
|
||||
// Log in state changes. Notify parent object to update.
|
||||
LoginStateChanged?.Invoke(this, new LoginStateChangedEventArgs(l_oAccount.SessionCookie, l_oAccount.Mail));
|
||||
|
||||
return l_oAccount;
|
||||
}
|
||||
|
||||
/// <summary> Logs user out. </summary>
|
||||
public async Task DoLogout()
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected log out request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request to reserve a bike.
|
||||
/// </summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
public async Task DoReserve(
|
||||
Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected booking request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary> Request to cancel a reservation.</summary>
|
||||
/// <param name="p_oBike">Bike to book.</param>
|
||||
public async Task DoCancelReservation(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected cancel reservation request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary> Get authentication keys.</summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
public async Task CalculateAuthKeys(Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected request to get authentication keys detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary> Updates COPRI lock state for a booked bike. </summary>
|
||||
/// <param name="bike">Bike to update locking state for.</param>
|
||||
/// <param name="location">Location where lock was opened/ changed.</param>
|
||||
/// <returns>Response on updating locking state.</returns>
|
||||
public async Task StartReturningBike(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected request to notify about start of returning bike. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary> Notifies COPRI about start of returning sequence. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <returns>Response on notification about start of returning sequence.</returns>
|
||||
public async Task UpdateLockingStateAsync(Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable bike, LocationDto location)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected request to update locking state detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task DoBookAsync(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike, LockingAction? nextAction = null)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected booking request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task BookAndOpenAync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected request to book and open bike detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<BookingFinishedModel> DoReturn(
|
||||
Bikes.BikeInfoNS.BC.IBikeInfoMutable bike,
|
||||
LocationDto location,
|
||||
ISmartDevice smartDevice)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected returning request detected. No user logged in.");
|
||||
return await Task.FromResult(new BookingFinishedModel());
|
||||
}
|
||||
|
||||
public async Task<BookingFinishedModel> ReturnAndCloseAsync(
|
||||
Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike,
|
||||
ISmartDevice smartDevice)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected close lock and return request detected. No user logged in.");
|
||||
return await Task.FromResult(new BookingFinishedModel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// <summary> Submits mini survey to copri server. </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
public async Task DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||
{
|
||||
Log.ForContext<Command>().Error("Unexpected submit mini survey request detected. No user logged in.");
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task OpenLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
321
SharedBusinessLogic/Model/Connector/Command/CommandLoggedIn.cs
Normal file
321
SharedBusinessLogic/Model/Connector/Command/CommandLoggedIn.cs
Normal file
|
@ -0,0 +1,321 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Device;
|
||||
using ShareeBike.Model.User.Account;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Repository.Exception;
|
||||
using ShareeBike.Repository.Request;
|
||||
using ShareeBike.Repository.Response;
|
||||
using ShareeBike.Services.CopriApi;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
public class CommandLoggedIn : BaseLoggedIn, ICommand
|
||||
{
|
||||
/// <summary> True if connector has access to copri server, false if cached values are used. </summary>
|
||||
public bool IsConnected => CopriServer.IsConnected;
|
||||
|
||||
/// <summary> Is raised whenever login state has changed.</summary>
|
||||
public event LoginStateChangedEventHandler LoginStateChanged;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
public CommandLoggedIn(ICopriServerBase p_oCopriServer,
|
||||
string sessionCookie,
|
||||
string mail,
|
||||
Func<DateTime> dateTimeProvider) : base(p_oCopriServer, sessionCookie, mail, dateTimeProvider)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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 ShareeBike.Repository.Exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="p_oAccount">Account to use for login.</param>
|
||||
public Task<IAccount> DoLogin(string mail, string password, string deviceId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(mail))
|
||||
{
|
||||
throw new ArgumentNullException("Can not login user. Mail address must not be null or empty.");
|
||||
}
|
||||
|
||||
throw new Exception($"Fehler beim Anmelden von unter {mail}. Benutzer {Mail} ist bereits angemeldet.");
|
||||
}
|
||||
|
||||
/// <summary> Logs user out. </summary>
|
||||
public async Task DoLogout()
|
||||
{
|
||||
AuthorizationoutResponse l_oResponse = null;
|
||||
try
|
||||
{
|
||||
l_oResponse = (await CopriServer.DoAuthoutAsync()).GetIsResponseOk();
|
||||
}
|
||||
catch (AuthcookieNotDefinedException)
|
||||
{
|
||||
// Cookie is no more defined, i.e. no need to logout user at copri because user is already logged out.
|
||||
// Just ignore this error.
|
||||
// User logged out, log in state changed. Notify parent object to update.
|
||||
LoginStateChanged?.Invoke(this, new LoginStateChangedEventArgs());
|
||||
return;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
// User logged out, log in state changed. Notify parent object to update.
|
||||
LoginStateChanged?.Invoke(this, new LoginStateChangedEventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request to reserve a bike.
|
||||
/// </summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
public async Task DoReserve(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not reserve bike. No bike object available.");
|
||||
}
|
||||
|
||||
BikeInfoReservedOrBooked response;
|
||||
try
|
||||
{
|
||||
response = (await CopriServer.DoReserveAsync(bike.Id, bike.OperatorUri)).GetIsReserveResponseOk(bike.Id);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Exception was not expected or too many subsequent exceptions detected.
|
||||
throw;
|
||||
}
|
||||
|
||||
bike.Load(response, Mail, Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||
}
|
||||
|
||||
/// <summary> Request to cancel a reservation.</summary>
|
||||
/// <param name="bike">Bike to cancel reservation.</param>
|
||||
public async Task DoCancelReservation(
|
||||
Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not cancel reservation of bike. No bike object available.");
|
||||
}
|
||||
|
||||
BookingActionResponse response;
|
||||
try
|
||||
{
|
||||
response = (await CopriServer
|
||||
.DoCancelReservationAsync(bike.Id, bike.OperatorUri))
|
||||
.GetIsResponseOk(string.Format(MultilingualResources.AppResources.ErrorCancelReservationFailed, bike.Id));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Exception was not expected or too many subsequent exceptions detected.
|
||||
throw;
|
||||
}
|
||||
|
||||
bike.Load(Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||
}
|
||||
|
||||
/// <summary> Get authentication keys.</summary>
|
||||
/// <param name="bike">Bike to get new keys for.</param>
|
||||
public async Task CalculateAuthKeys(Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable bike)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not calculate auth keys. No bike object available.");
|
||||
}
|
||||
|
||||
switch (bike.State.Value)
|
||||
{
|
||||
case State.InUseStateEnum.Reserved:
|
||||
case State.InUseStateEnum.Booked:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentNullException($"Can not calculate auth keys. Unexpected bike state {bike.State.Value} detected.");
|
||||
}
|
||||
|
||||
BikeInfoReservedOrBooked response;
|
||||
Guid guid = (bike is BikeInfoMutable btBike) ? btBike.LockInfo.Guid : new Guid();
|
||||
try
|
||||
{
|
||||
response = (await CopriServer.CalculateAuthKeysAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Exception was not expected or too many subsequent exceptions detected.
|
||||
throw;
|
||||
}
|
||||
|
||||
UpdaterJSON.Load(
|
||||
bike,
|
||||
response,
|
||||
Mail,
|
||||
Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||
}
|
||||
|
||||
/// <summary> Notifies COPRI about start of returning sequence. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <returns>Response on notification about start of returning sequence.</returns>
|
||||
public async Task StartReturningBike(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not notify about start returning bike. No bike object available.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
(await CopriServer.StartReturningBike(
|
||||
bike.Id,
|
||||
bike.OperatorUri)).GetIsResponseOk("Start returning bike");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Exception was not expected or too many subsequent exceptions detected.
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Updates COPRI lock state for a booked or reserved bike. </summary>
|
||||
/// <param name="bike">Bike to update locking state for.</param>
|
||||
/// <param name="location">Location of the bike.</param>
|
||||
/// <returns>Response on updating locking state.</returns>
|
||||
public async Task UpdateLockingStateAsync(
|
||||
IBikeInfoMutable bike,
|
||||
LocationDto location)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not update locking state of bike. No bike object available.");
|
||||
}
|
||||
|
||||
if (bike.State.Value != State.InUseStateEnum.Booked && bike.State.Value != State.InUseStateEnum.Reserved)
|
||||
{
|
||||
throw new ArgumentNullException($"Can not update locking state of bike. Unexpected booking state {bike.State} detected.");
|
||||
}
|
||||
|
||||
lock_state? state = RequestBuilderHelper.GetLockState(bike.LockInfo.State);
|
||||
|
||||
if (!state.HasValue)
|
||||
{
|
||||
throw new ArgumentNullException($"Can not update locking state of bike. Unexpected locking state {bike.LockInfo.State} detected.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
(await CopriServer.UpdateLockingStateAsync(
|
||||
bike.Id,
|
||||
state.Value,
|
||||
bike.OperatorUri,
|
||||
location,
|
||||
bike.LockInfo.BatteryPercentage,
|
||||
bike.LockInfo.VersionInfo)).GetIsBookingResponseOk(bike.Id);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Exception was not expected or too many subsequent exceptions detected.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Request to book a bike. </summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
/// <param name="nextAction">If not null next locking action which is performed after booking.</param>
|
||||
public async Task DoBookAsync(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike, LockingAction? nextAction = null)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(bike), "Can not book bike. No bike object available.");
|
||||
}
|
||||
|
||||
BikeInfoReservedOrBooked response;
|
||||
var btBike = bike as BikeInfoMutable;
|
||||
Guid guid = btBike != null ? btBike.LockInfo.Guid : new Guid();
|
||||
double batteryPercentage = btBike != null ? btBike.LockInfo.BatteryPercentage : double.NaN;
|
||||
|
||||
response = (await CopriServer.DoBookAsync(
|
||||
bike.OperatorUri,
|
||||
bike.Id,
|
||||
guid,
|
||||
batteryPercentage,
|
||||
nextAction)).GetIsBookingResponseOk(bike.Id);
|
||||
|
||||
bike.Load(
|
||||
response,
|
||||
Mail,
|
||||
Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Books a bike and opens the lock.
|
||||
/// </summary>
|
||||
/// <param name="bike">Bike to book and open.</param>
|
||||
public async Task BookAndOpenAync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
=> await Polling.BookAndOpenAync(CopriServer, bike, Mail);
|
||||
|
||||
/// <summary> Request to return a bike.</summary>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <param name="locaton">Position of the bike for bluetooth locks.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
public async Task<BookingFinishedModel> DoReturn(
|
||||
Bikes.BikeInfoNS.BC.IBikeInfoMutable bike,
|
||||
LocationDto location = null,
|
||||
ISmartDevice smartDevice = null)
|
||||
{
|
||||
if (bike == null)
|
||||
{
|
||||
throw new ArgumentNullException("Can not return bike. No bike object available.");
|
||||
}
|
||||
|
||||
DoReturnResponse response
|
||||
= (await CopriServer.DoReturn(bike.Id, location, bike.OperatorUri)).GetIsReturnBikeResponseOk(bike.Id);
|
||||
|
||||
bike.Load(
|
||||
Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None,
|
||||
response.bike_returned.station ?? string.Empty);
|
||||
|
||||
return response?.Create() ?? new BookingFinishedModel();
|
||||
}
|
||||
|
||||
/// <summary> Request to return bike and close the lock.</summary>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
public async Task<BookingFinishedModel> ReturnAndCloseAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike, ISmartDevice smartDevice = null)
|
||||
=> await Polling.ReturnAndCloseAync(CopriServer, smartDevice, bike);
|
||||
|
||||
/// <summary>
|
||||
/// 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.BikeId, userFeedback.Message, userFeedback.IsBikeBroken, opertorUri);
|
||||
#else
|
||||
/// <summary> Submits feedback for a renting operation.</summary>
|
||||
public async Task DoSubmitFeedback(
|
||||
IUserFeedback userFeedback,
|
||||
Uri opertorUri)
|
||||
=> await CopriServer.DoSubmitFeedback(userFeedback.BikeId, userFeedback.CurrentChargeBars, userFeedback.Message, userFeedback.IsBikeBroken, opertorUri);
|
||||
#endif
|
||||
|
||||
/// <summary> Submits mini survey to copri server. </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
public async Task DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||
=> await CopriServer.DoSubmitMiniSurvey(answers);
|
||||
|
||||
public async Task OpenLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
=> await CopriServer.OpenAync(bike);
|
||||
public async Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike)
|
||||
=> await CopriServer.CloseAync(bike);
|
||||
}
|
||||
}
|
177
SharedBusinessLogic/Model/Connector/Command/ICommand.cs
Normal file
177
SharedBusinessLogic/Model/Connector/Command/ICommand.cs
Normal file
|
@ -0,0 +1,177 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ShareeBike.Model.Device;
|
||||
using ShareeBike.Model.User.Account;
|
||||
using ShareeBike.Repository.Request;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
public interface ICommand
|
||||
{
|
||||
/// <summary> Is raised whenever login state has changed.</summary>
|
||||
event LoginStateChangedEventHandler LoginStateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 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 exception is thrown.
|
||||
/// </summary>
|
||||
Task<IAccount> DoLogin(string p_strMail, string p_strPassword, string p_strDeviceId);
|
||||
|
||||
/// <summary> Logs user out. </summary>
|
||||
Task DoLogout();
|
||||
|
||||
/// <summary> Request to reserve a bike.</summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
Task DoReserve(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Request to cancel a reservation.</summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
Task DoCancelReservation(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Get authentication keys to connect to lock.</summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
Task CalculateAuthKeys(Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Notifies COPRI about start of returning sequence. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <returns>Response on notification about start of returning sequence.</returns>
|
||||
Task StartReturningBike(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Updates COPRI lock state for a booked bike. </summary>
|
||||
/// <param name="bike">Bike to update locking state for.</param>
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <returns>Response on updating locking state.</returns>
|
||||
Task UpdateLockingStateAsync(Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable bike, LocationDto location = null);
|
||||
|
||||
/// <summary> Request to book a bike.</summary>
|
||||
/// <param name="bike">Bike to book.</param>
|
||||
/// <param name="nextAction">If not null next locking action which is performed after booking.</param>
|
||||
Task DoBookAsync(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike, LockingAction? nextAction = null);
|
||||
|
||||
/// <summary> Request to book a bike and open its lock.</summary>
|
||||
/// <param name="bike">Bike to book and to open lock for.</param>
|
||||
Task BookAndOpenAync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Request to open lock.</summary>
|
||||
/// <param name="bike">Bike for which lock has to be opened.</param>
|
||||
Task OpenLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Request to close lock.</summary>
|
||||
/// <param name="bike">Bike for which lock has to be closed.</param>
|
||||
Task CloseLockAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike);
|
||||
|
||||
/// <summary> Request to return a bike.</summary>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
Task<BookingFinishedModel> DoReturn(Bikes.BikeInfoNS.BC.IBikeInfoMutable bike, LocationDto geolocation = null, ISmartDevice smartDevice = null);
|
||||
|
||||
/// <summary> Request to return bike and close the lock.</summary>
|
||||
/// <param name="bike">Bike to return.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
Task<BookingFinishedModel> ReturnAndCloseAsync(Bikes.BikeInfoNS.CopriLock.IBikeInfoMutable bike, ISmartDevice smartDevice = null);
|
||||
|
||||
/// <summary> True if connector has access to copri server, false if cached values are used. </summary>
|
||||
bool IsConnected { get; }
|
||||
|
||||
/// <summary> True if user is logged in false if not. </summary>
|
||||
string SessionCookie { get; }
|
||||
|
||||
/// <summary> Submits feedback for a renting operation.</summary>
|
||||
Task DoSubmitFeedback(
|
||||
IUserFeedback userFeedback,
|
||||
Uri opertorUri);
|
||||
|
||||
/// <summary> Submits mini survey to copri server. </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
Task DoSubmitMiniSurvey(IDictionary<string, string> answers);
|
||||
|
||||
#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>Defines delegate to be raised whenever login state changes.</summary>
|
||||
/// <param name="eventArgs">Holds session cookie and mail address if user logged in successfully.</param>
|
||||
public delegate void LoginStateChangedEventHandler(object sender, LoginStateChangedEventArgs eventArgs);
|
||||
|
||||
#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 the current charging level of the battery in bars, null if unknown.
|
||||
/// </summary>
|
||||
int? CurrentChargeBars { get; set; }
|
||||
|
||||
/// <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
|
||||
{
|
||||
public LoginStateChangedEventArgs() : this(string.Empty, string.Empty)
|
||||
{ }
|
||||
|
||||
public LoginStateChangedEventArgs(string sessionCookie, string mail)
|
||||
{
|
||||
SessionCookie = sessionCookie;
|
||||
Mail = mail;
|
||||
}
|
||||
|
||||
public string SessionCookie { get; }
|
||||
|
||||
public string Mail { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a action to be performed with an lock.
|
||||
/// </summary>
|
||||
public enum LockingAction
|
||||
{
|
||||
Close,
|
||||
Open,
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
namespace ShareeBike.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; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the current charging level of the battery in bars, null if unknown.
|
||||
/// </summary>
|
||||
public int? CurrentChargeBars { get; set; }
|
||||
|
||||
public bool IsBikeBroken { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue