Advertisement
SemlerPDX

AVCS SENS DHT1 MAIN-v4 Inline Function in C# for VoiceAttack & Arduino

Jun 3rd, 2022 (edited)
1,112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.55 KB | None | 0 0
  1. //AVCS SENS - AVCS-DHT1 External Sensor Temperature Data Monitoring Function v4
  2. // - Parses new External DHT11 data from Arduino every 30 seconds
  3. // by SemlerPDX Mar/May2022
  4. // VETERANS-GAMING.COM
  5.  
  6. //#define DEBUG  //DEV DEBUGGING - comment/uncomment to disable/enable debug output
  7.  
  8. using System;
  9. using System.IO.Ports;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Text.RegularExpressions;
  13. using System.Threading;
  14.  
  15. public class VAInline
  16. {
  17.     double MonitorTimerDelay = 2000; //in milliseconds (default 2000 == 2 seconds)
  18.    
  19.     public void ClearSensorVariables()
  20.     {
  21.         VA.SetDecimal("AVCS_SENS_TempDHTc", null);
  22.         VA.SetDecimal("AVCS_SENS_TempDHTh", null);
  23.         VA.SetDecimal("AVCS_SENS_TempDHTf", null);
  24.         VA.SetDecimal("AVCS_SENS_TempDHTi", null);
  25.     }
  26.    
  27.     public void ClearMonitorVariables()
  28.     {
  29.         ClearSensorVariables();
  30.         VA.SetInt("AVCS_SENS_IntervalDHT1", null);
  31.         VA.SetText("AVCS_SENS_ComportDHT1", null);
  32.         VA.SetBoolean("AVCS_SENS_MonitoringDHT1", null);
  33.         VA.SetBoolean("AVCS_SENS_SensorTestDHT1", null);
  34.     }
  35.    
  36.     public void SensorMonitoringEnd()
  37.     {
  38.         ClearMonitorVariables();
  39.         VA.WriteToLog("External AVCS-DHT1 Sensor Monitor has been terminated...", "black");
  40.     }
  41.    
  42.     public void SensorTestFailure()
  43.     {
  44.         ClearMonitorVariables();
  45.         VA.WriteToLog("AVCS-DHT1 Sensor Identification Test FAILURE!", "red");
  46.         VA.WriteToLog("Please check USB connection of AVCS-DHT1 Sensor. See user guide for more information.", "red");
  47.         VA.SetText("AVCS_SENS_Test_ReturnTTS", "Test failed. Please check device or settings.");
  48.     }
  49.    
  50.     public void SensorIdentifyFailure()
  51.     {
  52.         ClearMonitorVariables();
  53.         VA.WriteToLog("External AVCS-DHT1 Sensor comport not found...", "black");
  54.         VA.WriteToLog("Diagnostic & indoor weather commands will be unavailable", "black");
  55.     }
  56.    
  57.     private void WriteToLog_Long(string longString, string colorString)
  58.     {
  59.         StringBuilder sb = new StringBuilder();
  60.         string[] longStringSegments = longString.Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
  61.        
  62.         //Write each new line of log data, break up any longer than approximate min-width of VA window (~91) to new lines
  63.         for (int a = 0; a < longStringSegments.Length; a++)
  64.         {
  65.             if (longStringSegments[a].Length > 91)
  66.             {
  67.                 sb.Append(longStringSegments[a].ToString());
  68.                 while (sb.Length > 91)
  69.                 {
  70.                     try
  71.                     {
  72.                         VA.WriteToLog(sb.ToString(0, 91), colorString);
  73.                         sb.Remove(0, 91);
  74.                     }
  75.                     catch
  76.                     {
  77.                         //ignore
  78.                     }
  79.                     finally
  80.                     {
  81.                         if (sb.Length <= 91)
  82.                             VA.WriteToLog(sb.ToString(), colorString);
  83.                     }
  84.                 }
  85.             }
  86.             else
  87.             {
  88.                 //Lines already less than 91 characters
  89.                 VA.WriteToLog(longStringSegments[a], colorString);
  90.             }
  91.         }
  92.     }
  93.    
  94.     public decimal TTS_GetRoundedDecimal(string thisStringDec, int decimalPlaces)
  95.     {
  96.         //For Text-To-Speech brevity, return decimal that does not end in .00'
  97.         decimal thisDecimal = Decimal.Round(Convert.ToDecimal(thisStringDec), decimalPlaces);
  98.         decimal truncatedDecimal = Decimal.Truncate(thisDecimal);
  99.         if (truncatedDecimal != thisDecimal)
  100.             return thisDecimal;
  101.        
  102.         return truncatedDecimal;
  103.     }
  104.    
  105.     private string GetArduinoSerialData(string PortDHT1)
  106.     {
  107.         System.IO.Ports.SerialPort SerialPortDHT1 = new System.IO.Ports.SerialPort();
  108.         bool debugging = false;
  109.         if (VA.GetBoolean("AVCS_SENS_DebugArduino") == true)
  110.             debugging = true;
  111.        
  112.         string incoming = "";
  113.         string dataBuild = "";
  114.         bool dataComplete = false;
  115.         int serialReadTimeouts = 0;
  116.         int timeoutsMax = 4;
  117.         int dataChars = 1;
  118.         byte[] inBuffer = new byte[1];
  119.        
  120.         SerialPortDHT1.PortName = PortDHT1;
  121.         SerialPortDHT1.BaudRate = 9600;
  122.         SerialPortDHT1.DataBits = 8;
  123.         SerialPortDHT1.Parity = Parity.None;
  124.         SerialPortDHT1.StopBits = StopBits.One;
  125.         SerialPortDHT1.Handshake = Handshake.None;
  126.         SerialPortDHT1.Encoding = System.Text.Encoding.Default;
  127.         SerialPortDHT1.ReadTimeout = 100;
  128.         if (SerialPortDHT1 != null)
  129.         {
  130.             if (SerialPortDHT1.IsOpen)
  131.             {
  132.                 SerialPortDHT1.Close();
  133.                 while (SerialPortDHT1.IsOpen)
  134.                     Thread.Sleep(100);
  135.                 //Thread.Sleep(2000); //Restart Delay for Arduino Sketch?
  136.             }
  137.            
  138.             try
  139.             {
  140.                 SerialPortDHT1.Open();
  141.                 Thread.Sleep(100);
  142.             }
  143.             catch (Exception ex)
  144.             {
  145.                 dataComplete = true;
  146.                 dataBuild = "nothing";
  147.                 if (debugging)
  148.                     WriteToLog_Long("AVCS Error: Serial Port Open() ended on exception" +
  149.                                         Environment.NewLine + "Error Details:" +
  150.                                         Environment.NewLine + ex.ToString(), "red");
  151.             }
  152.            
  153.             while (dataComplete != true)
  154.             {
  155.                 try
  156.                 {
  157.                     SerialPortDHT1.Read(inBuffer, 0, 1);
  158.                     incoming = Encoding.ASCII.GetString(inBuffer, 0, inBuffer.Length);
  159.                     if (String.IsNullOrEmpty(incoming))
  160.                     {
  161.                         incoming = "nothing";
  162.                     }
  163.                     else
  164.                     {
  165.                         if (String.IsNullOrEmpty(dataBuild))
  166.                         {
  167.                             if (incoming == "[")
  168.                                 dataBuild += incoming;
  169.                         }
  170.                         else
  171.                         {
  172.                             dataChars++;
  173.                             dataBuild += incoming;
  174.                             if (incoming == "]")
  175.                                 dataComplete = true;
  176.                         }
  177.                         if ((dataChars >= 39) && (dataComplete != true))
  178.                             serialReadTimeouts = timeoutsMax;
  179.                     }
  180.                 }
  181.                 catch (TimeoutException e)
  182.                 {
  183.                     serialReadTimeouts += 1;
  184.                     if (debugging)
  185.                         VA.WriteToLog("AVCS Error: Serial Port read timed out.", "red");
  186.                 }
  187.                 finally
  188.                 {
  189.                     if ((serialReadTimeouts >= timeoutsMax) && (dataComplete != true))
  190.                     {
  191.                         dataComplete = true;
  192.                         dataBuild = "nothing";
  193.                         if (debugging)
  194.                             VA.WriteToLog("AVCS Error: Serial Port data read ended on timeout", "red");
  195.                     }
  196.                 }
  197.             }
  198.             SerialPortDHT1.Dispose();
  199.         }
  200.         return dataBuild;
  201.     }
  202.    
  203.     private string GetArduinoPortName(string portRegExCheck)
  204.     {
  205.         string portNameDHT = "";
  206.         string receivedData = "";
  207.         string[] ports = SerialPort.GetPortNames().Distinct().ToArray();
  208.         int serialPortAttemptsMax = 8;
  209.         if (ports.Length > 0)
  210.             serialPortAttemptsMax = ports.Length * serialPortAttemptsMax;
  211.        
  212.         for (int serialPortAttempts = 0; serialPortAttempts <= serialPortAttemptsMax; serialPortAttempts++)
  213.         {
  214.             foreach (string port in ports)
  215.             {
  216.                 try
  217.                 {
  218.                     receivedData = GetArduinoSerialData(port);
  219.                 }
  220.                 catch
  221.                 {
  222.                     receivedData = "nothing";
  223.                 }
  224.                 finally
  225.                 {
  226.                     if (Regex.IsMatch(receivedData, portRegExCheck))
  227.                         portNameDHT = port;
  228.                 }
  229.                 if (portNameDHT != "")
  230.                     break;
  231.             }
  232.             if (portNameDHT != "")
  233.                 break;
  234.         }
  235.        
  236.         if ((VA.GetBoolean("AVCS_SENS_SensorTestDHT1") == true) && (portNameDHT != ""))
  237.         {
  238.             VA.WriteToLog("AVCS-DHT1 Data: " + receivedData, "blue");
  239.             VA.WriteToLog("AVCS-DHT1 Sensor Test has succeeded!", "green");
  240.             VA.SetText("AVCS_SENS_Test_ReturnTTS", "Test succeeded.");
  241.         }
  242.        
  243.         return portNameDHT;
  244.     }
  245.    
  246.     private bool ContinuingSystemsOperationEnded()
  247.     {
  248.         //Continuing Operations Check - if not monitoring other systems, end this monitor timer
  249.         int checkSystems = 0;
  250.         if (VA.GetBoolean("AVCS_OWM_Monitor_Startup") != true)
  251.         {
  252.             if (VA.GetBoolean("AVCS_OWM_Monitoring") != true)
  253.                 checkSystems++;
  254.         }
  255.         if (VA.GetBoolean("AVCS_SENS_Monitor_Startup") != true)
  256.         {
  257.             if (VA.GetBoolean("AVCS_SENS_Monitoring") != true)
  258.                 checkSystems++;
  259.         }
  260.         if (checkSystems == 2)
  261.             return true;
  262.        
  263.         return false;
  264.     }
  265.    
  266.     private void MonitorTimer(double MonitorTimerDelay)
  267.     {
  268.         VA.WriteToLog("AVCS-DHT1 Sensor Monitor is now running...", "black");
  269.         VA.SetBoolean("AVCS_SENS_TimerWorkingDHT1", null);
  270.         VA.SetInt("AVCS_SENS_IntervalDHT1", null);
  271.         System.Timers.Timer t = new System.Timers.Timer(MonitorTimerDelay);
  272.         t.Elapsed += MonitorTimerElapsed;
  273.         t.Start();
  274.     }
  275.    
  276.     private void MonitorTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
  277.     {
  278.         if (VA.GetBoolean("AVCS_SENS_TimerWorkingDHT1") != true)
  279.         {
  280.             VA.SetBoolean("AVCS_SENS_TimerWorkingDHT1", true);
  281.             bool debugging = false;
  282.             if (VA.GetBoolean("AVCS_SENS_DebugArduino") == true)
  283.                 debugging = true;
  284.            
  285.             if (VA.GetBoolean("AVCS_SENS_MonitoringDHT1") != true)
  286.             {
  287.                 SensorMonitoringEnd();
  288.                 (sender as System.Timers.Timer).Stop();
  289.             }
  290.             else
  291.             {
  292.                 // Serial Data in format: [AVCS,-cc.cc,hh.hh,-ff.ff,-xx.xx,DHT1]  *negatives possible yet highly unlikely
  293.                 string dataRegEx = @"^\[AVCS\,\-?\d\d\.\d\d\,\d\d\.\d\d\,\-?\d\d\.\d\d\,\-?\d\d\.\d\d\,DHT1\]$";
  294.                 string comPort = "";
  295.                 string receivedData = "";
  296.                 int ArduinoCheckDelay = 15; //in multiples of MonitorTimerDelay (default 15*2000 == 30 seconds)
  297.                 int intervalDHT = Convert.ToInt32(VA.ParseTokens("{INT:AVCS_SENS_IntervalDHT1:" + ArduinoCheckDelay.ToString() + "}"));
  298.                 intervalDHT++;
  299.                 if (intervalDHT > ArduinoCheckDelay)
  300.                     intervalDHT = 0;
  301.                 VA.SetInt("AVCS_SENS_IntervalDHT1", intervalDHT);
  302.                
  303.                 if (debugging)
  304.                     VA.WriteToLog("DHT INTERVAL: " + intervalDHT.ToString(), "purple");
  305.                
  306.                 if (VA.GetBoolean("AVCS_SENS_SensorTestDHT1") == true)
  307.                     VA.SetText("AVCS_SENS_ComportDHT1", null);
  308.                
  309.                 if ((intervalDHT == 0) || (VA.GetBoolean("AVCS_SENS_SensorTestDHT1") == true))
  310.                 {
  311.                     if (String.IsNullOrEmpty(VA.GetText("AVCS_SENS_ComportDHT1")))
  312.                     {
  313.                         comPort = GetArduinoPortName(dataRegEx);
  314.                         if (debugging)
  315.                             VA.WriteToLog("COMPORT = " + comPort, "pink");
  316.                         if (comPort.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
  317.                         {
  318.                             VA.SetText("AVCS_SENS_ComportDHT1", comPort);
  319.                         }
  320.                         else
  321.                         {
  322.                             comPort = "";
  323.                             if (VA.GetBoolean("AVCS_SENS_SensorTestDHT1") == true)
  324.                             {
  325.                                 SensorTestFailure();
  326.                             }
  327.                             else
  328.                             {
  329.                                 SensorIdentifyFailure();
  330.                             }
  331.                         }
  332.                     }
  333.                     else
  334.                     {
  335.                         comPort = VA.GetText("AVCS_SENS_ComportDHT1");
  336.                     }
  337.                    
  338.                     //Clear Testing Variable after test run (if true)
  339.                     if (VA.GetBoolean("AVCS_SENS_SensorTestDHT1") == true)
  340.                         VA.SetBoolean("AVCS_SENS_SensorTestDHT1", null);
  341.                    
  342.                     //Continuing Operation Check - exit if OWM and AIDA64 monitors not running
  343.                     if ((VA.GetBoolean("AVCS_SENS_MonitoringDHT1") != true) || (ContinuingSystemsOperationEnded()))
  344.                         comPort = "";
  345.                    
  346.                     if (comPort != "")
  347.                     {
  348.                         receivedData = GetArduinoSerialData(comPort);
  349.                         if (Regex.IsMatch(receivedData, dataRegEx))
  350.                         {
  351.                             if (debugging)
  352.                                 VA.WriteToLog(receivedData.ToString(), "blue");
  353.                            
  354.                             string[] receivedDataArray = receivedData.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
  355.                             VA.SetDecimal("AVCS_SENS_TempDHTc", TTS_GetRoundedDecimal(receivedDataArray[1], 2));
  356.                             VA.SetDecimal("AVCS_SENS_TempDHTh", TTS_GetRoundedDecimal(receivedDataArray[2], 0));
  357.                             VA.SetDecimal("AVCS_SENS_TempDHTf", TTS_GetRoundedDecimal(receivedDataArray[3], 1));
  358.                             VA.SetDecimal("AVCS_SENS_TempDHTi", TTS_GetRoundedDecimal(receivedDataArray[4], 0));
  359.                         }
  360.                         else
  361.                         {
  362.                             //When a single read of previously good ComPort fails, null the ComPort var for one last try on next interval
  363.                             if (debugging)
  364.                                 VA.WriteToLog("RegEx was not match - circling back to try again: " + receivedData,"pink");
  365.                            
  366.                             VA.SetText("AVCS_SENS_ComportDHT1", null);
  367.                             VA.SetInt("AVCS_SENS_IntervalDHT1", ArduinoCheckDelay); //bypass 30 second wait for last try before quitting
  368.                         }
  369.                     }
  370.                     else
  371.                     {
  372.                         SensorMonitoringEnd();
  373.                         (sender as System.Timers.Timer).Stop();
  374.                     }
  375.                 }
  376.             }
  377.             //Clear Startup Variable after first run (if true)
  378.             if (VA.GetBoolean("AVCS_DHT1_Monitor_Startup") == true)
  379.                 VA.SetBoolean("AVCS_DHT1_Monitor_Startup", null);
  380.             //Final Continuing Operation Check - exit if OWM and AIDA64 monitors not running
  381.             if (ContinuingSystemsOperationEnded())
  382.                 VA.SetBoolean("AVCS_SENS_MonitoringDHT1", false);
  383.            
  384.             VA.SetBoolean("AVCS_SENS_TimerWorkingDHT1", false);
  385.         }
  386.     }
  387.    
  388.     public void main()
  389.     {
  390.         //DEV DEBUGGING -- Sets SENS_MONITORING to true to simulate systems running and keep this loop active
  391.         #if (DEBUG)
  392.             VA.SetBoolean("AVCS_SENS_Monitoring", true); // (means AIDA64 monitoring is on, allows this test to loop)
  393.             VA.SetBoolean("AVCS_SENS_DebugArduino", true);
  394.         #endif
  395.        
  396.         if (VA.GetBoolean("AVCS_SENS_MonitoringDHT1") != true)
  397.         {
  398.             #if (DEBUG)
  399.                 VA.ClearLog();
  400.             #endif
  401.             ClearSensorVariables();
  402.             VA.SetBoolean("AVCS_SENS_MonitoringDHT1", true);
  403.             MonitorTimer(MonitorTimerDelay);
  404.         }
  405.         #if (DEBUG)
  406.         else //DEV DEBUGGING ELSE -- for TEST RUN Toggle On/Off in editor
  407.         {
  408.             VA.WriteToLog("DEV DISABLE BOOLS - RESET TEST", "grey");
  409.             VA.SetBoolean("AVCS_SENS_Monitoring", false);
  410.             VA.SetBoolean("AVCS_SENS_MonitoringDHT1", false);
  411.             VA.SetBoolean("AVCS_SENS_DebugArduino", false);
  412.         }
  413.         #endif
  414.     }
  415. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement