// This is where we get responses from the TCP Client helper class. This is where we handle the events that are raised // This is a CUSTOM class. how we interact with it was defined by the programmer. This is not a Crestron Class! // DO NOT assume this is how you use a Crestron class. Look at the Sourcecode for that class to see how to interact with a // TCP Client directly. private void MyClient_tcpHelperEvent(object sender, TCPClientHelperEventArgs e) { // Send a string out our Virtual Console for display VirtualConsole.Send(String.Format("TCPIPClient Event Message={0}", e.Message), true); // e.Message will contain keywords telling us what event was raised // STATUS = Status change RX = data was received FAIL= connection failed if (e.Message == "STATUS") { // Connected is a boolean True = connected, False = disconnected // We leverage the NOT ! operator here to make our feedback correct. myXpanel.BooleanInput[20].BoolValue = e.Connected; //Connected Feedback join myXpanel.BooleanInput[21].BoolValue = !e.Connected; //Disconnected Feedback join } if (e.Message == "RX") // We have data waiting to be processed that is in e.RX { VirtualConsole.Send(String.Format("RX Text = {0}", e.RX)); // Print out what came in for debugging ProjProcessing(e.RX); // Call our method we created below to process // the received data from the projector. // This method is at the bottom of this file } myXpanel.StringInput[2].StringValue = e.RX; // display on our touch panel any received data }
/*********************************************************************************************** * Session 3 File loading and display and sorting methods ***********************************************************************************************/ private void LoadFile() { // Do not forget to add the Masters2021() class instantiation at the top to get the file created for students. // Challenge: What if the file was not there? How can we check if it exists before we try to open it? // Add the code to check if the file exists at that location only only open and read it if it does. var path = Directory.GetApplicationRootDirectory() + "/user/names.txt"; VirtualConsole.Send(String.Format("Opening file {0}", path)); // We should check to see if the file was actually able to be opened and read sucessfully and report back if it was unable to. // Add code here to make this fail gracefully if it was unable to open the file or read from it. var file = new FileStream(path, FileMode.Open); var stream = new StreamReader(file); VirtualConsole.Send("File Opened"); // If the above crashed by throwing an exception, this will not execute. // C# arrays are zero based, we have index 0 to 9 available var i = 0; while (!stream.EndOfStream) // Loop until we get to the end of the file { Names[i] = stream.ReadLine(); // Load the line from the file into the array i++; // Increment our index variable } stream.Close(); // Extremely important. Don not forget to close these file.Close(); VirtualConsole.Send(String.Format("Read {0} entries", i)); // We hardcoded the number of entries below, this is NOT a best practice in coding. we should know how many we read and // all processing from that point on should be based on the amount of data that was read. This also means using a hard array is // not the right answer. As an exercise, investigate what other storage method that can change based on data read in could be // used instead of an array. // Hint: it's not a dictionary. for (i = 0; i < 10; i++) // Loop to load the array into the touch panel strings { myXpanel.StringInput[(uint)(30 + i)].StringValue = Names[i]; // (uint) casts the integers to unsigned integers } }
// This is how you create a Virtual Console Command Method: This is a freebie that is not a part of the Masters Session private string TestFunc(string s) { VirtualConsole.Send(string.Format("Test Command line Called and after it was sent {0}", s)); return(""); //return an empty string. }
/***************************************************************************************************** * Session 1 Touchpanel Events setup, adding page flips and basic logic *****************************************************************************************************/ // This is where our Touchpanel Signal changes are processed. Digitals, Analogs, and Serials All end up here. private void MyXpanel_SigChange(BasicTriList currentDevice, SigEventArgs args) { VirtualConsole.Send(String.Format("TP Sig Change Type={0} Number={1} State={2}", args.Sig.Type, args.Sig.Number, args.Sig.BoolValue), true); // Question: What is all this? What does {0} mean? // and yes a line can be on 2 lines // Answer: Look up String.Format and read up on the specifier string. This is like the Trace and MakeString in Simpl Plus. // Important to split it like this for more flexibility. Check if it's a digital, then anything below is for digitals if (args.Sig.Type == eSigType.Bool) // Is it a digital? { //SESSION 1: Create a Momentary Button (This has to be outside the check if true below) if (args.Sig.Number == 11) { // This passes the button events back to the feedback myXpanel.BooleanInput[11].BoolValue = args.Sig.BoolValue; // we want both the press and release here } //SESSION 1: Check if it is pressed if (args.Sig.BoolValue == true) // Look for only pressed button events { // Page Navigation Session 1: Instructor put in the first page nav code The rest are student lab switch (args.Sig.Number) { case 1: myXpanel.BooleanInput[1].BoolValue = true; // Traditional way of setting it high then low myXpanel.BooleanInput[1].BoolValue = false; myXpanel.StringInput[1].StringValue = "Front Page"; break; case 2: myXpanel.BooleanInput[2].Pulse(); // using the built in method to pulse it myXpanel.StringInput[1].StringValue = "Projector"; break; case 3: myXpanel.BooleanInput[3].Pulse(); myXpanel.StringInput[1].StringValue = "Phone Book"; break; } /****************************************************************************************** * Session 1 Lab work below (Momentary is above outside the "true" check for boolvalue) ******************************************************************************************/ // Create a Toggle Button if (args.Sig.Number == 10) { // We read the current feedback and use the compliment or NOT by using ! to toggle between states myXpanel.BooleanInput[10].BoolValue = !myXpanel.BooleanInput[10].BoolValue; // Invert The Feedback } // Interlock with simple Logic. Pay attention to the join numbers used /* * switch(args.Sig.Number) * { * case 12: * myXpanel.BooleanInput[13].BoolValue = false; * myXpanel.BooleanInput[14].BoolValue = false; * myXpanel.BooleanInput[12].BoolValue = true; * break; * * case 13: * myXpanel.BooleanInput[12].BoolValue = false; * myXpanel.BooleanInput[14].BoolValue = false; * myXpanel.BooleanInput[13].BoolValue = true; * break; * * case 14: * myXpanel.BooleanInput[12].BoolValue = false; * myXpanel.BooleanInput[13].BoolValue = false; * myXpanel.BooleanInput[14].BoolValue = true; * break; * } */ //Interlock leveraging the power of a method if (args.Sig.Number >= 12 && args.Sig.Number <= 14) // We only want joins 12,13,14 { Interlock(myXpanel.BooleanInput, 12, 14, args.Sig.Number); // Look for this custom method below } /********************************************************************************************** * Session 2 **********************************************************************************************/ // #### Projector Button Press Logic // #### All of this SHOULD exist in a method or even another class to make the code more manageable and organized // // We are still inside the pair of IF statements for "was this a boolean(digital) and was it true(pressed) // Nested If statements can get complex and hard to navigate quickly. ProjectorButtonPress(args.Sig.Number); // Call our method below // Hidden Challenge: Make the projector Connect when it is on the projector Page, // and Disconnect when the user leaves the projector page. // Second hidden Challenge: Do not use join numbers but instead use an enum with names // so you can easily remap to different buttons /******************************************************************************************** * Session 3 ********************************************************************************************/ // File Read and Sort button management Methods start down near line 370 switch (args.Sig.Number) { case 30: LoadFile(); // Call our method to load the file and display the contents break; case 31: SortFile(); // Call our method to sort the strings and present them break; } } } }