You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

668 lines
26 KiB

using GMCabsDriverAssistant.Models;
using GMCabsDriverAssistant.Services;
using GMCabsDriverAssistant.Utils;
using GMCabsDriverAssistant.ViewModels;
using GMCabsDriverAssistantSolution.Views;
//using Plugin.BluetoothLE;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Threading;
//using Xamarin.CommunityToolkit.Extensions;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using GMCabsDriverAssistantSolution.ViewModels;
namespace GMCabsDriverAssistant.UserControl.ViewModels
{
public delegate void BluetoothStatusChanged();
class TripInformationViewModel : BaseViewModel
{
[Browsable(true)]
[Category("Action")]
[Description("Invoked when user clicks button")]
public event BluetoothStatusChanged BluetoothStatusChanged;
#region Fields
private bool hasUnreadNotifications;
public int seconds = 0;
public string timerSeconds = "00:00:00";
public string pickUpAddress = "";
public string dropUpAddress = "";
private bool isBookingAvailable;
private string startTripButtonText;
private bool visibleTrip;
private string startSuburb;
private bool isStartTripButtonVisible;
private string pickUpDateTimeOrEndSuburb;
//private List<IGattCharacteristic> Characteristics;
private bool foundDevice = false;
//private IAdapter adapter;
public bool MeterTripStarted;
private int lastMeterTripStatus = -1;
private string startTimeOrEndLocation;
private bool isOkButtonVisible = false;
public int autocloseOkSecond = 30;
Page _page;
private int mainStackLayoutMargin;
private int indicatorMargin;
private int logoMargin;
private bool isDummyButtonsVisible;
private int controlsMargin;
private int dummyButtonLayoutMargin;
private bool duressReleased;
private int duressSeconds;
private string duressButtonText;
private string bluetoothConnectionStatusText;
private string imageIcon;
private int topLayoutMargin;
private int rightLayoutMargin;
private bool isPlotButtonVisible;
#endregion
#region Properties
public Command OnStartEndTripClick { get; }
MeterTrip meterTrip = new MeterTrip();
public ObservableCollection<BookingDto> Bookings { get; }
public Command<BookingDto> BookingTapped { get; }
public double CurrentLat { get; set; }
public double CurrentLng { get; set; }
public Location CurrentLocation { get; set; }
public Command onStartTripClick { get; }
public Command OnOkButtonClick { get; }
public string StartTripButtonText
{
get => startTripButtonText;
set => SetProperty(ref startTripButtonText, value);
}
public bool HasUnreadNotifications
{
get => hasUnreadNotifications;
set => SetProperty(ref hasUnreadNotifications, value);
}
public string TimerSeconds
{
get => timerSeconds;
set => SetProperty(ref timerSeconds, value);
}
public string PickUpAddress
{
get => pickUpAddress;
set
{
SetProperty(ref pickUpAddress, value);
}
}
public string DropUpAddress
{
get => dropUpAddress;
set
{
SetProperty(ref dropUpAddress, value);
}
}
public bool IsBookingAvailable
{
get => isBookingAvailable;
set => SetProperty(ref isBookingAvailable, value);
}
public bool VisibleTrip
{
get => visibleTrip;
set => SetProperty(ref visibleTrip, value);
}
public string StartSuburb
{
get => startSuburb;
set
{
SetProperty(ref startSuburb, value);
}
}
public bool IsStartTripButtonVisible
{
get => isStartTripButtonVisible;
set => SetProperty(ref isStartTripButtonVisible, value);
}
public string PickUpDateTimeOrEndSuburb
{
get => pickUpDateTimeOrEndSuburb;
set => SetProperty(ref pickUpDateTimeOrEndSuburb, value);
}
public Thickness MainStackLayoutMargin
{
get { return new Thickness(mainStackLayoutMargin, 0, mainStackLayoutMargin, 20); }
}
public Thickness IndicatorMargin
{
get { return new Thickness(0, indicatorMargin, 0, 0); }
}
public Thickness LogoMargin
{
#if DEBUG
get { return new Thickness(0, logoMargin, 0, 0); }
#else
get { return new Thickness(logoMargin, 0 , 0, 0); }
#endif
}
public Thickness ImageLayoutMargin
{
#if DEBUG
get { return new Thickness(0, topLayoutMargin, rightLayoutMargin, 0); }
#else
get { return new Thickness(0, topLayoutMargin, rightLayoutMargin, 0); }
#endif
}
public Thickness ControlsMargin
{
get { return new Thickness(0, controlsMargin, 0, 0); }
}
public Thickness DummyButtonLayoutMargin
{
get { return new Thickness(0, dummyButtonLayoutMargin, 0, 0); }
}
public bool IsDummyButtonsVisible
{
get => isDummyButtonsVisible;
set
{
SetProperty(ref isDummyButtonsVisible, value);
}
}
public Command onCancelTripClick { get; }
public Command OnMeterStartTripClick { get; }
public Command OnMeterEndTripClick { get; }
public string StartTimeOrEndLocation
{
get => startTimeOrEndLocation;
set => SetProperty(ref startTimeOrEndLocation, value);
}
public bool IsOkButtonVisible
{
get => isOkButtonVisible;
set => SetProperty(ref isOkButtonVisible, value);
}
public string BluetoothConnectionStatusText
{
get => bluetoothConnectionStatusText;
set
{
SetProperty(ref bluetoothConnectionStatusText, value);
BluetoothStatusChanged?.Invoke();
}
}
public string DuressButtonText
{
get => duressButtonText;
set
{
SetProperty(ref duressButtonText, value);
}
}
public string ImageIcon
{
get => imageIcon;
set
{
SetProperty(ref imageIcon, value);
}
}
public bool IsPlotButtonVisible
{
get => isPlotButtonVisible;
set => SetProperty(ref isPlotButtonVisible, value);
}
#endregion
#region Constructor
public TripInformationViewModel()
{
ContinuouslyShowAllPropertiesStatus();
ShowStartTimerDuration(DispatchAppComponentService.isTripStarted);
CountEndTripDuration(DispatchAppComponentService.isTripEndeded);
lastMeterTripStatus = Preferences.Get("MeterTripStatus", 0);
OnOkButtonClick = new Command(OnOkClick);
OnStartEndTripClick = new Command(OnStartEndTripButtonClick);
OnMeterStartTripClick = new Command(CallMeterStartTrip);
OnMeterEndTripClick = new Command(MeterEndTrip);
DuressButtonText = "!";
CheckForConnectedMeter();
#if DEBUG
mainStackLayoutMargin = 30;
indicatorMargin = 5;
logoMargin = 20;
IsDummyButtonsVisible = true;
controlsMargin = 20;
dummyButtonLayoutMargin = 10;
topLayoutMargin = -5;
rightLayoutMargin = -15;
#else
mainStackLayoutMargin = 30;
indicatorMargin = 5;
logoMargin = 20;
IsDummyButtonsVisible = true;
controlsMargin = 20;
dummyButtonLayoutMargin = 10;
topLayoutMargin = -5;
rightLayoutMargin = -15;
#endif
}
#endregion
#region Methods
private void OnStartEndTripButtonClick(object obj)
{
ManageDriverTrip(false);
}
private void OnOkClick()
{
DispatchAppComponentService.OnOkClick();
DispatchAppComponentService.isPlotButtonVisible = true;
ShowAllPropertiesStatus();
}
private void MeterStartTrip()
{
// setting MeterTripStarted only here to ensure a manual trip does not get mistaken for a meter trip
if (!MeterTripStarted)
{
StartTripButtonText = DispatchAppComponentService.MeterStartTrip();
ManageDriverTrip(true);
}
}
private void MeterEndTrip()
{
if (MeterTripStarted)
{
StartTripButtonText = DispatchAppComponentService.MeterEndTrip();
ManageDriverTrip(true);
}
}
public void StartDriverDuress()
{
duressReleased = false;
duressSeconds = 0;
bool hasVibrated = false;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
duressSeconds++;
if (duressSeconds > 2)
{
if (!hasVibrated)
{
hasVibrated = true;
Vibration.Vibrate(TimeSpan.FromSeconds(1));
}
}
if (duressReleased)
{
return false;
}
else
{
return true;
}
});
}
public async void EndDriverDuress()
{
duressReleased = true;
Vibration.Cancel();
if (duressSeconds > 2)
{
var token = Preferences.Get(SecureStorageData.Token,"");
GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
var currentLocation = Geolocation.GetLastKnownLocationAsync();
double currentLat = 0;
double currentLng = 0;
if (currentLocation != null && currentLocation.Result != null)
{
currentLat = currentLocation.Result.Latitude;
currentLng = currentLocation.Result.Longitude;
}
await gmCabsDriverService.DriverDistress(token, currentLat, currentLng);
DuressButtonText = "...";
await System.Threading.Tasks.Task.Delay(2000);
DuressButtonText = "!";
}
}
private void ShowStartTimerDuration(bool isTripStarted)
{
seconds = DispatchAppComponentService.seconds;
if (isTripStarted)
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
var meterRunningStatus = Preferences.Get("MeterRunningStatus", "");
if (meterRunningStatus == "Running")
{
Device.BeginInvokeOnMainThread(() =>
{
++seconds;
DispatchAppComponentService.StartTrip(seconds);
TimerSeconds = DispatchAppComponentService.timerSeconds;
DispatchAppComponentService.seconds = seconds;
});
}
if (meterRunningStatus == "Running")
return true;
else
return false;
});
}
}
private void CountEndTripDuration(bool isTripEnded)
{
autocloseOkSecond = DispatchAppComponentService.autocloseOkSecond;
if (isTripEnded)
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
var meterRunningStatus = Preferences.Get("MeterRunningStatus", "");
if (meterRunningStatus == "Stopped")
{
if (autocloseOkSecond == 0)
{
Device.BeginInvokeOnMainThread(() =>
{
OnOkClick();
});
}
else
{
--autocloseOkSecond;
DispatchAppComponentService.autocloseOkSecond = autocloseOkSecond;
}
}
if (meterRunningStatus == "Stopped")
return true;
else
return false;
});
}
}
private void ShowAllPropertiesStatus()
{
ImageIcon = DispatchAppComponentService.imageIcon;
IsStartTripButtonVisible = DispatchAppComponentService.isStartTripButtonVisible;
IsPlotButtonVisible = DispatchAppComponentService.isPlotButtonVisible;
StartTripButtonText = DispatchAppComponentService.startTripButtonText;
MeterTripStarted = DispatchAppComponentService.meterTripStarted;
VisibleTrip = DispatchAppComponentService.visibleTrip;
StartSuburb = DispatchAppComponentService.startSuburb;
PickUpDateTimeOrEndSuburb = DispatchAppComponentService.pickUpDateTimeOrEndSuburb;
StartTimeOrEndLocation = DispatchAppComponentService.startTimeOrEndLocation;
IsOkButtonVisible = DispatchAppComponentService.isOkButtonVisible;
TimerSeconds = DispatchAppComponentService.timerSeconds;
}
private void ContinuouslyShowAllPropertiesStatus()
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Device.BeginInvokeOnMainThread(() =>
{
ShowAllPropertiesStatus();
});
return true;
});
}
public void SetTripStartEndButtonPosition()
{
DispatchAppComponentService.isPlotButtonVisible= false;
ShowAllPropertiesStatus();
}
#endregion
#region Trip Handling
private void ManageDriverTrip(bool fromMeter)
{
if (StartTripButtonText.Equals("START TRIP"))
{
DispatchAppComponentService.isTripStarted = true;
DispatchAppComponentService.isTripEndeded = false;
DispatchAppComponentService.ManageDriverTrip(fromMeter);
StartTimeOrEndLocation = DispatchAppComponentService.startTimeOrEndLocation;
StartTrip(fromMeter);
TimerSeconds = DispatchAppComponentService.timerSeconds;
DispatchAppComponentService.seconds = seconds = 0;
ShowStartTimerDuration(DispatchAppComponentService.isTripStarted);
DispatchAppComponentService.isPlotButtonVisible = false;
}
else if (StartTripButtonText.Equals("DROP OFF"))
{
DispatchAppComponentService.isTripStarted = false;
DispatchAppComponentService.isTripEndeded = true;
DispatchAppComponentService.ManageDriverTrip(fromMeter);
StartTimeOrEndLocation = DispatchAppComponentService.startTimeOrEndLocation;
EndTrip(fromMeter);
IsOkButtonVisible = DispatchAppComponentService.isOkButtonVisible;
DispatchAppComponentService.autocloseOkSecond = autocloseOkSecond = 30;
CountEndTripDuration(DispatchAppComponentService.isTripEndeded);
}
}
private async void StartTrip(bool fromMeter)
{
DispatchAppComponentService.startSuburb = await DispatchAppComponentService.GetSuburbName(fromMeter, true);
MeterTripStarted = DispatchAppComponentService.meterTripStarted;
ImageIcon = DispatchAppComponentService.imageIcon;
VisibleTrip = DispatchAppComponentService.visibleTrip;
StartSuburb = DispatchAppComponentService.startSuburb;
PickUpDateTimeOrEndSuburb = DispatchAppComponentService.pickUpDateTimeOrEndSuburb;
StartTripButtonText = DispatchAppComponentService.startTripButtonText;
}
private async void EndTrip(bool fromMeter)
{
DispatchAppComponentService.pickUpDateTimeOrEndSuburb = await DispatchAppComponentService.GetSuburbName(fromMeter, false);
MeterTripStarted = DispatchAppComponentService.meterTripStarted;
PickUpDateTimeOrEndSuburb = DispatchAppComponentService.pickUpDateTimeOrEndSuburb;
ImageIcon = DispatchAppComponentService.imageIcon;
IsStartTripButtonVisible = DispatchAppComponentService.isStartTripButtonVisible;
}
private void CallMeterStartTrip()
{
DispatchAppComponentService.startTripButtonText = "START TRIP";
DispatchAppComponentService.meterTripStarted = false;
DispatchAppComponentService.isTripStarted = true;
DispatchAppComponentService.isTripEndeded = false;
DispatchAppComponentService.isOkButtonVisible = false;
DispatchAppComponentService.isStartTripButtonVisible = true;
DispatchAppComponentService.ManageDriverTrip(false);
StartTimeOrEndLocation = DispatchAppComponentService.startTimeOrEndLocation;
StartTrip(false);
TimerSeconds = DispatchAppComponentService.timerSeconds;
DispatchAppComponentService.seconds = seconds = 0;
ShowStartTimerDuration(DispatchAppComponentService.isTripStarted);
}
#endregion Trip Handling
#region Meter Handling
private void CheckForConnectedMeter()
{
// ConnectToMeter();
}
//private void ConnectToMeter()
//{
// adapter = CrossBleAdapter.Current;
// var status = adapter.Status.ToString();
// if (status.Contains("Off"))
// {
// bluetoothConnectionStatusText = "Bluetooth connection off...";
// }
// else
// {
// BluetoothConnectionStatusText = "Checking meter connection...";
// BluetoothConnectionStatusText = $"Adapter status {CrossBleAdapter.Current.Status.ToString()}";
// IDevice bondedDevice = null;
// CrossBleAdapter.Current.GetConnectedDevices().Subscribe(deviceResult =>
// {
// bondedDevice = deviceResult.GetEnumerator().Current;
// });
// if (bondedDevice != null && bondedDevice.Status == ConnectionStatus.Connected)
// {
// ListenForCharacteristic(bondedDevice);
// }
// else
// {
// CrossBleAdapter.Current.GetPairedDevices().Subscribe(devices =>
// {
// if (devices != null)
// {
// ConnectionConfig conConfig = new ConnectionConfig();
// conConfig.AutoConnect = true;
// BluetoothConnectionStatusText = $"Listening for paired device";
// foreach (var pairedDevice in devices)
// {
// pairedDevice.ConnectWait(conConfig).Subscribe(device =>
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"{device.Status}"; });
// ListenForCharacteristic(pairedDevice);
// });
// }
// }
// });
// if (CrossBleAdapter.Current.IsScanning)
// {
// BluetoothConnectionStatusText = $"resuming scan";
// }
// else
// {
// BluetoothConnectionStatusText = $"Adapter status {CrossBleAdapter.Current.Status.ToString()} - Scanning";
// Characteristics = new List<IGattCharacteristic>();
// var scanResult = CrossBleAdapter.Current.Scan().Subscribe(scResult => { CheckDevice(scResult); }, exception =>
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Error: {exception.Message}"; });
// });
// }
// }
// }
//}
//private void CheckDevice(IScanResult scanResult)
//{
// if (scanResult.Device.Name != null && scanResult.Device.Name.StartsWith("MTI_") && !foundDevice)
// {
// BluetoothConnectionStatusText = $"Meter found - {scanResult.Device.Name}";
// foundDevice = true;
// CrossBleAdapter.Current.StopScan();
// ConnectToDevice(scanResult.Device);
// }
//}
//private void ConnectToDevice(IDevice discoveredDevice)
//{
// ConnectionConfig conConfig = new ConnectionConfig();
// conConfig.AutoConnect = true;
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Device Details - P:{discoveredDevice.PairingStatus.ToString()} - C:{discoveredDevice.IsConnected()}"; });
// if (discoveredDevice.IsConnected())
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Searching for GUIDs"; });
// ListenForCharacteristic(discoveredDevice);
// }
// else
// {
// if (discoveredDevice.PairingStatus == PairingStatus.NotPaired)
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Pairing"; });
// discoveredDevice.PairingRequest("191135");
// }
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Connecting"; });
// discoveredDevice.ConnectWait(conConfig).Subscribe(device =>
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"{device.Status}"; });
// ListenForCharacteristic(device);
// });
// }
//}
//private void ListenForCharacteristic(IDevice device)
//{
// bool subscribed = false;
// try
// {
// device.GetKnownCharacteristics(Guid.Parse("de201840-063f-11e5-be3e-0002a5d5c51b"), new Guid[] { Guid.Parse("de000180-063f-11e5-9e69-0002a5d5c503") }).Subscribe(characteristics =>
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { BluetoothConnectionStatusText = $"Service Detected"; });
// if (characteristics != null)
// {
// characteristics.RegisterAndNotify().Subscribe(registerResult =>
// {
// // RegisterAndNotify seems to keep firing each time, there must be a better way
// // to do this only once, currently just setting a local flag.
// if (!subscribed)
// {
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
// {
// BluetoothConnectionStatusText = "Ready";
// });
// subscribed = true;
// characteristics.WhenNotificationReceived().Subscribe(notification => { CheckNotification(notification); });
// }
// });
// }
// });
// }
// catch(Exception ex)
// {
// }
//}
//private void CheckNotification(CharacteristicGattResult notification)
//{
// if (notification != null && notification.Data != null && notification.Characteristic != null && notification.Characteristic.Uuid.ToString() == "de000180-063f-11e5-9e69-0002a5d5c503")
// {
// string data = $"Date:{DateTime.Now.ToString("HH:mm:ss")}, Description:{notification.Characteristic.Uuid},Data:{BitConverter.ToString(notification.Data)}\n";
// Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
// {
// int tripStatus = 0;
// if (notification.Data[0] != 0) { tripStatus = 1; }
// if (lastMeterTripStatus != tripStatus)
// {
// lastMeterTripStatus = tripStatus;
// Preferences.Set("MeterTripStatus", tripStatus);
// if (tripStatus == 0)
// {
// MeterEndTrip();
// }
// else if (tripStatus == 1)
// {
// //MeterStartTrip();
// CallMeterStartTrip();
// }
// }
// });
// }
//}
#endregion Meter Handling
}
}