├── IntegrationDemo.deck ├── res ├── demo-enter-pin.png └── authorize-app-popup.png ├── .gitignore ├── demos ├── net_wrapper │ ├── lib │ │ ├── MatricIntegration.dll │ │ └── MatricIntegration.pdb │ ├── packages.config │ ├── App.config │ ├── IntegrationDemoCSWrapper.csproj.user │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── IntegrationDemoCSWrapper.csproj │ └── Program.cs └── raw │ ├── packages.config │ ├── App.config │ ├── DemoRaw.csproj.user │ ├── Properties │ └── AssemblyInfo.cs │ ├── DemoRaw.csproj │ ├── Program.cs │ └── DemoIntegrationHelper.cs ├── DemoCommon.cs ├── IntegrationDemo.sln └── README.md /IntegrationDemo.deck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgudelj/MATRICIntegrationDemo/HEAD/IntegrationDemo.deck -------------------------------------------------------------------------------- /res/demo-enter-pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgudelj/MATRICIntegrationDemo/HEAD/res/demo-enter-pin.png -------------------------------------------------------------------------------- /res/authorize-app-popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgudelj/MATRICIntegrationDemo/HEAD/res/authorize-app-popup.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /packages 2 | /demos/net_wrapper/obj 3 | /demos/net_wrapper/bin 4 | /demos/raw/bin 5 | /demos/raw/obj 6 | .vs 7 | -------------------------------------------------------------------------------- /demos/net_wrapper/lib/MatricIntegration.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgudelj/MATRICIntegrationDemo/HEAD/demos/net_wrapper/lib/MatricIntegration.dll -------------------------------------------------------------------------------- /demos/net_wrapper/lib/MatricIntegration.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgudelj/MATRICIntegrationDemo/HEAD/demos/net_wrapper/lib/MatricIntegration.pdb -------------------------------------------------------------------------------- /demos/raw/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /demos/net_wrapper/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /demos/raw/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demos/net_wrapper/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demos/raw/DemoRaw.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ProjectFiles 5 | 6 | -------------------------------------------------------------------------------- /demos/net_wrapper/IntegrationDemoCSWrapper.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ShowAllFiles 5 | 6 | -------------------------------------------------------------------------------- /DemoCommon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace IntegrationDemo { 3 | public static class CONST 4 | { 5 | public static string DEMO_DECK_ID = "7f18056c-7a2a-46ac-9956-662e7d0b78ec"; 6 | public static string SMILE_WINK = "😉"; 7 | public static string APP_NAME = "MATRIC Integration Demo"; 8 | public static int API_PORT = 50300; 9 | public static string PIN = "0450"; 10 | } 11 | 12 | public static class DemoPages 13 | { 14 | public static string SEMAPHORE = "00d9c649-f2df-405f-abfd-06d38f8626be"; 15 | public static string SHIELDS_AND_WEAPONS = "16856457-d2f8-405e-927e-749b1dc7d7ec"; 16 | public static string DEMO_COMPLETE = "b0a0b559-9e2c-42af-9c64-95951ef09cbd"; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /demos/raw/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("IntegrationDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IntegrationDemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d84ec5c4-6daa-4131-b2e3-5edadc5d3b32")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.1.0.0")] 36 | [assembly: AssemblyFileVersion("1.1.0.0")] 37 | -------------------------------------------------------------------------------- /demos/net_wrapper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("IntegrationDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IntegrationDemo")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d84ec5c4-6daa-4131-b2e3-5edadc5d3b32")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /IntegrationDemo.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32112.339 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoRaw", "demos\raw\DemoRaw.csproj", "{99839985-31B8-4FD2-947E-CD66E76046E5}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationDemoCSWrapper", "demos\net_wrapper\IntegrationDemoCSWrapper.csproj", "{D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9F8AC669-FE67-4F4D-94C8-6455C61D6ACD}" 11 | ProjectSection(SolutionItems) = preProject 12 | DemoCommon.cs = DemoCommon.cs 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Debug|x64 = Debug|x64 19 | Release|Any CPU = Release|Any CPU 20 | Release|x64 = Release|x64 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Debug|x64.ActiveCfg = Debug|x64 26 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Debug|x64.Build.0 = Debug|x64 27 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Release|x64.ActiveCfg = Release|x64 30 | {99839985-31B8-4FD2-947E-CD66E76046E5}.Release|x64.Build.0 = Release|x64 31 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Debug|x64.ActiveCfg = Debug|x64 34 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Debug|x64.Build.0 = Debug|x64 35 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Release|x64.ActiveCfg = Release|x64 38 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32}.Release|x64.Build.0 = Release|x64 39 | EndGlobalSection 40 | GlobalSection(SolutionProperties) = preSolution 41 | HideSolutionNode = FALSE 42 | EndGlobalSection 43 | GlobalSection(ExtensibilityGlobals) = postSolution 44 | SolutionGuid = {15101259-A543-4F92-A4A0-580D6D497CE7} 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /demos/raw/DemoRaw.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {99839985-31B8-4FD2-947E-CD66E76046E5} 8 | Exe 9 | IntegrationDemo 10 | IntegrationDemo 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | bin\x64\Debug\ 39 | DEBUG;TRACE 40 | full 41 | x64 42 | 7.3 43 | prompt 44 | true 45 | 46 | 47 | bin\x64\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x64 52 | 7.3 53 | prompt 54 | true 55 | 56 | 57 | 58 | ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | DemoCommon.cs 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /demos/net_wrapper/IntegrationDemoCSWrapper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D84EC5C4-6DAA-4131-B2E3-5EDADC5D3B32} 8 | Exe 9 | IntegrationDemo 10 | IntegrationDemo 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | bin\x64\Debug\ 39 | DEBUG;TRACE 40 | full 41 | x64 42 | 7.3 43 | prompt 44 | true 45 | 46 | 47 | bin\x64\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x64 52 | 7.3 53 | prompt 54 | true 55 | 56 | 57 | 58 | False 59 | lib\MatricIntegration.dll 60 | 61 | 62 | ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | DemoCommon.cs 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /demos/raw/Program.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using static IntegrationDemo.DemoIntegrationHelper; 7 | 8 | namespace IntegrationDemo { 9 | 10 | 11 | class Program { 12 | public static string DEMO_DECK_ID = CONST.DEMO_DECK_ID; 13 | public static string PIN = CONST.PIN; 14 | public static string CLIENT_ID; 15 | public static DemoIntegrationHelper mtrx; 16 | static void Main(string[] args) 17 | { 18 | Console.Title = "MATRIC Integration Demo"; 19 | mtrx = new DemoIntegrationHelper(); 20 | Console.WriteLine("Authorize connection in MATRIC, then enter PIN:"); 21 | //mtrx.Connect(); 22 | //PIN = Console.ReadLine(); 23 | mtrx.GetConnectedClients(); 24 | Console.ReadLine(); 25 | } 26 | 27 | private static void StartDemo() { 28 | string GRAY = "#111111"; 29 | string YELLOW = "yellow"; 30 | string GREEN = "green"; 31 | string RED = "red"; 32 | string BLACK = "black"; 33 | string WHITE = "white"; 34 | 35 | mtrx.SetDeck(CLIENT_ID, DEMO_DECK_ID, DemoPages.SEMAPHORE); 36 | Thread.Sleep(800); 37 | 38 | List listOn = new List(); 39 | //we will refer to the buttons by name rather then id 40 | listOn.Add(new VisualStateItem(null, "on", buttonName: "BTN_GREEN")); 41 | listOn.Add(new VisualStateItem(null, "on", buttonName: "BTN_YELLOW")); 42 | listOn.Add(new VisualStateItem(null, "on", buttonName: "BTN_RED")); 43 | 44 | List listOff = new List(); 45 | listOff.Add(new VisualStateItem(null, "off", buttonName: "BTN_GREEN")); 46 | listOff.Add(new VisualStateItem(null, "off", buttonName: "BTN_YELLOW")); 47 | listOff.Add(new VisualStateItem(null, "off", buttonName: "BTN_RED")); 48 | 49 | mtrx.SetButtonsVisualState(CLIENT_ID, listOn); 50 | Thread.Sleep(800); 51 | mtrx.SetButtonsVisualState(CLIENT_ID, listOff); 52 | Thread.Sleep(800); 53 | mtrx.SetButtonsVisualState(CLIENT_ID, listOn); 54 | Thread.Sleep(800); 55 | mtrx.SetButtonsVisualState(CLIENT_ID, listOff); 56 | Thread.Sleep(800); 57 | 58 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_GREEN", backgroundcolorOff: GREEN); 59 | Thread.Sleep(800); 60 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_GREEN", backgroundcolorOff: GRAY); 61 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_YELLOW", backgroundcolorOff: YELLOW); 62 | Thread.Sleep(800); 63 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_GREEN", backgroundcolorOff: GRAY); 64 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_YELLOW", backgroundcolorOff: GRAY); 65 | mtrx.SetButtonProperties(CLIENT_ID, "BTN_RED", backgroundcolorOff: RED); 66 | Thread.Sleep(1000); 67 | 68 | mtrx.SetActivePage(CLIENT_ID, DemoPages.SHIELDS_AND_WEAPONS); 69 | Thread.Sleep(1500); 70 | //simulate battle 71 | int ammo = 500; 72 | int shields = 100; 73 | for (int i = 0; i < 100; i++) { 74 | mtrx.SetControlsState(CLIENT_ID, new List { 75 | new SetControlStateItem(null, $"{{value: {shields}}}", "SHIELDS_SLIDER") 76 | }); 77 | if (shields < 30) 78 | { 79 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_CRITICAL", textcolorOff: BLACK, backgroundcolorOff: RED); 80 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: RED, text: $@"{shields}%"); 81 | } 82 | else if (shields < 50) 83 | { 84 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: YELLOW, text: $@"{shields}%"); 85 | } 86 | else { 87 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: GREEN, text: $@"{shields}%"); 88 | } 89 | mtrx.SetButtonProperties(CLIENT_ID, "AMMO_COUNT", backgroundcolorOff: GRAY, textcolorOff: WHITE, text: $@"{ammo}"); 90 | shields--; 91 | ammo = ammo -5; 92 | Thread.Sleep(100); 93 | } 94 | 95 | //flash critical shields 96 | bool criticalOn = true; 97 | for (int i = 0; i < 10; i++) { 98 | if (criticalOn) 99 | { 100 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_CRITICAL", textcolorOff: GRAY, backgroundcolorOff: BLACK); 101 | } 102 | else { 103 | mtrx.SetButtonProperties(CLIENT_ID, "SHIELDS_CRITICAL", textcolorOff: GRAY, backgroundcolorOff: RED); 104 | } 105 | criticalOn = !criticalOn; 106 | Thread.Sleep(400); 107 | } 108 | 109 | mtrx.SetActivePage(CLIENT_ID, DemoPages.DEMO_COMPLETE); 110 | Thread.Sleep(1000); 111 | mtrx.SetButtonProperties(CLIENT_ID, "WINK_BUTTON", text: CONST.SMILE_WINK); 112 | Console.WriteLine("Demo complete"); 113 | //mtrx.SetDeck(CLIENT_ID, DEMO_DECK_ID, DemoPages.SEMAPHORE); 114 | 115 | } 116 | 117 | public static void ParseMessage(string json) { 118 | JObject obj = JObject.Parse(json); 119 | string messageType = obj.GetValue("MessageType").ToString(); 120 | switch (messageType) { 121 | case "ClientList": 122 | UpdateClientsList(obj.GetValue("MessageData").ToString()); 123 | break; 124 | case "ControlInteraction": 125 | OnControlInteraction(obj.GetValue("MessageData").ToString()); 126 | break; 127 | } 128 | } 129 | public static void OnControlInteraction(string data) 130 | { 131 | Console.WriteLine("Control interaction:"); 132 | Console.WriteLine(data); 133 | } 134 | 135 | public static void UpdateClientsList(string json) { 136 | JArray connectedClients = (JArray)JsonConvert.DeserializeObject(json); 137 | if (connectedClients.Count == 0) 138 | { 139 | Console.WriteLine("No connected devices found, make sure your smartphone/tablet is connected\nPress any key to exit"); 140 | Console.ReadKey(); 141 | Environment.Exit(0); 142 | } 143 | Console.WriteLine("Found devices:"); 144 | foreach (JObject client in connectedClients) 145 | { 146 | Console.WriteLine($@"{client.GetValue("Hash")} {client.GetValue("Name")}"); 147 | } 148 | CLIENT_ID = ((JObject)connectedClients[0]).GetValue("clientId").ToString(); 149 | Console.WriteLine("Starting demo on first device"); 150 | StartDemo(); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /demos/raw/DemoIntegrationHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using System.Text; 6 | 7 | namespace IntegrationDemo { 8 | public class DemoIntegrationHelper { 9 | 10 | UdpClient udpClient; 11 | IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, API_PORT); 12 | public static int API_PORT = CONST.API_PORT; 13 | public static int UDP_LISTENER_PORT = 50301; 14 | private string APP_NAME = CONST.APP_NAME; 15 | 16 | public DemoIntegrationHelper() { 17 | udpClient = new UdpClient(UDP_LISTENER_PORT); 18 | udpClient.BeginReceive(new AsyncCallback(ReceiveCallback), null); 19 | } 20 | 21 | 22 | public void ReceiveCallback(IAsyncResult ar){ 23 | IPEndPoint ep = new IPEndPoint(serverEP.Address, serverEP.Port); 24 | byte[] receiveBytes = udpClient.EndReceive(ar, ref ep); 25 | string receiveString = Encoding.ASCII.GetString(receiveBytes); 26 | 27 | Program.ParseMessage(receiveString); 28 | udpClient.BeginReceive(new AsyncCallback(ReceiveCallback), null); 29 | } 30 | 31 | 32 | 33 | /// 34 | /// Initiates the connection 35 | /// 36 | public void Connect() { 37 | string msg = $@" 38 | {{""command"":""CONNECT"", 39 | ""appName"":""{APP_NAME}""}} 40 | "; 41 | UDPSend(msg); 42 | } 43 | 44 | /// 45 | ///Requests the list of connected MATRIC clients 46 | /// 47 | public void GetConnectedClients() 48 | { 49 | string msg = $@" 50 | {{""command"":""GETCONNECTEDCLIENTS"", 51 | ""appName"":""{APP_NAME}"", 52 | ""appPIN"":""{Program.PIN}""}} 53 | "; 54 | UDPSend(msg); 55 | } 56 | 57 | /// 58 | /// Sets various button properties 59 | /// 60 | /// Target client id 61 | /// Id of the button we want to change 62 | /// Button text to set 63 | /// Button text color in pressed state 64 | /// Button text color in normal state 65 | /// Button background color in normal state 66 | /// Button background color in pressed state 67 | /// Button relative font size - string: small, medium, large, xlarge, xxlarge, xxxlarge 68 | /// Button image in pressed state 69 | /// Button image in normal state 70 | /// Button name (preferred way to reference buttons, rather then by id) 71 | public void SetButtonProperties(string clientId, string buttonName, string text = null, string textcolorOn = null, string textcolorOff = null, 72 | string backgroundcolorOff = null, string backgroundcolorOn = null, string imageOn = null, string imageOff = null, string fontSize = null, string buttonId = null) 73 | { 74 | //Remark: if we do not want to change a particular property, we will send it as null 75 | string msg = $@" 76 | {{""command"":""SETBUTTONPROPS"", 77 | ""appName"":""{APP_NAME}"", 78 | ""appPIN"":""{Program.PIN}"", 79 | ""clientId"":""{clientId}"", 80 | ""buttonId"":""{buttonId}"", 81 | ""buttonName"": ""{buttonName}"", 82 | ""data"":{{ 83 | ""imageOff"": { (imageOff == null ? "null" : "\"" + imageOff + "\"") }, 84 | ""imageOn"": { (imageOn == null ? "null" : "\"" + imageOff + "\"") }, 85 | ""textcolorOn"": { (textcolorOn == null ? "null" : "\"" + textcolorOn + "\"")}, 86 | ""textcolorOff"":{ (textcolorOff == null ? "null" : "\"" + textcolorOff + "\"")}, 87 | ""backgroundcolorOn"": { (backgroundcolorOn == null ? "null" : "\"" + backgroundcolorOn + "\"")}, 88 | ""backgroundcolorOff"":{ (backgroundcolorOff == null ? "null" : "\"" + backgroundcolorOff + "\"")}, 89 | ""fontSize"":{ (fontSize == null ? "null" : "\"" + fontSize + "\"")}, 90 | ""text"":{ (text == null ? "null" : "\"" + text + "\"")} 91 | }} 92 | }}"; 93 | UDPSend(msg); 94 | } 95 | 96 | /// 97 | /// Sets the active page 98 | /// 99 | /// Target client id 100 | /// Page id 101 | public void SetActivePage(string clientId, string pageId) 102 | { 103 | string msg = $@" 104 | {{""command"":""SETACTIVEPAGE"", 105 | ""appName"":""{APP_NAME}"", 106 | ""appPIN"":""{Program.PIN}"", 107 | ""clientId"":""{clientId}"", 108 | ""pageId"":""{pageId}""}} 109 | "; 110 | UDPSend(msg); 111 | } 112 | 113 | /// 114 | /// Sets deck and optionally page 115 | /// 116 | /// Target client id 117 | /// deck id 118 | /// page id 119 | public void SetDeck(string clientId, string deckId, string pageId) { 120 | string msg = $@" 121 | {{""command"":""SETDECK"", 122 | ""appName"":""{APP_NAME}"", 123 | ""appPIN"":""{Program.PIN}"", 124 | ""clientId"":""{clientId}"", 125 | ""deckId"":""{deckId}"", 126 | ""pageId"":""{pageId}""}} 127 | "; 128 | UDPSend(msg); 129 | } 130 | 131 | public class SetControlStateItem 132 | { 133 | public string controlId; 134 | public string controlName; 135 | public string state; 136 | 137 | public SetControlStateItem(string _controlId, string state, string _controlName = null) 138 | { 139 | this.controlId = _controlId; 140 | this.state = state; 141 | this.controlName = _controlName; 142 | } 143 | } 144 | 145 | public class VisualStateItem { 146 | public string buttonId; 147 | public string buttonName; 148 | public string state; 149 | 150 | public VisualStateItem(string buttonId, string state, string buttonName = null) 151 | { 152 | this.buttonId = buttonId; 153 | this.state = state; 154 | this.buttonName = buttonName; 155 | } 156 | } 157 | 158 | public void SetButtonsVisualState(string clientId, List list) { 159 | string btnList = ""; 160 | 161 | for (int i = 0; i < list.Count; i++) { 162 | VisualStateItem item = list[i]; 163 | if (i != 0) { 164 | btnList += ","; 165 | } 166 | btnList += $@"{{""buttonId"":""{ item.buttonId}"", ""buttonName"": ""{item.buttonName}"", ""state"":""{item.state}""}}"; 167 | } 168 | 169 | string msg = $@" 170 | {{""command"":""SETBUTTONSVISUALSTATE"", 171 | ""appName"":""{APP_NAME}"", 172 | ""appPIN"":""{Program.PIN}"", 173 | ""clientId"":""{clientId}"", 174 | ""data"":[{btnList}] 175 | }} 176 | "; 177 | UDPSend(msg); 178 | } 179 | 180 | public void SetControlsState(string clientId, List list) 181 | { 182 | string ctlList = ""; 183 | 184 | for (int i = 0; i < list.Count; i++) 185 | { 186 | SetControlStateItem item = list[i]; 187 | if (i != 0) 188 | { 189 | ctlList += ","; 190 | } 191 | ctlList += $@"{{""controlId"":""{ item.controlId}"", ""controlName"": ""{item.controlName}"", ""state"":{item.state}}}"; 192 | } 193 | 194 | string msg = $@" 195 | {{""command"":""SETCONTROLSSTATE"", 196 | ""appName"":""{APP_NAME}"", 197 | ""appPIN"":""{Program.PIN}"", 198 | ""clientId"":""{clientId}"", 199 | ""data"":[{ctlList}] 200 | }} 201 | "; 202 | UDPSend(msg); 203 | } 204 | 205 | /// 206 | /// Sends UDP message to Matric server 207 | /// 208 | void UDPSend(string message) 209 | { 210 | byte[] bytes = Encoding.UTF8.GetBytes(message); 211 | udpClient.Send(bytes, bytes.Length, serverEP); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MATRIC Integration API Demo 2 | This project is a simple demo of MATRIC integration API 3 | 4 | MATRIC (https://matricapp.com) can be used as an input device (controlling PC applications from smartphone or tablet) by emulating keyboard and mouse, but can also be used to display data from 3rd party applications by utilizing Integration API. 5 | 6 | Integration API enables 3rd party applications to use MATRIC as an output device. Perhaps it is best illustrated by use-case example: 7 | Let's say we have a flight simulator game, and we are using MATRIC as a virtual cockpit button board. But what if we want to reflect the game state to MATRIC, e.g. we want to indicate remaining fuel or low fuel warning. We can do that using Integration API to push changes to MATRIC deck from our flight sim, e.g. we will change the fuel button text to indicate remaining fuel and maybe set its color to red if the fuel is low. 8 | 9 | ## API Basics 10 | 11 | Integration API uses simple JSON text commands which 3rd party app sends via UDP to matric server (default port for Integration API is 50300 and it always listens on loopback address 127.0.0.1). 12 | 13 | c# API wrapper is also available to make things easier 14 | 15 | ## How to use the demo 16 | Prerequisites: 17 | - Enable integration API by editing /Documents/.matric/config.json, set "EnableIntegrationAPI" to **true** 18 | - Import demo deck (IntegrationDemo.deck) from this repository by double clicking it. 19 | 20 | ## Running the integration demo 21 | 1) Start MATRIC, connect with smartphone/tablet 22 | 2) Start demo 23 | 3) MATRIC will display a popup messsage similar to this one: 24 | 25 | ![Authorization popup](/res/authorize-app-popup.png) 26 | 27 | 4) Click Yes on the MATRIC popup and then type the PIN into demo console: 28 | 29 | ![Enter PIN in demo app console](/res/demo-enter-pin.png) 30 | 31 | 5) The demos will run switching the deck on the first connected client to demo deck and dynamically changing button visuals. The demo is not ment to illustrate any programming best practices, instead it is made to be as simple and minimalistic as possible. 32 | 33 | ## Integration API commands (if you do not want to use the convenient .Net wrapper) 34 | 35 | ### Common properties 36 | 37 | | Property | Type | | 38 | |---|---|---| 39 | | command | string | The command we want to execute (see below) | 40 | | appName | string | The name to identify the app sending the integration commands | 41 | | appPIN | string | PIN assigned to app sending the integration commands | 42 | | clientId | string | client Id of the client we want to target. If set to null commands will be sent to all connected clients | 43 | 44 | ### CONNECT 45 | 46 | Triggers authorization popup on PC. User will be prompted to allow access to Integration API to 3rd party application and shown a PIN number which must be entered into 3rd party application. Typically you'd do this only once and save the PIN. 47 | 48 | Example request: 49 | 50 | ``` 51 | { 52 | "command":"CONNECT", 53 | "appName":"Integration demo" 54 | } 55 | ``` 56 | 57 | ### GETCONNECTEDCLIENTS 58 | 59 | Returns a list of connected clients. 60 | 61 | Example request: 62 | 63 | ``` 64 | { 65 | "command":"GETCONNECTEDCLIENTS", 66 | "appName":"Integration demo", 67 | "appPIN":"0186" 68 | } 69 | ``` 70 | 71 | Example response: 72 | 73 | ``` 74 | [ 75 | {"Name":"Joe's Galaxy S10", 76 | "IP":"192.168.8.45", 77 | "Id":"iQyGDYxja7Zm2yuLt9MJ9Yld+aQCVXX60KV71XPpIJA=", 78 | "MatricVersion":2, 79 | "LastContact":"2019-08-29T15:28:38.1185368+02:00"} 80 | ] 81 | ``` 82 | 83 | ### SETDECK 84 | 85 | Instructs the client (specified by clientId) to load deck (specified by deckId) and (optionally) switch to page in deck (specified by pageId). 86 | 87 | Example request: 88 | 89 | ``` 90 | { 91 | "command":"SETDECK", 92 | "appName":"Integration demo", 93 | "appPIN":"0186", 94 | "clientId":"iQyGDYxja7Zm2yuLt9MJ9Yld+aQCVXX60KV71XPpIJA=", 95 | "deckId":"7f18056c-7a2a-46ac-9956-662e7d0b78ec", 96 | "pageId":"00d9c649-f2df-405f-abfd-06d38f8626be" 97 | } 98 | ``` 99 | 100 | ### SETACTIVEPAGE 101 | 102 | Instructs the client to switch to page specified by pageId. 103 | 104 | Example request: 105 | 106 | ``` 107 | { 108 | "command":"SETACTIVEPAGE", 109 | "appName":"Integration demo", 110 | "appPIN":"0186", 111 | "clientId":"iQyGDYxja7Zm2yuLt9MJ9Yld+aQCVXX60KV71XPpIJA=", 112 | "pageId":"00d9c649-f2df-405f-abfd-06d38f8626be" 113 | } 114 | ``` 115 | 116 | ### SETBUTTONPROPS 117 | Modifies the properties of a button specified by buttonId or buttonName. Note that you can change button visual properties but not it's function. This is behaviour by design. Note also that changes are not persisted, integration commands does not alter the button definition in deck on MATRIC server (PC). 118 | 119 | Example request: 120 | 121 | ``` 122 | { 123 | "command":"SETBUTTONPROPS", 124 | "appName":"Integration demo", 125 | "appPIN":"0186", 126 | "clientId":"iQyGDYxja7Zm2yuLt9MJ9Yld+aQCVXX60KV71XPpIJA=", 127 | "buttonId":"cf3cd93c-e43c-4649-9f47-5441555ca7ce", 128 | "buttonName":"BIG_RED_BUTTON", 129 | "data":{ 130 | "imageOff": null, 131 | "imageOn": null, 132 | "textcolorOn": null, 133 | "textcolorOff":null, 134 | "backgroundcolorOn": null, 135 | "backgroundcolorOff":"green", 136 | "fontSize":null, 137 | "text":null 138 | } 139 | } 140 | ``` 141 | 142 | ### SETBUTTONPROPSEX 143 | Modifies the properties of multiple buttons. Note that you can change button visual properties but not it's function. This is behaviour by design. Note also that changes are not persisted, integration commands does not alter the button definition in deck on MATRIC server (PC). 144 | 145 | IMPORTANT: This method is available in version 1.22 and higher! 146 | 147 | Example request: 148 | ``` 149 | { 150 | "appName": "MATRIC4DCS", 151 | "appPin": "9087", 152 | "clientId": "twQd9g6COnWeT7SPaInvcTk2xdvBW7lN8+b+a9QQRfk=", 153 | "command": "SETBUTTONPROPSEX", 154 | "data": [ { 155 | "buttonId": "7eec29e4-1f59-47d2-bdd5-9b599d375fc9", 156 | "imageOff": "8e7b4b9f-3e18-4009-bae1-445b1f3aa81f.png", 157 | "textcolorOff": "white" 158 | }, { 159 | "buttonName": "BIG_RED_ONE", 160 | "imageOff": "8e7b4b9f-3e18-4009-bae1-445b1f3aa81f.png", 161 | "textcolorOff": "white" 162 | }, { 163 | "buttonId": "404e46c7-8b8e-48dd-89dd-276a408fcf4b", 164 | "imageOff": "8e7b4b9f-3e18-4009-bae1-445b1f3aa81f.png", 165 | "textcolorOff": "white" 166 | }, { 167 | "buttonId": "d6c9836c-7986-48bc-b4a8-1cb52407bb5d", 168 | "imageOff": "8e7b4b9f-3e18-4009-bae1-445b1f3aa81f.png", 169 | "textcolorOff": "white" 170 | }, { 171 | "buttonId": "2dee5490-bc3e-4c48-a6d2-144f37800993", 172 | "imageOff": "8e7b4b9f-3e18-4009-bae1-445b1f3aa81f.png", 173 | "textcolorOff": "white" 174 | } ] 175 | } 176 | ``` 177 | 178 | ### SETBUTTONSVISUALSTATE 179 | Sets the visual state of multiple buttons defined by their ids or names. It sets predefined properties defined in MATRIC editor for "on" (pressed) and "off" (not pressed). It is easier to use then SETBUTTONPROPS and SETBUTTONPROPSEX as you do not need to define all the properties in the command but instead just set the state to on or off. 180 | 181 | IMPORTANT: This method is available in version 1.26 and higher! 182 | 183 | Example request: 184 | ``` 185 | { 186 | "appName": "MATRIC4DCS", 187 | "appPin": "9087", 188 | "clientId": "twQd9g6COnWeT7SPaInvcTk2xdvBW7lN8+b+a9QQRfk=", 189 | "command": "SETBUTTONSVISUALSTATE", 190 | "data": [ { 191 | "buttonId": "7eec29e4-1f59-47d2-bdd5-9b599d375fc9", 192 | "state": "on" 193 | }, { 194 | "buttonName": "BIG_RED_ONE", 195 | "state": off" 196 | }, { 197 | "buttonId": "404e46c7-8b8e-48dd-89dd-276a408fcf4b", 198 | "state": "off" 199 | }, { 200 | "buttonId": "d6c9836c-7986-48bc-b4a8-1cb52407bb5d", 201 | "state": "on" 202 | }] 203 | } 204 | ``` 205 | 206 | ### SETCONTROLSSTATE 207 | Sets the state of multiple controls defined by their ids or names. 208 | State object depends on control type: 209 | for buttons : {pressed: boolean} 210 | for sliders: {value: number} 211 | for rotary: {pressed: boolean, value: number} 212 | for rotary encoder: {pressed: boolean} 213 | 214 | IMPORTANT: This method is available in version 2.0 and higher! 215 | 216 | Example request: 217 | ``` 218 | { 219 | "appName": "MATRIC4DCS", 220 | "appPin": "9087", 221 | "clientId": "twQd9g6COnWeT7SPaInvcTk2xdvBW7lN8+b+a9QQRfk=", 222 | "command": "SETCONTROLSSTATE", 223 | "data": [ { 224 | "controlId": "7eec29e4-1f59-47d2-bdd5-9b599d375fc9", 225 | "state": {pressed: true} 226 | }, { 227 | "controlName": "SOME_SLIDER", 228 | "state": { value: 50} 229 | }, { 230 | "controlName": "SOME_ROTARY", 231 | "state": { pressed: true, value: 30} 232 | }] 233 | } 234 | ``` 235 | State object depends on the control type, given in the table below: 236 | | Control | State object example| Description | 237 | |---------|--------------|-------------| 238 | |Button | {pressed: true } | pressed: set button state to pressed or "normal" | 239 | |Slider | {value: 50} | | value: - integer (0-100) which determines the slider position 240 | |Rotary | {pressed: true, value: 50} | pressed: set button state to pressed or "normal" value: - integer (0-100) which determines the slider position | 241 | |Multi position switch | {position: 2} | position: integer specifying switch position. Note position starts from 1 | 242 | |Encoder| {pressed: true} | pressed: set button state to pressed or "normal" | 243 | 244 | ## Integration API .Net wrapper 245 | 246 | .Net wrapper is made to make integration with .Net applications easier, please refer to [C# demo](demos/net_wrapper). 247 | A more detailed reference will be available soon. 248 | -------------------------------------------------------------------------------- /demos/net_wrapper/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using Matric.Integration; 5 | 6 | namespace IntegrationDemo { 7 | 8 | 9 | class Program { 10 | 11 | public static string DEMO_DECK_ID = CONST.DEMO_DECK_ID; 12 | public static string PIN = CONST.PIN; 13 | public static string CLIENT_ID; 14 | static Matric.Integration.Matric matric; 15 | 16 | static void Main(string[] args) 17 | { 18 | Console.Title = "MATRIC Integration Demo .Net"; 19 | //Console.WriteLine("Authorize connection in MATRIC, then enter PIN:"); 20 | //New using integration library 21 | matric = new Matric.Integration.Matric(CONST.APP_NAME, CONST.PIN, CONST.API_PORT); 22 | //matric.RequestAuthorizePrompt(); 23 | //PIN = Console.ReadLine(); 24 | matric.PIN = PIN; 25 | matric.OnError += Matric_OnError; 26 | matric.OnConnectedClientsReceived += Matric_OnConnectedClientsReceived; 27 | matric.OnControlInteraction += Matric_OnControlInteraction; 28 | matric.OnVariablesChanged += Matric_OnVariablesChanged; 29 | Console.WriteLine("Press any key to start demo"); 30 | Console.ReadKey(); 31 | Console.WriteLine("Trying to get connected clients"); 32 | matric.GetConnectedClients(); 33 | Console.WriteLine("Press any key to exit"); 34 | Console.ReadKey(); 35 | } 36 | 37 | private static void Matric_OnVariablesChanged(object sender, ServerVariablesChangedEventArgs data) { 38 | Console.WriteLine("Server variables changed"); 39 | foreach (string varName in data.ChangedVariables) { 40 | Console.WriteLine($"{varName}: {data.Variables[varName].Value}"); 41 | } 42 | } 43 | 44 | private static void Matric_OnError(Exception ex) 45 | { 46 | Console.WriteLine(ex.Message); 47 | } 48 | 49 | private static void Matric_OnControlInteraction(object sender, object data) 50 | { 51 | Console.WriteLine("Control interaction:"); 52 | Console.WriteLine(data.ToString()); 53 | } 54 | 55 | private static void Matric_OnConnectedClientsReceived(object source, List clients) { 56 | UpdateClientsList(clients); 57 | } 58 | 59 | private static void StartDemo() { 60 | string GRAY = "#111111"; 61 | string YELLOW = "yellow"; 62 | string GREEN = "green"; 63 | string RED = "red"; 64 | string BLACK = "black"; 65 | string WHITE = "white"; 66 | 67 | ServerVariable vString = new ServerVariable() { 68 | Name = "demo_string", 69 | VariableType = ServerVariable.ServerVariableType.STRING, 70 | Value = "Initial string" 71 | }; 72 | ServerVariable vBool = new ServerVariable() { 73 | Name = "demo_bool", 74 | VariableType = ServerVariable.ServerVariableType.BOOL, 75 | Value = true 76 | }; 77 | ServerVariable vNumber = new ServerVariable() { 78 | Name = "demo_number", 79 | VariableType = ServerVariable.ServerVariableType.NUMBER, 80 | Value = 1 81 | }; 82 | ServerVariable vJsonObject = new ServerVariable() { 83 | Name = "demo_number", 84 | VariableType = ServerVariable.ServerVariableType.JSONOBJECT, 85 | Value = @"{""propNumber"":""1"", ""propString"":""Hello from demo""}" 86 | }; 87 | 88 | List variables = new List() { 89 | vString, vBool, vNumber, vJsonObject 90 | }; 91 | 92 | matric.SetVariables(variables); 93 | Thread.Sleep(5000); 94 | vString.Value = "New value..."; 95 | vBool.Value = !((bool)vBool.Value); 96 | vNumber.Value = ((int)vNumber.Value) + 1; 97 | vJsonObject.Value = @"{""propNumber"":""999"", ""propString"":""Is it working?""}"; 98 | matric.SetVariables(variables); 99 | Thread.Sleep(5000); 100 | 101 | matric.SetDeck(CLIENT_ID, DEMO_DECK_ID, DemoPages.SEMAPHORE); 102 | Thread.Sleep(800); 103 | 104 | List listOn = new List(); 105 | //we will refer to the buttons by name rather then id 106 | listOn.Add(new SetButtonsVisualStateArgs(state:"on", buttonName: "BTN_GREEN")); 107 | listOn.Add(new SetButtonsVisualStateArgs(state:"on", buttonName: "BTN_YELLOW")); 108 | listOn.Add(new SetButtonsVisualStateArgs(state:"on", buttonName: "BTN_RED")); 109 | 110 | List listOff = new List(); 111 | listOff.Add(new SetButtonsVisualStateArgs(state:"off", buttonName: "BTN_GREEN")); 112 | listOff.Add(new SetButtonsVisualStateArgs(state:"off", buttonName: "BTN_YELLOW")); 113 | listOff.Add(new SetButtonsVisualStateArgs(state:"off", buttonName: "BTN_RED")); 114 | 115 | matric.SetButtonsVisualState(CLIENT_ID, listOn); 116 | Thread.Sleep(300); 117 | matric.SetButtonsVisualState(CLIENT_ID, listOff); 118 | Thread.Sleep(300); 119 | matric.SetButtonsVisualState(CLIENT_ID, listOn); 120 | Thread.Sleep(300); 121 | matric.SetButtonsVisualState(CLIENT_ID, listOff); 122 | Thread.Sleep(300); 123 | matric.SetButtonsVisualState(CLIENT_ID, listOn); 124 | Thread.Sleep(300); 125 | matric.SetButtonsVisualState(CLIENT_ID, listOff); 126 | 127 | 128 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: GREEN, buttonName: "BTN_GREEN"); 129 | Thread.Sleep(800); 130 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: GRAY, buttonName: "BTN_GREEN"); 131 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: YELLOW, buttonName: "BTN_YELLOW"); 132 | Thread.Sleep(800); 133 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: GRAY, buttonName: "BTN_GREEN"); 134 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: GRAY, buttonName: "BTN_YELLOW"); 135 | matric.SetButtonProperties(CLIENT_ID, backgroundcolorOff: RED, buttonName: "BTN_RED"); 136 | Thread.Sleep(800); 137 | matric.SetButtonProperties(CLIENT_ID, fontSize: "10", buttonName: "BTN_GREEN"); 138 | Thread.Sleep(500); 139 | matric.SetButtonProperties(CLIENT_ID, fontSize: "20", buttonName: "BTN_GREEN"); 140 | Thread.Sleep(500); 141 | matric.SetButtonProperties(CLIENT_ID, fontSize: "30", buttonName: "BTN_GREEN"); 142 | Thread.Sleep(500); 143 | matric.SetButtonProperties(CLIENT_ID, fontSize: "40", buttonName: "BTN_GREEN"); 144 | Thread.Sleep(500); 145 | 146 | matric.SetButtonPropertiesEx(null, new List { 147 | new SetButtonPropsArgsEx 148 | { 149 | text="RED!!!", ButtonName = "BTN_RED" 150 | }, 151 | new SetButtonPropsArgsEx 152 | { 153 | text="YELLOW!!!", ButtonName = "BTN_YELLOW" 154 | }, 155 | new SetButtonPropsArgsEx 156 | { 157 | text="GREEN!!!", ButtonName = "BTN_GREEN" 158 | } 159 | }); 160 | Thread.Sleep(2000); 161 | matric.SetActivePage(CLIENT_ID, DemoPages.SHIELDS_AND_WEAPONS); 162 | Thread.Sleep(1500); 163 | matric.SetControlsState(null, new List { 164 | new SetControlsStateArgs 165 | { 166 | ControlId=null, ControlName="MULTI_POS_5", State = new { position = 5} 167 | } 168 | }); 169 | //simulate battle 170 | int ammo = 500; 171 | int shields = 100; 172 | for (int i = 0; i < 100; i++) { 173 | matric.SetControlsState(null, new List { 174 | new SetControlsStateArgs 175 | { 176 | ControlId=null, ControlName="SHIELDS_SLIDER", State = new { value = shields} 177 | } 178 | }); 179 | if (shields < 30) 180 | { 181 | matric.SetControlsState(null, new List { 182 | new SetControlsStateArgs 183 | { 184 | ControlId=null, ControlName="MULTI_POS_5", State = new { position = 3} 185 | } 186 | }); 187 | matric.SetButtonProperties(CLIENT_ID, buttonName:"SHIELDS_CRITICAL", textcolorOff: BLACK, backgroundcolorOff: RED); 188 | matric.SetButtonProperties(CLIENT_ID, buttonName:"SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: RED, text: $@"{shields}%"); 189 | } 190 | else if (shields < 50) 191 | { 192 | matric.SetControlsState(null, new List { 193 | new SetControlsStateArgs 194 | { 195 | ControlId=null, ControlName="MULTI_POS_5", State = new { position = 4} 196 | } 197 | }); 198 | matric.SetButtonProperties(CLIENT_ID, buttonName: "SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: YELLOW, text: $@"{ shields}%"); 199 | } 200 | else { 201 | matric.SetButtonProperties(CLIENT_ID, buttonName: "SHIELDS_PERCENT", backgroundcolorOff: GRAY, textcolorOff: GREEN, text: $@"{ shields}%"); 202 | } 203 | matric.SetButtonProperties(CLIENT_ID, buttonName: "AMMO_COUNT", backgroundcolorOff: GRAY, textcolorOff: WHITE, text: $@"{ ammo}"); 204 | shields--; 205 | ammo = ammo -5; 206 | Thread.Sleep(100); 207 | } 208 | 209 | //flash critical shields 210 | matric.SetControlsState(null, new List { 211 | new SetControlsStateArgs 212 | { 213 | ControlId=null, ControlName="MULTI_POS_5", State = new { position = 2} 214 | } 215 | }); 216 | bool criticalOn = true; 217 | for (int i = 0; i < 10; i++) { 218 | if (criticalOn) 219 | { 220 | matric.SetButtonProperties(CLIENT_ID, buttonName: "SHIELDS_CRITICAL", textcolorOff: GRAY, backgroundcolorOff: BLACK); 221 | } 222 | else { 223 | matric.SetButtonProperties(CLIENT_ID, buttonName: "SHIELDS_CRITICAL", textcolorOff: GRAY, backgroundcolorOff: RED); 224 | } 225 | criticalOn = !criticalOn; 226 | Thread.Sleep(400); 227 | } 228 | 229 | matric.SetActivePage(CLIENT_ID, DemoPages.DEMO_COMPLETE); 230 | Thread.Sleep(1000); 231 | matric.SetButtonProperties(CLIENT_ID, buttonName: "WINK_BUTTON", text: CONST.SMILE_WINK); 232 | Console.WriteLine("Demo complete"); 233 | 234 | } 235 | 236 | 237 | public static void UpdateClientsList(List connectedClients) { 238 | if (connectedClients.Count == 0) 239 | { 240 | Console.WriteLine("No connected devices found, make sure your smartphone/tablet is connected\nPress any key to exit"); 241 | Console.ReadKey(); 242 | Environment.Exit(0); 243 | } 244 | Console.WriteLine("Found devices:"); 245 | foreach (ClientInfo client in connectedClients) 246 | { 247 | Console.WriteLine($@"{client.Id} {client.Name}"); 248 | } 249 | CLIENT_ID = connectedClients[0].Id; 250 | Console.WriteLine("Starting demo on first device"); 251 | StartDemo(); 252 | } 253 | } 254 | } 255 | --------------------------------------------------------------------------------