mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-05 15:38:29 -04:00
8bebf0c394
Convert to IActivate, IDeactivate scheme, thanks andrew add support for rfcomm* interfaces on linux fix guage off screen draw mono issue. remove use of BackStageViewContentPanel andrews spacer changes - not using dues to screen space issue change configpanel constructor to load xml directly remove IMavlink Interface fix hsi off screen draw issue on mono modify hud to use sprite fonts, instead of drawing via GDI+ modify progress reporter to use a 10hz timer to update screen, using invoke/begininvoke fails on mono at 50hz (over 100ms per call). fix targetalt and target airspeed jumping issue. lots of cleanup on tab switching, ie stoping timers/other 3dr radio status led update update ardurover car icon speedup georef image screen. tested on over 1000 images.
173 lines
8.4 KiB
C#
173 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reactive.Disposables;
|
|
using System.Reactive.Linq;
|
|
using System.Reactive.Subjects;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
namespace ArdupilotMega.Controls
|
|
{
|
|
public partial class ConnectionStats : UserControl
|
|
{
|
|
private readonly MAVLink _mavlink;
|
|
private CompositeDisposable _subscriptionsDisposable;
|
|
|
|
public ConnectionStats(MAVLink comPort)
|
|
: this()
|
|
{
|
|
_mavlink = comPort;
|
|
|
|
this.Load += ConnectionStats_Load;
|
|
this.Disposed += (sender, e) => StopUpdates();
|
|
}
|
|
|
|
public ConnectionStats()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
void ConnectionStats_Load(object sender, EventArgs e)
|
|
{
|
|
_subscriptionsDisposable = new CompositeDisposable();
|
|
|
|
var packetsReceivedCount = _mavlink.WhenPacketReceived.Scan(0, (x, y) => x + y);
|
|
var packetsLostCount = _mavlink.WhenPacketLost.Scan(0, (x, y) => x + y);
|
|
|
|
var bytesReceivedEverySecond = _mavlink.BytesReceived
|
|
.Buffer(TimeSpan.FromSeconds(1))
|
|
.Select(bytes => bytes.Sum());
|
|
|
|
var subscriptions = new List<IDisposable>
|
|
{
|
|
// Total number of packets received
|
|
// but only update the text box at 4Hz
|
|
packetsReceivedCount
|
|
.Sample(TimeSpan.FromMilliseconds(250))
|
|
.SubscribeForTextUpdates(txt_PacketsRx),
|
|
|
|
packetsLostCount
|
|
.Sample(TimeSpan.FromMilliseconds(250))
|
|
.SubscribeForTextUpdates(txt_PacketsLost),
|
|
|
|
// Packets per second = total number of packets received over the
|
|
// last 3 seconds divided by three
|
|
// Do that every second
|
|
_mavlink.WhenPacketReceived
|
|
.Buffer(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(1))
|
|
.Select(xs => xs.Sum()/3.0)
|
|
.ObserveOn(SynchronizationContext.Current)
|
|
.Subscribe(x => this.txt_PacketsPerSecond.Text = x.ToString("0")),
|
|
|
|
// Link quality is a percentage of the number of good packets received
|
|
// to the number of packets missed (detected by mavlink seq no.)
|
|
// Calculated as an average over the last 3 seconds (non weighted)
|
|
// Calculated every second
|
|
CombineWithDefault(_mavlink.WhenPacketReceived, _mavlink.WhenPacketLost, Tuple.Create)
|
|
.Buffer(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(1))
|
|
.Select(CalculateAverage)
|
|
.ObserveOn(SynchronizationContext.Current)
|
|
.Subscribe(x => this.txt_LinkQuality.Text = x.ToString("00%")),
|
|
|
|
// Bytes per second is the average number of bytes received every second
|
|
// sampled for the last 3 seconds
|
|
// updated every second
|
|
bytesReceivedEverySecond
|
|
.Buffer(3, 1)
|
|
.Select(xs => (int) xs.Average())
|
|
.Select(ToHumanReadableByteCount)
|
|
.SubscribeForTextUpdates(txt_BytesPerSecondRx),
|
|
|
|
// Total bytes received - just count them up,
|
|
// but only update the text box at 4Hz so as not to swamp the UI thread
|
|
// Also use a human friendly version e.g '1.3K' not 1345
|
|
_mavlink.BytesReceived
|
|
.Scan(0, (x, y) => x + y)
|
|
.Sample(TimeSpan.FromMilliseconds(250))
|
|
.Select(ToHumanReadableByteCount)
|
|
.SubscribeForTextUpdates(txt_BytesReceived),
|
|
|
|
_mavlink.BytesSent
|
|
.Scan(0, (x, y) => x + y)
|
|
.Sample(TimeSpan.FromMilliseconds(250))
|
|
.Select(ToHumanReadableByteCount)
|
|
.SubscribeForTextUpdates(txt_BytesSent),
|
|
|
|
_mavlink.BytesSent
|
|
.Buffer(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1))
|
|
.Select(xs => xs.Any() ? xs.Average() : 0)
|
|
.Select(x => ToHumanReadableByteCount((int) x))
|
|
.SubscribeForTextUpdates(txt_BytesPerSecondSent),
|
|
|
|
// Observable.Interval(TimeSpan.FromSeconds(1))
|
|
// .Scan(TimeSpan.Zero, (a, _) => a.Add(TimeSpan.FromSeconds(1)))
|
|
// .ObserveOn(SynchronizationContext.Current)
|
|
// .Subscribe(ts => this.txt_TimeConnected.Text = ts.ToString()),
|
|
|
|
// The maximum length of time between reception of good packets
|
|
// evaluated continuously
|
|
_mavlink.WhenPacketReceived
|
|
.TimeInterval()
|
|
.Select(x => x.Interval.Ticks)
|
|
.Scan(0L, Math.Max)
|
|
.Select(TimeSpan.FromTicks)
|
|
.Select(ts => ts.Milliseconds)
|
|
.ObserveOn(SynchronizationContext.Current)
|
|
.SubscribeForTextUpdates(txt_MaxPacketInterval),
|
|
|
|
};
|
|
|
|
subscriptions.ForEach(d => _subscriptionsDisposable.Add(d));
|
|
}
|
|
|
|
public void StopUpdates()
|
|
{
|
|
_subscriptionsDisposable.Dispose();
|
|
}
|
|
|
|
private static IObservable<TResult> CombineWithDefault<TSource, TResult>(IObservable<TSource> first, Subject<TSource> second, Func<TSource, TSource, TResult> resultSelector)
|
|
{
|
|
return Observable.Defer(() =>
|
|
{
|
|
var foo = new Subject<TResult>();
|
|
|
|
first.Select(x => resultSelector(x, default(TSource))).Subscribe(foo);
|
|
second.Select(x => resultSelector(default(TSource), x)).Subscribe(foo);
|
|
|
|
return foo;
|
|
});
|
|
}
|
|
|
|
private static double CalculateAverage(IList<Tuple<int, int>> xs)
|
|
{
|
|
var packetsReceived = xs.Sum(t => t.Item1);
|
|
var packetsLost = xs.Sum(t => t.Item2);
|
|
|
|
return packetsReceived/(packetsReceived + (double)packetsLost);
|
|
}
|
|
|
|
private static string ToHumanReadableByteCount(int i)
|
|
{
|
|
if (i > 1024)
|
|
return string.Format("{0:0.00}K", i/ (float)1024);
|
|
if (i > 1024 * 1024)
|
|
return string.Format("{0:0.00}Mb", i / (float)(1024 * 1024));
|
|
return string.Format("{0:####}",i);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class CompositeDisposableEx
|
|
{
|
|
public static IDisposable SubscribeForTextUpdates<T>(this IObservable<T> source, TextBox txtBox)
|
|
{
|
|
return source
|
|
.ObserveOn(SynchronizationContext.Current)
|
|
.Subscribe(x => txtBox.Text = x.ToString());
|
|
}
|
|
}
|
|
}
|