Compare commits

...

2 Commits

Author SHA1 Message Date
1addb3c4e1 Add project files. 2022-02-08 18:25:21 +13:00
527f9f451d Add .gitattributes and .gitignore. 2022-02-08 18:25:21 +13:00
9 changed files with 374 additions and 14 deletions

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

16
.gitignore vendored
View File

@ -1,4 +1,3 @@
# ---> VisualStudio
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
@ -30,6 +29,7 @@ x86/
bld/ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Oo]ut/
[Ll]og/ [Ll]og/
[Ll]ogs/ [Ll]ogs/
@ -360,16 +360,4 @@ MigrationBackup/
.ionide/ .ionide/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd
# ---> VisualStudioCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32127.271
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Starlink Desktop Monitor", "Starlink Desktop Monitor\Starlink Desktop Monitor.csproj", "{E90822C7-1FC9-4FB7-89E2-D60CD9AC8D8A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E90822C7-1FC9-4FB7-89E2-D60CD9AC8D8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E90822C7-1FC9-4FB7-89E2-D60CD9AC8D8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E90822C7-1FC9-4FB7-89E2-D60CD9AC8D8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E90822C7-1FC9-4FB7-89E2-D60CD9AC8D8A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AD4A0B2A-DDC8-4EAA-80ED-680B115D5FD4}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,9 @@
<Application x:Class="Starlink_Desktop_Monitor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Starlink_Desktop_Monitor"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Starlink_Desktop_Monitor
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@ -0,0 +1,70 @@
<Window x:Class="Starlink_Desktop_Monitor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Starlink_Desktop_Monitor"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Vertical" Margin="5,0,5,0">
<Grid x:Name="DownloadGrid" Height="200" Width="200">
<Grid>
<Grid x:Name="BlackObscure" Height="134" Width="200" HorizontalAlignment="Right" VerticalAlignment="Top">
<Ellipse x:Name="BaseRing_Black" Height="200" Stroke="Black" Width="200" StrokeThickness="5" HorizontalAlignment="Right"/>
</Grid>
</Grid>
<Grid HorizontalAlignment="Center" Height="200" VerticalAlignment="Center" Width="200" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Grid x:Name="RedObscure" HorizontalAlignment="Right" VerticalAlignment="Top" Width="54" Height="136">
<Ellipse x:Name="BaseRing_Red" HorizontalAlignment="Right" Height="200" Stroke="Red" VerticalAlignment="Top" Width="200" StrokeThickness="5"/>
</Grid>
</Grid>
<Rectangle x:Name="NeedleDL" HorizontalAlignment="Center" Height="5" VerticalAlignment="Center" Width="100" StrokeThickness="0" Fill="#99313131" RenderTransformOrigin="1,0.5" Margin="0,0,100,0">
<Rectangle.RenderTransform>
<RotateTransform Angle="-20"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<TextBlock TextWrapping="Wrap" Text="Download" HorizontalAlignment="Center"/>
<TextBlock x:Name="DL_TextRate" TextWrapping="Wrap" Text="0 MB/s" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5,0,5,0">
<Grid x:Name="UploadGrid" Height="200" Width="200">
<Grid>
<Grid x:Name="BlackObscure1" Height="134" Width="200" HorizontalAlignment="Right" VerticalAlignment="Top">
<Ellipse x:Name="BaseRing_Black1" Height="200" Stroke="Black" Width="200" StrokeThickness="5" HorizontalAlignment="Right"/>
</Grid>
</Grid>
<Grid HorizontalAlignment="Center" Height="200" VerticalAlignment="Center" Width="200">
<Grid x:Name="RedObscure1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="54" Height="136">
<Ellipse x:Name="BaseRing_Red1" HorizontalAlignment="Right" Height="200" Stroke="Red" VerticalAlignment="Top" Width="200" StrokeThickness="5"/>
</Grid>
</Grid>
<Rectangle x:Name="NeedleUL" HorizontalAlignment="Left" Height="5" VerticalAlignment="Center" Width="100" StrokeThickness="0" Fill="#99313131" RenderTransformOrigin="1,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="-20"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<TextBlock TextWrapping="Wrap" Text="Upload" HorizontalAlignment="Center"/>
<TextBlock x:Name="UL_TextRate" TextWrapping="Wrap" Text="0 MB/s" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Starlink_Desktop_Monitor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Timer t;
public MainWindow()
{
InitializeComponent();
PacketReciever pr = new PacketReciever(this);
byte[] statsSequence = new byte[] { 0, 0, 0, 0, 3, 0xE2, 0x3E, 0 };
t = new(new((x) => pr.Update(statsSequence)), null, 2000, 500); // Fire at a regular interval
}
public void UpdateDisplay(float download, float upload)
{
// Low Limit = -20 deg, high limit = -160 deg.
double dlRate = download / 367001600; // Get % of full gauge
double ulRate = upload / 52428800;
// Clamp values
if (ulRate > 1.0) ulRate = 1.0;
if (dlRate > 1.0) dlRate = 1.0;
// Apply an e^logx function to exaggerate smaller results
dlRate = Math.Pow( Math.E, 0.66 * Math.Log(dlRate));
ulRate = Math.Pow( Math.E, 0.66 * Math.Log(ulRate));
// Full range is 220 deg. (-20 -> -160)
double realDLDeg = dlRate * 220.0;
double realULDeg = ulRate * 220.0;
// Calc the true rot
realDLDeg -= 20;
realULDeg -= 20;
// Finally, if the rotation is actually greater than 180, correctly set it
if (realDLDeg > 180.0) realDLDeg = -160 - (realDLDeg - 180);
if (realULDeg > 180.0) realULDeg = -160 - (realULDeg - 180);
RotateTransform ulRotateTransform = new(realULDeg);
RotateTransform dlRotateTransform = new(realDLDeg);
DoubleAnimation ulRotAnim = new DoubleAnimation(realULDeg, new Duration(TimeSpan.FromMilliseconds(1500)));
DoubleAnimation dlRotAnim = new DoubleAnimation(realDLDeg, new Duration(TimeSpan.FromMilliseconds(1500)));
ulRotAnim.AccelerationRatio = 0.01;
dlRotAnim.AccelerationRatio = 0.01;
ulRotAnim.DecelerationRatio = 0.01;
dlRotAnim.DecelerationRatio = 0.01;
NeedleDL.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, dlRotAnim);
NeedleUL.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, ulRotAnim);
//NeedleDL.RenderTransform = dlRotateTransform;
//NeedleUL.RenderTransform = ulRotateTransform;
DL_TextRate.Text = string.Format("{0:0.000} {1}B/s", download / (download < 8e6f ? (8.0f * 1024.0f) : (8.0f * 1024.0f * 1024.0f)), download < 8e6 ? "k" : "M");
UL_TextRate.Text = string.Format("{0:0.000} {1}B/s", upload / (upload < 8e6f ? (8.0f * 1024.0f) : (8.0f * 1024.0f * 1024.0f)), upload < 8e6 ? "k" : "M");
}
}
class PacketReciever
{
MainWindow main;
readonly HttpClient client;
/// <summary>
/// List of known data tags
/// </summary>
static readonly List<byte[]> KnownTags = new()
{
new byte[] { 0xa5, 0x3f }, // BoresiteElevation
new byte[] { 0x9d, 0x3f }, // Boresite Azimuth
new byte[] { 0x8d, 0x3f }, // Ping
new byte[] { 0x85, 0x3f }, // Upload
new byte[] { 0xfd, 0x3e }, // Download
//new byte[] { 0xfd, 0x3f }, // Unknown
// ??? // Ping loss rate
};
public PacketReciever(MainWindow main)
{
this.main = main;
client = new();
client.DefaultRequestVersion = HttpVersion.Version11;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
}
public async void Update(byte[] requestContent)
{
try
{
// Create the request
ByteArrayContent content = new(requestContent);
// gRPC expects the content type to be a gRPC request, else will not respond with valid data
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/grpc-web+proto");
// Send the request
HttpResponseMessage r = await client.PostAsync("http://192.168.100.1:9201/SpaceX.API.Device.Device/Handle", content);
//Console.Clear();
Dictionary<string, byte[]> tagValues = new();
byte[] data = await r.Content.ReadAsByteArrayAsync();
int dataIndex = LastIndexOf(data, new byte[] { 0x67, 0x72, 0x70, 0x63, 0x2D, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3A });
while (dataIndex > -1) // Search for `grpc-status:`; is the known end of data
{
// Valid data packet, parse;
foreach (var item in KnownTags)
{
if (data[dataIndex] == item[0] && data[dataIndex + 1] == item[1])
{
byte[] dataBytes = new byte[] { data[dataIndex + 2], data[dataIndex + 3], data[dataIndex + 4], data[dataIndex + 5] };
tagValues.Add(string.Format("{0:X}{1:X}", item[0], item[1]), dataBytes);
break;
}
}
dataIndex--;
}
float download = tagValues.ContainsKey("FD3E") ? BitConverter.ToSingle(tagValues["FD3E"]) : 0.00f;
float upload = tagValues.ContainsKey("853F") ? BitConverter.ToSingle(tagValues["853F"]) : 0.00f;
/*Console.WriteLine(" DL: \t{0} b/s ({1:0.000} {2}B/s)", download, download / (download < 8e6f ? (8.0f * 1024.0f) : (8.0f * 1024.0f * 1024.0f)), download < 8e6 ? "k" : "M");
Console.WriteLine(" UL: \t{0} b/s ({1:0.000} {2}B/s)", upload, upload / (upload < 8e6f ? (8.0f * 1024.0f) : (8.0f * 1024.0f * 1024.0f)), upload < 8e6 ? "k" : "M");
Console.WriteLine(" Ping: \t{0} ms", tagValues.ContainsKey("8D3F") ? BitConverter.ToSingle(tagValues["8D3F"]) : 0.00);
Console.WriteLine(" Boresite Azimuth: \t{0}°", tagValues.ContainsKey("9D3F") ? BitConverter.ToSingle(tagValues["9D3F"]) : 0.00);
Console.WriteLine("Boresite Elevation: \t{0}°", tagValues.ContainsKey("A53F") ? BitConverter.ToSingle(tagValues["A53F"]) : 0.00);*/
Application.Current.Dispatcher.Invoke(() => { main.UpdateDisplay(download, upload); });
}
catch { }
}
public static int LastIndexOf(byte[] src, byte[] searchBytes)
{
if (src.Length <= searchBytes.Length) return -1;
int pos = src.Length - searchBytes.Length;
while (pos > -1 && !exactMatch(src, searchBytes, pos))
{
pos--;
}
return pos;
}
static bool exactMatch(byte[] src, byte[] search, int pos)
{
for (int i = 0; i < search.Length; i++)
{
if (src[pos + i] != search[i])
{
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<RootNamespace>Starlink_Desktop_Monitor</RootNamespace>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>