diff --git a/.gitignore b/.gitignore index 91757b6..0cc2e2a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ Apex7000_BillValidator_Test\obj\* Apex7000_BillValidator/obj/ Apex7000_BillValidator_Test/bin/ Apex7000_BillValidator_Test/obj/ +Apex7000_BillValidator/bin/ +API_Test/bin/ +API_Test/obj/ diff --git a/API_Test/API_Test.csproj b/API_Test/API_Test.csproj new file mode 100644 index 0000000..6344bde --- /dev/null +++ b/API_Test/API_Test.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + {71DEAB9A-CC67-4BD8-9FEC-C5E59ED2A75F} + Library + Properties + API_Test + API_Test + v4.5.1 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + {735220bb-d8e8-4e21-80d9-aea6e41b13ed} + Apex7000_BillValidator + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/API_Test/Properties/AssemblyInfo.cs b/API_Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..767c5f4 --- /dev/null +++ b/API_Test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("API_Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("API_Test")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4681deb4-b35c-4be8-a264-cc4d89b60051")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/API_Test/SlaveCodex_Test.cs b/API_Test/SlaveCodex_Test.cs new file mode 100644 index 0000000..9d81c05 --- /dev/null +++ b/API_Test/SlaveCodex_Test.cs @@ -0,0 +1,206 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Apex7000_BillValidator; + +namespace API_Test +{ + [TestClass] + public class SlaveCodex_Test + { + + [TestMethod] + public void TestToSlaveMessage() + { + byte[] testData; + + // Test the we return invalid command on empty data + testData = new byte[] { }; + + Assert.AreEqual(SlaveCodex.SlaveMessage.InvalidCommand, SlaveCodex.ToSlaveMessage(testData)); + + // Test the we return invalid command on too large of data + testData = new byte[12]; + + Assert.AreEqual(SlaveCodex.SlaveMessage.InvalidCommand, SlaveCodex.ToSlaveMessage(testData)); + } + + + [TestMethod] + public void TestGetState() + { + + States state; + SlaveCodex.SlaveMessage message; + byte[] testData; + + // Idling and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.Idling, state); + + // Accepting and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x02, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.Accepting, state); + + // Escrowed and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x04, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.Escrowed, state); + + // Stacking and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x8, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.Stacking, state); + + // Returning and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x20, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.Returning, state); + + // Jammed and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x00, 0x14, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.BillJammed, state); + + // Cashbox full and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x00, 0x18, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.StackerFull, state); + + // Acceptor Failure and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x00, 0x10, 0x04, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + state = SlaveCodex.GetState(message); + Assert.AreEqual(States.AcceptorFailure, state); + + Assert.IsTrue(SlaveCodex.IsCashboxPresent(message)); + + } + + [TestMethod] + public void TestGetEvent() + { + + Events events; + SlaveCodex.SlaveMessage message; + byte[] testData; + + // Idling and Stacked + testData = new byte[] { 0x02, 0x0B, 0x21, 0x11, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + events = SlaveCodex.GetEvents(message); + Assert.AreEqual(Events.Stacked, events); + + // Idling and returned + testData = new byte[] { 0x02, 0x0B, 0x21, 0x41, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + events = SlaveCodex.GetEvents(message); + Assert.AreEqual(Events.Returned, events); + + // Cheated and returning + testData = new byte[] { 0x02, 0x0B, 0x21, 0x20, 0x11, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + events = SlaveCodex.GetEvents(message); + Assert.AreEqual(Events.Cheated, events); + + // Rejected and cashbox present + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x12, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + events = SlaveCodex.GetEvents(message); + Assert.AreEqual(Events.BillRejected, events); + + // Power up + testData = new byte[] { 0x02, 0x0B, 0x21, 0x00, 0x00, 0x01, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + events = SlaveCodex.GetEvents(message); + Assert.AreEqual(Events.PowerUp, events); + } + + + [TestMethod] + public void TestGetCredit() + { + int credit; + SlaveCodex.SlaveMessage message; + byte[] testData; + + // None/Unknown + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x00, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(0, credit); + + // $1 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x08, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(1, credit); + + // $2 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x10, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(2, credit); + + // $5 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x18, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(3, credit); + + // $10 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x20, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(4, credit); + + // $20 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x28, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(5, credit); + + // $50 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x30, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(6, credit); + + // $100 + testData = new byte[] { 0x02, 0x0B, 0x21, 0x01, 0x10, 0x38, 0x00, 0x11, 0x11, 0x03, 0x3B }; + message = SlaveCodex.ToSlaveMessage(testData); + + credit = SlaveCodex.GetCredit(message); + Assert.AreEqual(7, credit); + } + + } +} diff --git a/Apex7000_BillValidator/Apex7000_BillValidator.csproj b/Apex7000_BillValidator/Apex7000_BillValidator.csproj index 0dbee9c..c7be45f 100644 --- a/Apex7000_BillValidator/Apex7000_BillValidator.csproj +++ b/Apex7000_BillValidator/Apex7000_BillValidator.csproj @@ -9,7 +9,7 @@ Properties Apex7000_BillValidator Apex7000_BillValidator - v4.0 + v3.5 512 @@ -21,6 +21,9 @@ DEBUG;TRACE prompt 4 + bin\Debug\Apex7000_BillValidator.XML + true + Off pdbonly @@ -31,20 +34,30 @@ 4 + + ..\packages\log4net.2.0.3\lib\net35-full\log4net.dll + True + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Apex7000_BillValidator_Test/App.xaml.cs b/Apex7000_BillValidator_Test/App.xaml.cs index b20efe5..7772c43 100644 --- a/Apex7000_BillValidator_Test/App.xaml.cs +++ b/Apex7000_BillValidator_Test/App.xaml.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; namespace Apex7000_BillValidator_Test { diff --git a/Apex7000_BillValidator_Test/BillBank_Sample.cs b/Apex7000_BillValidator_Test/BillBank_Sample.cs new file mode 100644 index 0000000..2e040fb --- /dev/null +++ b/Apex7000_BillValidator_Test/BillBank_Sample.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; + +namespace Apex7000_BillValidator_Test +{ + partial class MainWindow : INotifyPropertyChanged + { + #region Fields + private int bill1 = 0; + private int bill2 = 0; + private int bill3 = 0; + private int bill4 = 0; + private int bill5 = 0; + private int bill6 = 0; + private int bill7 = 0; + private int total = 0; + + private static Dictionary currencyMap = new Dictionary(); + private Dictionary cashbox = new Dictionary(); + #endregion + + // Configure our currency map + static MainWindow() + { + currencyMap.Add(1, 1); + currencyMap.Add(2, 2); + currencyMap.Add(3, 5); + currencyMap.Add(4, 10); + currencyMap.Add(5, 20); + currencyMap.Add(6, 50); + currencyMap.Add(7, 100); + } + + #region Properties + public int Bill1 + { + get { return bill1; } + set + { + bill1 = value; + NotifyPropertyChanged("Bill1"); + } + } + + public int Bill2 + { + get { return bill2; } + set + { + bill2 = value; + NotifyPropertyChanged("Bill2"); + } + } + + public int Bill3 + { + get { return bill3; } + set + { + bill3 = value; + NotifyPropertyChanged("Bill3"); + } + } + + public int Bill4 + { + get { return bill4; } + set + { + bill4 = value; + NotifyPropertyChanged("Bill4"); + } + } + + public int Bill5 + { + get { return bill5; } + set + { + bill5 = value; + NotifyPropertyChanged("Bill5"); + } + } + + public int Bill6 + { + get { return bill6; } + set + { + bill6 = value; + NotifyPropertyChanged("Bill6"); + } + } + + public int Bill7 + { + get { return bill7; } + set + { + bill7 = value; + NotifyPropertyChanged("Bill7"); + } + } + + public int Total + { + get { return total; } + set + { + total = value; + NotifyPropertyChanged("Total"); + } + } + #endregion + + /// + /// Adds credit to the specified slot, returns the denomination that was credited + /// + /// + /// + internal int AddCredit(int denom) + { + switch(denom) + { + case 1: + Bill1++; + break; + case 2: + Bill2++; + break; + case 3: + Bill3++; + break; + case 4: + Bill4++; + break; + case 5: + Bill5++; + break; + case 6: + Bill6++; + break; + case 7: + Bill7++; + break; + + default: + // Illegal value + return 0; + } + + // Return translated value and increment bill bank total + var val = currencyMap[denom]; + Total += val; + return val; + } + + + #region Private Helpers + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + + #endregion + + private void NotifyPropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + #endregion + } +} diff --git a/Apex7000_BillValidator_Test/CreditAndEscrow_Sample.cs b/Apex7000_BillValidator_Test/CreditAndEscrow_Sample.cs new file mode 100644 index 0000000..d785d05 --- /dev/null +++ b/Apex7000_BillValidator_Test/CreditAndEscrow_Sample.cs @@ -0,0 +1,111 @@ +using Apex7000_BillValidator; +using System; + +namespace Apex7000_BillValidator_Test +{ + /// + /// This class demonstrates how to handle the OnCredit Event + /// + partial class MainWindow + { + + + /// + /// If in escrow mode, check that we have the specified index enabled + /// + /// + /// + private void validator_OnEscrow(object sender, EscrowArgs e) + { + var index = e.Index; + + DoOnUIThread(() => + { + + string action = ""; + + // If bill is enabled by our mask, stack the note + bool isEnabled = checkEnableMask(index); + + // Here you could also a call to check the user's account balance to make sure they're not + // exceeding a specified amount. Remember, returns and rejects can be triggered by a few things: + // 1) Reject : Invalid note + // 2) Reject : Cheat attemp + // 3) Return : Note disabled by E/D mask + // 4) Return : Host manually send return message because a check failed (e.g. too much money on user account etc.) + + + if (isEnabled) + { + // Pass Escrow state to UI + State = States.Escrowed; + action = "Escrowed"; + validator.Stack(); + } + else + { + action = "Rejected"; + validator.Reject(); + } + + + if (currencyMap.ContainsKey(index)) + Console.WriteLine("{0} ${1}", action, currencyMap[index]); + else + Console.WriteLine("{0} Unknown denomination index: {1}", action, index); + + + }); + } + + + + /// + /// On credit, add the val to our bill bank. + /// + /// + /// + private void validator_OnCredit(object sender, CreditArgs e) + { + var denomination = e.Index; + if (currencyMap.ContainsKey(denomination)) + { + if (denomination > 0) + Console.WriteLine("Credited ${0}", AddCredit(denomination)); + else + Console.WriteLine("Failed to credit: {0}", denomination); + } + } + + + /// + /// Checks if the specified index is enabled by our checkboxes. This could also be a call to + /// a remote system or any other check-pass/fail process. + /// + /// + /// + private bool checkEnableMask(int index) + { + switch (index) + { + case 1: + return chk1.IsChecked.Value; + case 2: + return chk2.IsChecked.Value; + case 3: + return chk3.IsChecked.Value; + case 4: + return chk4.IsChecked.Value; + case 5: + return chk5.IsChecked.Value; + case 6: + return chk6.IsChecked.Value; + case 7: + return chk7.IsChecked.Value; + + default: + return false; + } + } + } +} diff --git a/Apex7000_BillValidator_Test/DebugData_Sample.cs b/Apex7000_BillValidator_Test/DebugData_Sample.cs new file mode 100644 index 0000000..9a37764 --- /dev/null +++ b/Apex7000_BillValidator_Test/DebugData_Sample.cs @@ -0,0 +1,89 @@ +using Apex7000_BillValidator; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; + +namespace Apex7000_BillValidator_Test +{ + /// + /// Demonstrates how to make use of the debug data + /// + partial class MainWindow + { + + private FixedObservableLinkedList debugQueueMaster = new FixedObservableLinkedList(20); + private FixedObservableLinkedList debugQueueSlave = new FixedObservableLinkedList(20); + + /// + /// On receipt of a debug entry, add the entry to our UI console + /// + /// + /// + void config_OnSerialData(object sender, DebugEntryArgs e) + { + var entry = e.Entry; + DoOnUIThread(() => + { + if (entry.Flow == Flows.Master) + { + debugQueueMaster.Add(entry); + + ConsoleLoggerMaster.ScrollIntoView(entry); + } + else + { + debugQueueSlave.Add(entry); + + ConsoleLoggerSlave.ScrollIntoView(entry); + } + }); + } + } + + /// + /// Used for the debug console view, we limit the number of entries that our list contains. This + /// avoids out of memory exceptions if you were to leave this running overnight at a fast poll rate. + /// + /// + internal class FixedObservableLinkedList : LinkedList, INotifyCollectionChanged + { + private readonly object syncObject = new object(); + + public int Size { get; private set; } + + public FixedObservableLinkedList(int size) + { + Size = size; + } + + /// + /// Adds elements to the head of the list so when bound to a UI element, + /// the latest entry is on top + /// + /// + public void Add(T obj) + { + AddFirst(obj); + lock (syncObject) + { + while (Count > Size) + { + RemoveLast(); + } + } + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, null)); + } + + public event NotifyCollectionChangedEventHandler CollectionChanged; + private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) + { + App.Current.Dispatcher.Invoke((Action)delegate + { + if (CollectionChanged != null) + CollectionChanged(this, args); + }); + } + } +} diff --git a/Apex7000_BillValidator_Test/MainWindow.xaml b/Apex7000_BillValidator_Test/MainWindow.xaml index 326b8e1..494ad3e 100644 --- a/Apex7000_BillValidator_Test/MainWindow.xaml +++ b/Apex7000_BillValidator_Test/MainWindow.xaml @@ -1,8 +1,231 @@  - - - + Title="RS-232 Sample Application" Height="650" Width="800" SnapsToDevicePixels="True"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Apex7000_BillValidator_Test/MainWindow.xaml.cs b/Apex7000_BillValidator_Test/MainWindow.xaml.cs index 9acfe80..14e6e15 100644 --- a/Apex7000_BillValidator_Test/MainWindow.xaml.cs +++ b/Apex7000_BillValidator_Test/MainWindow.xaml.cs @@ -1,18 +1,8 @@ -using System; +using Apex7000_BillValidator; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -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.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using Apex7000_BillValidator; namespace Apex7000_BillValidator_Test { @@ -21,55 +11,70 @@ namespace Apex7000_BillValidator_Test /// public partial class MainWindow : Window { - public ApexValidator validator; + private ApexValidator validator; + private RS232Config config; + + + public MainWindow() { + DataContext = this; InitializeComponent(); - Loaded += MainWindow_Loaded; } - void MainWindow_Loaded(object sender, RoutedEventArgs e) - { - //validator = new ApexValidator(COMPort.COM10, "en-US"); - validator = new ApexValidator(COMPort.COM2); - validator.PowerUp += validator_PowerUp; - validator.OnEscrow += validator_OnEscrow; - validator.BillStacked += validator_BillStacked; - validator.OnError += validator_OnError; - validator.CashboxAttached += validator_CashboxAttached; - validator.CashboxRemoved += validator_CashboxRemoved; - - validator.Connect(); - } - void validator_OnError(object sender, ErrorTypes type) + + /// Simple UI listeners + + private void btnReset_Click(object sender, RoutedEventArgs e) { - Console.WriteLine("Error has occured: {0}", type.ToString()); + if (validator != null) + { + validator.RequestReset(); + } } - void validator_CashboxRemoved(object sender, EventArgs e) + + private void chkEscrowMode_Checked(object sender, RoutedEventArgs e) { - Console.WriteLine("Box removed"); + IsEscrowMode = true; } - void validator_CashboxAttached(object sender, EventArgs e) + private void chkEscrowMode_Unchecked(object sender, RoutedEventArgs e) { - Console.WriteLine("Box Attached"); + IsEscrowMode = false; } - void validator_BillStacked(object sender, EventArgs e) - { - Console.WriteLine("Bill Stacked"); + private void AvailablePorts_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) + { + AvailablePorts.ItemsSource = ApexValidator.GetAvailablePorts(); } - void validator_OnEscrow(object sender, int denomination) + private void AvailablePorts_Loaded(object sender, RoutedEventArgs e) { - validator.Stack(); + AvailablePorts.ItemsSource = ApexValidator.GetAvailablePorts(); } - void validator_PowerUp(object sender, EventArgs e) + private void ed_Changed(object sender, RoutedEventArgs e) { - - } + // Avoids npe on startup + if (config == null) + return; + + int mask = 0; + + // Could be done with data bindings but why bother when bits are so much fun? + mask |= chk1.IsChecked.Value ? 1 << 0 : 0; + mask |= chk2.IsChecked.Value ? 1 << 1 : 0; + mask |= chk3.IsChecked.Value ? 1 << 2 : 0; + mask |= chk4.IsChecked.Value ? 1 << 3 : 0; + mask |= chk5.IsChecked.Value ? 1 << 4 : 0; + mask |= chk6.IsChecked.Value ? 1 << 5 : 0; + mask |= chk7.IsChecked.Value ? 1 << 6 : 0; + + config.EnableMask = (byte)mask; + } + } + } diff --git a/Apex7000_BillValidator_Test/ObservableModel_Sample.cs b/Apex7000_BillValidator_Test/ObservableModel_Sample.cs new file mode 100644 index 0000000..d25b715 --- /dev/null +++ b/Apex7000_BillValidator_Test/ObservableModel_Sample.cs @@ -0,0 +1,258 @@ +using Apex7000_BillValidator; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace Apex7000_BillValidator_Test +{ + internal enum TagTypes + { + NonEmptyTags, + Events, + States + } + + + /// + /// This class demonstrates some databinding techniques for illustrating state and events. + /// + partial class MainWindow : Window, INotifyPropertyChanged + { + private static SolidColorBrush inactive = new SolidColorBrush(Colors.LightGray); + private static SolidColorBrush cashboxOkay = new SolidColorBrush(Colors.LightYellow); + private static SolidColorBrush activeError = new SolidColorBrush(Colors.LightPink); + private static SolidColorBrush activeEvent = new SolidColorBrush(Colors.LightGreen); + private static SolidColorBrush activeState = new SolidColorBrush(Colors.LightBlue); + + #region Fields + private string _portName = ""; + private States _state = States.Offline; + private Events _event = Events.None; + + private bool _isEscrowMode = false; + private bool _isConnected = false; + #endregion + + #region Properties + public string PortName + { + get { return _portName; } + set + { + _portName = value; + NotifyPropertyChanged("PortName"); + } + } + + public States State + { + get { return _state; } + set + { + DoOnUIThread(() => + { + switch (value) + { + case States.Idling: + setState(btnIdle); + break; + case States.Accepting: + setState(btnAccepting); + break; + case States.Escrowed: + setState(btnEscrowed); + break; + case States.Stacking: + setState(btnStacking); + break; + case States.Returning: + setState(btnReturning); + break; + case States.BillJammed: + setState(btnBillJammed); + break; + case States.StackerFull: + setState(btnStackerFull); + break; + case States.AcceptorFailure: + setState(btnFailure); + break; + } + + }); + + _state = value; + NotifyPropertyChanged("State"); + } + } + + public Events Event + { + get { return _event; } + set + { + DoOnUIThread(() => + { + if ((_event & (Events.Returned | Events.Stacked | Events.BillRejected | Events.Cheated)) != 0) + { + clearTags(TagTypes.NonEmptyTags); + } + }); + + switch (value) + { + case Events.BillRejected: + setEvent(btnRejected); + break; + case Events.Cheated: + setEvent(btnCheated); + break; + case Events.PowerUp: + Console.WriteLine("Powered Up"); + break; + case Events.Returned: + setEvent(btnReturned); + break; + case Events.Stacked: + setEvent(btnStacked); + break; + + default: + setEvent(null); + break; + } + + _event = value; + } + } + + public bool IsEscrowMode + { + get + { + if (config != null) + return config.IsEscrowMode; + else + return _isEscrowMode; + } + set + { + if (config != null) + config.IsEscrowMode = value; + else + _isEscrowMode = value; + NotifyPropertyChanged("IsEscrowMode"); + } + } + + public bool IsConnected + { + get { return _isConnected; } + set + { + _isConnected = value; + NotifyPropertyChanged("IsConnected"); + NotifyPropertyChanged("IsNotConnected"); + } + } + + public bool IsNotConnected + { + get { return !IsConnected; } + } + #endregion + + /// + /// Sets the state tag as active while clearing all other state tags + /// + /// + private void setState(Button target) + { + DoOnUIThread(() => + { + if (target == btnCB) + target.Background = cashboxOkay; + else + target.Background = activeState; + }); + } + + /// + /// Sets an event as active + /// + /// + private void setEvent(Button target) + { + DoOnUIThread(() => + { + if (target != null) + { + target.Background = activeEvent; + + } + else + clearTags(TagTypes.Events); + }); + } + + /// + /// Sets an error as active + /// + /// + private void setError(Button target) + { + DoOnUIThread(() => + { + clearTags(TagTypes.NonEmptyTags); + target.Background = activeError; + }); + } + + /// + /// Resets all state tags back to lightGrey. Must be called from UI thread. + /// + private void clearTags(TagTypes type) + { + var tag = ""; + IEnumerable