1
0
Fork 0
Browse Source

2021-05-03 Snapshot.

master
Craig Oates 3 years ago
parent
commit
21ead57d15
  1. 6
      src/EyesAndEars.UWP/EyesAndEars.UWP/EyesAndEars.UWP.csproj
  2. 90
      src/EyesAndEars.UWP/EyesAndEars.UWP/MainPage.xaml
  3. 27
      src/EyesAndEars.UWP/EyesAndEars.UWP/MainPage.xaml.cs
  4. 2
      src/EyesAndEars.UWP/EyesAndEars.UWP/Package.appxmanifest
  5. 126
      src/EyesAndEars.UWP/EyesAndEars.UWP/Services/DataServices.cs
  6. 2
      src/EyesAndEars.UWP/EyesAndEars.UWP/ViewModels/MainPageVM.cs

6
src/EyesAndEars.UWP/EyesAndEars.UWP/EyesAndEars.UWP.csproj

@ -19,9 +19,9 @@
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<PackageCertificateKeyFile>EyesAndEars.UWP_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>
</PackageCertificateThumbprint>
<PackageCertificateKeyFile>
</PackageCertificateKeyFile>
<PackageCertificateThumbprint>DAE20EE5240091F7E98C03948A35781171CB1005</PackageCertificateThumbprint>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<GenerateTestArtifacts>True</GenerateTestArtifacts>

90
src/EyesAndEars.UWP/EyesAndEars.UWP/MainPage.xaml

@ -12,6 +12,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="96"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
@ -25,10 +26,17 @@
Text="{x:Bind _vm.CurrentTime, Mode=OneWay, FallbackValue=00}"
Margin="0" Padding="0"/>
<StackPanel Grid.Row="0" Orientation="Horizontal"
<Rectangle Fill="White" Width="92" Height="92" HorizontalAlignment="Left"
RadiusX="46" RadiusY="46"
/>
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="2,0,0,0"
VerticalAlignment="Top">
<MediaElement Name="AudioUpdater" AutoPlay="True"/>
<Image Grid.Column="0" Width="88" Height="88" VerticalAlignment="Center"
Source="Images\logo.png"/>
<StackPanel Padding="8,0">
<TextBlock Text="Return to Ritherdon Project" FontSize="40"/>
<StackPanel Orientation="Horizontal">
@ -40,7 +48,7 @@
</StackPanel>
</StackPanel>
<Grid Grid.Row="1" Margin="0,12">
<Grid Grid.Row="1" Margin="0,12,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
@ -55,7 +63,8 @@
<Grid x:Name="Factory1Grid" Grid.Row="0" Grid.Column="0"
Background="{x:Bind _vm.Device1.StatusColour, Mode=OneWay,
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="300">
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="300"
CornerRadius="10">
<StackPanel Margin="12" VerticalAlignment="Stretch">
<TextBlock x:Name="Factory1Time"
Text="{x:Bind _vm.Device1.LatestReading.time,
@ -72,7 +81,8 @@
<Grid x:Name="Factory2Grid" Grid.Row="0" Grid.Column="1"
Background="{x:Bind _vm.Device2.StatusColour, Mode=OneWay,
FallbackValue=Orange}" Margin="12,0,12,12" Width="300" Height="300">
FallbackValue=Orange}" Margin="12,0,12,12" Width="300" Height="300"
CornerRadius="10">
<StackPanel Margin="12" VerticalAlignment="Stretch">
<TextBlock x:Name="Factory2Time" Foreground="White" FontSize="24"
Text="{x:Bind _vm.Device2.LatestReading.time,
@ -88,28 +98,33 @@
<Grid Grid.Row="0" Grid.Column="2" Grid.RowSpan="2">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Rectangle Fill="LightSeaGreen" Width="92" Height="52"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<Rectangle Fill="LightSeaGreen" Width="92" Height="52"
RadiusX="5" RadiusY="5"/>
<TextBlock Text="Device is on" FontSize="42"
VerticalAlignment="Center" Margin="12,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="DarkSeaGreen" Width="92" Height="52"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<Rectangle Fill="DarkSeaGreen" Width="92" Height="52"
RadiusX="5" RadiusY="5"/>
<TextBlock Text="Welding detected" FontSize="42"
VerticalAlignment="Center" Margin="12,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="LightSkyBlue" Width="92" Height="52"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<Rectangle Fill="LightSkyBlue" Width="92" Height="52"
RadiusX="5" RadiusY="5"/>
<TextBlock Text="Low light in factory" FontSize="42"
VerticalAlignment="Center" Margin="12,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="DarkOrange" Width="92" Height="52"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<Rectangle Fill="DarkOrange" Width="92" Height="52"
RadiusX="5" RadiusY="5"/>
<TextBlock Text="Unable to retrieve data" FontSize="42"
VerticalAlignment="Center" Margin="12,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="DarkRed" Width="92" Height="52"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5">
<Rectangle Fill="DarkRed" Width="92" Height="52"
RadiusX="5" RadiusY="5"/>
<TextBlock Text="Device is off" FontSize="42"
VerticalAlignment="Center" Margin="12,0"/>
</StackPanel>
@ -120,8 +135,8 @@
<TextBlock Text="Dashboard updates at slower rate than devices."
FontSize="18" Margin="0" Foreground="SlateGray"
VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
</Grid>
<!-- This device is not in use. Uncomment if becomes available. -->
<!--<Grid x:Name="Factory3Grid" Grid.Row="0" Grid.Column="2"
@ -143,7 +158,8 @@
<Grid x:Name="Gallery1Grid" Grid.Row="1" Grid.Column="0"
Background="{x:Bind _vm.Device4.StatusColour, Mode=OneWay,
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="150">
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="150"
CornerRadius="10">
<StackPanel Margin="12" VerticalAlignment="Bottom">
<TextBlock x:Name="Gallery1Time" Foreground="White"
Text="{x:Bind _vm.Device4.LatestStatus.time,
@ -159,7 +175,8 @@
<Grid x:Name="Gallery2Grid" Grid.Row="1" Grid.Column="1"
Background="{x:Bind _vm.Device5.StatusColour, Mode=OneWay,
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="150">
FallbackValue=Pink}" Margin="0,0,0,12" Width="300" Height="150"
CornerRadius="10">
<StackPanel Margin="12" VerticalAlignment="Bottom">
<TextBlock x:Name="Gallery2Time" Foreground="White" FontSize="24"
Text="{x:Bind _vm.Device5.LatestStatus.time,
@ -193,33 +210,52 @@
</Grid>
<Grid Grid.Row="2" Margin="0">
<Grid Grid.Row="2" Margin="0,0,0,8">
<ScrollViewer x:Name="LogViewer" VerticalScrollBarVisibility="Visible"
HorizontalScrollMode="Disabled" Margin="0"
VerticalScrollMode="Enabled">
<RichTextBlock x:Name="Logs" FontSize="16" FontFamily="Consolas">
</RichTextBlock>
</ScrollViewer>
</Grid>
<Grid Grid.Row="3" Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="113"/>
<ColumnDefinition Width="45"/>
<ColumnDefinition Width="*" MinWidth="350"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<HyperlinkButton x:Name="InfoButton" Grid.Column="0"
<StackPanel Orientation="Horizontal" Grid.Column="0" Grid.ColumnSpan="2">
<ToggleButton x:Name="LogToggle" FontFamily="Segoe MDL2 Assets"
Content="&#xE8BC;" HorizontalAlignment="Right"
VerticalAlignment="Top" FontSize="28"
Height="79" Width="79"
Unchecked="LogToggle_Unchecked"
Checked="LogToggle_Checked"
IsChecked="False"/>
<HyperlinkButton x:Name="InfoButton" Grid.Column="0"
NavigateUri="http://www.nicolaellis.com"
FontFamily="Segoe MDL2 Assets" Content="&#xE946;"
Height="79" Width="79" VerticalAlignment="Center"
HorizontalAlignment="Left" FontSize="28"
ToolTipService.Placement="Mouse"
ToolTipService.ToolTip="This is a link to a webpage with information about Nicola and the project."/>
</StackPanel>
<TextBox x:Name="WebAddressBox" Grid.Column="1" FontSize="26"
Text="{x:Bind _vm.BaseURL , Mode=TwoWay}"
Padding="20" TextAlignment="Left"
HorizontalAlignment="Stretch" TextWrapping="NoWrap"
Margin="0" VerticalAlignment="Center"
<TextBox x:Name="WebAddressBox" Grid.Column="2" FontSize="26"
Text="{x:Bind _vm.BaseURL, Mode=TwoWay}"
Padding="20" TextAlignment="Left" TextWrapping="NoWrap" VerticalAlignment="Center"
HorizontalContentAlignment="Left"
ToolTipService.Placement="Mouse"
ToolTipService.ToolTip="The base U.R.L. used to form the A.P.I. queries."
PlaceholderText="Enter the base U.R.L. here..." />
<StackPanel Orientation="Horizontal" Grid.Column="2">
<StackPanel Orientation="Horizontal" Grid.Column="3">
<ToggleButton x:Name="PlayButton" FontFamily="Segoe MDL2 Assets"
Content="&#xE71A;" Height="79" Width="79"
VerticalAlignment="Center" FontSize="28"

27
src/EyesAndEars.UWP/EyesAndEars.UWP/MainPage.xaml.cs

@ -2,6 +2,7 @@
using EyesAndEars.UWP.ViewModels;
using System;
using Windows.ApplicationModel;
using Windows.Media.SpeechSynthesis;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
@ -11,6 +12,7 @@ namespace EyesAndEars.UWP {
MainPageVM _vm = new MainPageVM();
DispatcherTimer _dispatcherTimer = new DispatcherTimer();
bool _logData;
public MainPage() {
InitializeComponent();
@ -35,7 +37,7 @@ namespace EyesAndEars.UWP {
_vm.Device4 = DataServices.CreateFallBackDevice(4);
_vm.Device5 = DataServices.CreateFallBackDevice(5);
// _vm.Device6 = DataServices.CreateFallBackDevice(6);
_vm.CurrentTime = DateTime.UtcNow.ToShortTimeString();
_vm.CurrentTime = DataServices.SetCurrentTime();
DataContext = _vm;
}
@ -50,13 +52,17 @@ namespace EyesAndEars.UWP {
var url = _vm.BaseURL;
if (!string.IsNullOrEmpty(url)) {
// Devices 3 and 6 are not in use.
_vm.Device1 = await DataServices.UpdateDevice(url, 1);
_vm.Device2 = await DataServices.UpdateDevice(url, 2);
_vm.Device1 = await DataServices.UpdateDevice
(url, 1, Logs, _vm.Device1.LatestStatus.status, AudioUpdater, _logData);
_vm.Device2 = await DataServices.UpdateDevice
(url, 2, Logs, _vm.Device2.LatestStatus.status, AudioUpdater, _logData);
// _vm.Device3 = await DataServices.UpdateDevice(url, 3);
_vm.Device4 = await DataServices.UpdateDevice(url, 4);
_vm.Device5 = await DataServices.UpdateDevice(url, 5);
_vm.Device4 = await DataServices.UpdateDevice
(url, 4, Logs, _vm.Device4.LatestStatus.status, AudioUpdater, _logData);
_vm.Device5 = await DataServices.UpdateDevice
(url, 5, Logs, _vm.Device5.LatestStatus.status, AudioUpdater, _logData);
// _vm.Device6 = await DataServices.UpdateDevice(url, 6);
_vm.CurrentTime = DateTime.UtcNow.ToShortTimeString();
_vm.CurrentTime = DataServices.SetCurrentTime();
}
else {
IntialiseDataContext();
@ -76,5 +82,14 @@ namespace EyesAndEars.UWP {
PlayButton.Content = "\uE71A";
_dispatcherTimer.Start();
}
private void LogToggle_Unchecked(object sender, RoutedEventArgs e) {
_logData = false;
Logs.Blocks.Clear();
}
private void LogToggle_Checked(object sender, RoutedEventArgs e) {
_logData = true;
}
}
}

2
src/EyesAndEars.UWP/EyesAndEars.UWP/Package.appxmanifest

@ -9,7 +9,7 @@
<Identity
Name="55acd946-60d4-4776-b6c6-03fef750e3da"
Publisher="CN=Craig Oates"
Version="2020.1.14.0" />
Version="2021.5.3.0" />
<mp:PhoneIdentity PhoneProductId="55acd946-60d4-4776-b6c6-03fef750e3da" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

126
src/EyesAndEars.UWP/EyesAndEars.UWP/Services/DataServices.cs

@ -6,11 +6,25 @@ using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Documents;
using Windows.UI.Text;
using Windows.Media.SpeechSynthesis;
namespace EyesAndEars.UWP.Services {
public static class DataServices {
public static async Task<Device> UpdateDevice(string url, int deviceId) {
static SpeechSynthesizer _synth = new SpeechSynthesizer();
public static string SetCurrentTime() {
var zone = TimeZoneInfo.Local;
var britishZone = TimeZoneInfo.FindSystemTimeZoneById(zone.Id);
var newDate = TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.Local, britishZone);
return newDate.ToShortTimeString();
}
public static async Task<Device> UpdateDevice(string url, int deviceId,
RichTextBlock logs, string currentStatus, MediaElement audioUpdater, bool _logData) {
try {
var id = MapFactoryDeviceToGalleyDevice(deviceId); // Has note.
var readingAPI = $"{url}/api/readings/latest/{id}";
@ -19,8 +33,11 @@ namespace EyesAndEars.UWP.Services {
var statusJSON = await WebServices.GetJSON(statusAPI);
var r = MapToLightReading(readingJSON);
var s = MapToDeviceStatus(statusJSON);
var c = UpdateStatusColour(s.status, r.reading);
return new Device(deviceId, r, s, c);
var c = UpdateStatusColour(deviceId, s.status, r.reading);
var dev = new Device(deviceId, r, s, c);
if(_logData == true) LogUpdate(logs, dev);
NotifyAnyStatusChanges(currentStatus, dev, audioUpdater);
return dev;
}
catch (Exception e) {
Debug.WriteLine(e.Message);
@ -28,38 +45,89 @@ namespace EyesAndEars.UWP.Services {
}
}
static SolidColorBrush UpdateStatusColour(string status, int reading) {
private static async void NotifyAnyStatusChanges(string currentStatus,
Device dev, MediaElement audioUpdater) {
if (currentStatus.Equals
(dev.LatestStatus.status, StringComparison.InvariantCulture)
!= true) {
var stream = await _synth.SynthesizeTextToStreamAsync
($"{TranslateDeviceIdToDeviceName(dev)} {dev.LatestStatus.status}");
audioUpdater.SetSource(stream, stream.ContentType);
audioUpdater.Play();
}
}
private static string TranslateDeviceIdToDeviceName(Device dev) {
if (dev.Id == 1) return "factory1";
else if (dev.Id == 2) return "factory2";
else if (dev.Id == 4) return "gallery1";
else return "gallery2";
}
private static void LogUpdate(RichTextBlock logs, Device dev) {
// Devices 3 and 6 are not in use.
// string device = TranslateDeviceIdToDeviceName(dev);
Paragraph paragraph = new Paragraph();
var run1 = new Run {
FontWeight = FontWeights.Bold,
Text = $"{DateTime.Now} | "
};
var run2 = new Run {
Foreground = dev.StatusColour,
FontWeight = FontWeights.Bold,
Text = TranslateDeviceIdToDeviceName(dev)
};
var run3 = new Run {
Foreground = dev.StatusColour,
Text = $" | {dev.LatestReading.id} | {dev.LatestReading.reading} | " +
$"{dev.LatestStatus.status} | {dev.LatestReading.time}"
};
paragraph.Inlines.Add(run1);
paragraph.Inlines.Add(run2);
paragraph.Inlines.Add(run3);
logs.Blocks.Insert(0, paragraph);
}
private static SolidColorBrush UpdateStatusColour(int device, string status, int reading) {
try {
if (status.Equals("on", StringComparison.OrdinalIgnoreCase)) {
/* Note: Reading values breakdown.
* =======================================
* 1. When testing the light meters, the base line for normal
* light is 48 or below. Anything above this is when one of
* the guys in the factory was welding. Becuase of this,
* I have set 0 to 48 as the 'default' status on the
* dashboard.
*
* 2. During testing we noticed the light meters would
* return 'negative light' values. There is a reason for
* this but that is out of the scope of this project. This
* project just needs to process the data. The negative
* light values are when the lights in the factory are off.
* The light meter is still running but there is no light
* to measure. So, everything is fine but it looks broken.
* The 'LightSkyBlue' colour is used to help relay this
* bit of information.
*/
if (reading > 0 && reading < 48) // On but no weld detected.
return new SolidColorBrush(Colors.LightSeaGreen);
if (reading > 48) // On and weld detected.
return new SolidColorBrush(Colors.DarkSeaGreen);
else {
// On but factory lights are off.
/* Note: 'Negative Light' Levels.
* ========================================================
* The light meters will record 'negative light' values
* when the factory lights are off. This does not mean
* the light meters are not functioning properly. With that
* said, this dashboard make it look like they are. Because
* of this, the blocks in the dashboard will change to
* 'LightSkyBlue' to help indicate the change is something
* the system knows about and everything is fine -- nothing
* is broken.
*/
if (device == 1) {
if (reading > 0 && reading <= 39) // No weld detected.
return new SolidColorBrush(Colors.LightSeaGreen);
if (reading > 38) // Weld detected.
return new SolidColorBrush(Colors.DarkSeaGreen);
}
else if (device == 2) {
if (reading > 0 && reading <= 48) // No weld detected.
return new SolidColorBrush(Colors.LightSeaGreen);
if (reading > 48) // Weld detected.
return new SolidColorBrush(Colors.DarkSeaGreen);
}
else if (reading < 0) {
// The device is on but factory lights are off.
return new SolidColorBrush(Colors.LightSkyBlue);
}
// Indicate the gallery relays are on.
return new SolidColorBrush(Colors.LightSeaGreen);
}
else return new SolidColorBrush(Colors.DarkRed); }
// The device is off.
return new SolidColorBrush(Colors.DarkRed);
}
catch (Exception e) {
// Extra protection to if-check at top of this try block.
Debug.WriteLine(e.Message);
return new SolidColorBrush(Colors.DarkOrange);
}

2
src/EyesAndEars.UWP/EyesAndEars.UWP/ViewModels/MainPageVM.cs

@ -26,7 +26,7 @@ namespace EyesAndEars.UWP.ViewModels {
Device4 = g1;
Device5 = g2;
Device6 = g3;
CurrentTime = DateTime.Now.ToShortTimeString();
CurrentTime = "Not Set";
}
string _currentTime;