ardupilot/Configurator/Configurator.Net/PresentationModels/MainVm.cs

269 lines
8.1 KiB
C#

using System;
using System.ComponentModel;
using Timer=System.Windows.Forms.Timer;
namespace ArducopterConfigurator.PresentationModels
{
public class MainVm : NotifyProperyChangedBase, IPresentationModel
{
private readonly IComms _comms;
private bool _isConnected;
private IPresentationModel _selectedVm;
private string _selectedPort;
private string _apmVersion;
private Timer _connectionAttemptsTimer;
private SessionStates _connectionState;
public MainVm(IComms session)
{
_comms = session;
_comms.LineOfDataReceived += _session_LineOfDataReceived;
MonitorVms = new BindingList<IPresentationModel>
{
new SensorsVm(),
new TransmitterChannelsVm(),
new FlightControlPidsVm(),
new PositionAltitudePidsVm(),
//new MotorCommandsVm(session),
new SerialMonitorVm()
};
foreach (var vm in MonitorVms)
{
if (vm is ItalksToApm)
vm.sendTextToApm += MainVm_sendTextToApm;
}
ConnectCommand = new DelegateCommand(
_ => Connect(),
_ => _connectionState==SessionStates.Disconnected && AvailablePorts.Contains(SelectedPort));
DisconnectCommand = new DelegateCommand(_ => Disconnect(), _ => IsConnected);
RefreshPortListCommand = new DelegateCommand(_ => RefreshPorts());
RestoreDefaultsCommand = new DelegateCommand(_ => RestoreDefaults(), _ => IsConnected);
WriteToEepromCommand = new DelegateCommand(_ => WriteToEeprom(), _ => IsConnected);
ConnectionState = SessionStates.Disconnected;
AvailablePorts = new BindingList<string>();
RefreshPorts();
// Initially have selected the last discovered com port.
// I think this is more likely to be the correct one, as
// the built in comports come first, then the usb/serial
// converter ports
if (AvailablePorts.Count > 0)
SelectedPort = AvailablePorts[AvailablePorts.Count-1];
}
void MainVm_sendTextToApm(object sender, sendTextToApmEventArgs e)
{
if (sender.Equals(_selectedVm)==false)
{
Console.WriteLine("Non selected vm wants to send something to the APM");
return;
}
if (_comms.IsConnected)
_comms.Send(e.textToSend);
}
private void RefreshPorts()
{
AvailablePorts.Clear();
foreach (var c in _comms.ListCommPorts())
AvailablePorts.Add(c);
}
private void RestoreDefaults()
{
if (_comms.IsConnected)
_comms.Send("Y");
}
private void WriteToEeprom()
{
if (_comms.IsConnected)
_comms.Send("W");
}
void _session_LineOfDataReceived(string strRx)
{
// If we are waiting for the version string
if (ConnectionState==SessionStates.Connecting)
{
if (strRx.Length > 6)
return; // too long for a version string - reject
// then assume that this is the version string received
ApmVersion = strRx;
ConnectionState = SessionStates.Connected;
_selectedVm.Activate();
}
else if (ConnectionState == SessionStates.Connected)
{
if (_selectedVm is ItalksToApm)
(_selectedVm as ItalksToApm).handleLineOfText(strRx);
}
}
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand RefreshPortListCommand { get; private set; }
public ICommand RestoreDefaultsCommand { get; private set; }
public ICommand WriteToEepromCommand { get; private set; }
public BindingList<string> AvailablePorts { get; private set; }
public enum SessionStates
{
Disconnected,
Connecting,
Connected,
}
public SessionStates ConnectionState
{
get { return _connectionState; }
set
{
if (_connectionState != value)
{
_connectionState = value;
IsConnected = _connectionState == SessionStates.Connected;
FirePropertyChanged("ConnectionState");
}
}
}
// provided for convenience for binding set from the session state prop
public bool IsConnected
{
get { return _isConnected; }
private set
{
if (_isConnected != value)
{
_isConnected = value;
FirePropertyChanged("IsConnected");
}
}
}
public string SelectedPort
{
get { return _selectedPort; }
set
{
if (_selectedPort != value)
{
_selectedPort = value;
FirePropertyChanged("SelectedPort");
}
}
}
public void Connect()
{
_comms.CommPort = SelectedPort;
// Todo: check the status of this call success/failure
_comms.Connect();
ConnectionState = SessionStates.Connecting;
_connectionAttemptsTimer = new Timer();
_connectionAttemptsTimer.Tick += _connectionAttemptsTimer_Tick;
_connectionAttemptsTimer.Interval = 1000; //milliseconds
_connectionAttemptsTimer.Start();
}
void _connectionAttemptsTimer_Tick(object sender, EventArgs e)
{
if (_connectionState != SessionStates.Connecting)
{
_connectionAttemptsTimer.Stop();
return;
}
_comms.Send("X");
// once we connected, then get the version string
_comms.Send("!");
}
public void Disconnect()
{
_comms.Send("X");
_comms.DisConnect();
ConnectionState = SessionStates.Disconnected;
}
public string ApmVersion
{
get { return _apmVersion; }
private set
{
if (_apmVersion != value)
{
_apmVersion = value;
FirePropertyChanged("ApmVersion");
}
}
}
public BindingList<IPresentationModel> MonitorVms { get; private set; }
public string Name
{
get { return "Arducopter Config"; }
}
public void Activate()
{
throw new System.NotImplementedException();
}
public void DeActivate()
{
throw new System.NotImplementedException();
}
public event EventHandler updatedByApm;
public void Select(IPresentationModel vm)
{
if (_selectedVm==vm)
return;
if (vm == null)
throw new ArgumentNullException("vm");
if (_selectedVm!=null)
_selectedVm.DeActivate();
_selectedVm = vm;
_selectedVm.Activate();
}
public void handleLineOfText(string strRx)
{
throw new System.NotImplementedException();
}
public event EventHandler<sendTextToApmEventArgs> sendTextToApm;
}
}