internal SensorCommunity(Support s) { string line; Sup = s; Sup.LogDebugMessage($"SensorCommunity ctor: Start"); SensorCommunityHttpClient = new HttpClient(); SensorCommunityHttpClient.Timeout = TimeSpan.FromSeconds(30); SensorCommunityHttpClient.BaseAddress = new Uri(URL); using (StreamReader cpuFile = new StreamReader("/proc/cpuinfo")) { line = cpuFile.ReadLine(); Sup.LogDebugMessage($"SensorCommunity ctor reading cpuinfo: {line}"); do { if (line.Contains("Serial", StringComparison.InvariantCultureIgnoreCase)) { Sup.LogDebugMessage($"SensorCommunity ctor: Serial line found => {line}"); string[] splitstring = line.Split(':'); SensorID = "raspi-" + splitstring[1].Trim(); Sup.LogDebugMessage($"SensorCommunity ctor: SensorID = {SensorID}"); break; } line = cpuFile.ReadLine(); } while (true); // end while } // end using => disposes the cpuFile Sup.LogDebugMessage($"SensorCommunity ctor end"); } // end constructor
static public void DetectSensors(Support Sup) { Sup.LogDebugMessage("I2C Detect"); Sup.LogDebugMessage("==============="); _I2CDetect = new I2cDetect(); var list = _I2CDetect.Detect(); foreach (var i2c in list) { int r = i2c / 16; int c = i2c % 16; _nDevices[r, c] = 1; // Check if the devices we want are present for (int i = 0; i < i2cAddress.Length; i++) { if (i2c == i2cAddress[i]) { i2cAddressDetected[i] = true; Sup.LogDebugMessage($"DetectSensors: found {Enum.GetName( typeof( I2cSensorsSupported ), i )} at {i2c:x2} "); } } } Sup.LogDebugMessage(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"); for (int i = 0; i < _rows; i++) { PrintRow(i, Sup); } }
public I2cSimulatorDevice(Support s, string Name) { Sup = s; Sup.LogDebugMessage($"I2cSimulatorDevice Constructor...{Name}"); SensorUsed = I2cSensorsSupported.Simulator; Valid = true; }
public I2cDummyDevice(Support s, string Name) { Sup = s; Sup.LogDebugMessage($"Dummy Constructor...{Name}"); SensorUsed = I2cSensorsSupported.Dummy; Valid = false; }
public double NowCast25, NowCast10; // Just need one parameter, after calculation // it is send by the webserver and can be forgotten. public EmulateAirLink(Support s) { Sup = s; Sup.LogDebugMessage($"AirLink Emulator: Constructor and started"); DoCalibrated = Sup.GetSensorsIniValue("General", "UseCalibration", "True").Equals("true", StringComparison.OrdinalIgnoreCase); }
public List <I2cSensordata> ObservationList = new List <I2cSensordata>(); // The list to create the minutevalues. Filled in DoWork(), Cleared in SetMinuteValuesFromObservations() public I2C(Support s, string Name) { Sup = s; Sup.LogDebugMessage($"I2C Constructor {Name}"); // Make all addresses i2cAddress[(int)I2cSensorsSupported.SHT31] = 0x44; // Now create the actual device try { SensorUsed = (I2cSensorsSupported)Enum.Parse(typeof(I2cSensorsSupported), Name, true); switch (SensorUsed) { case I2cSensorsSupported.SHT31: Sup.LogDebugMessage("I2C Constructor: Creating SHT31 sensor"); Sensor = new SHT31Device(Sup, Name); break; case I2cSensorsSupported.Simulator: Sup.LogDebugMessage("I2C Constructor: Creating SHT31 sensor"); Sensor = new I2cSimulatorDevice(Sup, Name); break; default: Sup.LogDebugMessage($"I2C Constructor: I2c sensor not implemented {SensorUsed}"); Sensor = new I2cDummyDevice(Sup, Name); break; } Sensor.Start(); } catch (Exception e) when(e is ArgumentException || e is ArgumentNullException) { // We arrive here if the sensor does not exist in the Enum definition Sup.LogTraceErrorMessage($"I2C Constructor: Exception on parsing I2cDevice Name : {e.Message}"); Sup.LogTraceErrorMessage("Either an error in naming or driver not implemented."); Sup.LogTraceErrorMessage("Replacing this device by a Dummy Driver. Continuing..."); Sensor = new I2cDummyDevice(Sup, Name); } }// Constructor
public List <PMSensordata> ObservationList = new List <PMSensordata>(); // The list to create the minutevalues public Serial(Support s, string Name) { Sup = s; Sup.LogDebugMessage($"Serial: Constructor...{Name}"); try { SensorUsed = (SerialSensorsSupported)Enum.Parse(typeof(SerialSensorsSupported), Name, true); switch (SensorUsed) { case SerialSensorsSupported.PMS1003: Sup.LogDebugMessage("Serial Constructor: Creating PMS1003 sensor"); Sensor = new PMS1003Device(Sup, Name); break; case SerialSensorsSupported.Simulator: Sup.LogDebugMessage("Serial Constructor: Creating PMS1003 sensor"); Sensor = new SerialSimulatorDevice(Sup, Name); break; default: Sup.LogDebugMessage($"Serial Constructor: Serial sensor not implemented {SensorUsed}"); Sensor = new SerialDummyDevice(Sup, Name); break; } Sensor.Open(); // Also called Open in some circles } catch (Exception e) when(e is ArgumentException || e is ArgumentNullException) { // We arrive here if the sensor does not exist in the Enum definition Sup.LogTraceErrorMessage($"Serial Constructor: Exception on parsing Serial Device Name : {e.Message}"); Sup.LogTraceErrorMessage("Either an error in naming or driver not implemented."); Sup.LogTraceErrorMessage("Replacing this device by a Dummy Driver. Continuing..."); Sensor = new SerialDummyDevice(Sup, Name); } }// Serial Constructor
internal DefinitionSerialPort(Support s, string Name) { Sup = s; Sup.LogDebugMessage($"DefinitionSerialPort Constructor..."); try { SerialPortUsed = Sup.GetSensorsIniValue("PortDefinitions", $"{Name}_SerialPort", "/dev/ttyS0"); SerialBaudRate = Convert.ToInt32(Sup.GetSensorsIniValue("PortDefinitions", $"{Name}_SerialBaudrate", "9600")); SerialParity = (Parity)Enum.Parse(typeof(Parity), Sup.GetSensorsIniValue("PortDefinitions", $"{Name}_SerialParity", "None"), true); SerialDataBits = Convert.ToInt32(Sup.GetSensorsIniValue("PortDefinitions", $"{Name}_SerialDataBits", "8")); SerialNrOfStopBits = (StopBits)Enum.Parse(typeof(StopBits), Sup.GetSensorsIniValue("PortDefinitions", $"{Name}_SerialStopBits", "One"), true); } catch (Exception e) when(e is ArgumentException || e is ArgumentNullException || e is OverflowException || e is FormatException) { Sup.LogTraceErrorMessage($"Serial: Exception on Serial Port definitions in Inifile : {e.Message}"); } }
static private void PrintRow(int rowId, Support Sup) { string row = string.Format("{0:00}: ", rowId); for (int i = 0; i < _cols; i++) { if ((rowId == 0 && i < 3) || (rowId == 7 && i > 7)) { row += " "; } else if (_nDevices[rowId, i] == 0) { row += string.Format("-- "); } else { row += string.Format("{0}{1:X} ", rowId, i); } } Sup.LogDebugMessage(row); }
public override void Start() { Sup.LogDebugMessage($"I2cSensorDevice {SensorUsed} Start on address {I2C.i2cAddress[ (int) SensorUsed ]:x2}"); thisConnect = Program.ThisDriver.Connect(I2C.i2cAddress[(int)SensorUsed]); }
void Init() { bool NoSerialDevice = false; bool NoI2cDevice = false; // Setup logging and Ini Sup = new Support(); Sup.LogDebugMessage(message: "Init() : Start"); string AirLinkPMDevice = ""; string AirLinkTHDevice = ""; Console.CancelKeyPress += new ConsoleCancelEventHandler(CtrlCHandler); CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; // Setup tracing Trace.Listeners.Add(new TextWriterTraceListener($"log/{DateTime.Now.ToString( "yyMMddHHmm", CultureInfo.InvariantCulture )}sensors.log")); Trace.AutoFlush = true; CUSensorsSwitch = new TraceSwitch("CUSensorsSwitch", "Tracing switch for CUSensors") { Level = TraceLevel.Verbose }; Sup.LogDebugMessage($"Initial {CUSensorsSwitch} => Error: {CUSensorsSwitch.TraceError}, Warning: {CUSensorsSwitch.TraceWarning}, Info: {CUSensorsSwitch.TraceInfo}, Verbose: {CUSensorsSwitch.TraceVerbose}, "); string thisTrace = Sup.GetSensorsIniValue("General", "TraceInfo", "Warning"); // Verbose, Information, Warning, Error, Off // Now set the Trace level to the wanted value switch (thisTrace.ToLower()) { case "error": CUSensorsSwitch.Level = TraceLevel.Error; break; case "warning": CUSensorsSwitch.Level = TraceLevel.Warning; break; case "info": CUSensorsSwitch.Level = TraceLevel.Info; break; case "verbose": CUSensorsSwitch.Level = TraceLevel.Verbose; break; default: CUSensorsSwitch.Level = TraceLevel.Off; break; } Sup.LogDebugMessage($"According to Inifile {CUSensorsSwitch} => Error: {CUSensorsSwitch.TraceError}, Warning: {CUSensorsSwitch.TraceWarning}, Info: {CUSensorsSwitch.TraceInfo}, Verbose: {CUSensorsSwitch.TraceVerbose}, "); // Determine which sensor has to be for the AirLink: AirLinkEmulation = Sup.GetSensorsIniValue("General", "AirLinkEmulation", "false").Equals("true", StringComparison.OrdinalIgnoreCase); AirLinkPMDevice = Sup.GetSensorsIniValue("AirLinkDevices", $"PMdevice", ""); AirLinkTHDevice = Sup.GetSensorsIniValue("AirLinkDevices", $"THdevice", ""); // Check if we want AirLinkEmulation and do accordingly // if (AirLinkEmulation) { Sup.LogDebugMessage(message: "Init : Creating the AirLink Emulator and the Webserver"); thisEmulator = new EmulateAirLink(Sup); thisWebserver = new WebServer(Sup, thisEmulator); } // Do the Serial devices Sup.LogDebugMessage(message: "Init : Creating the Serial devices"); for (int i = 0; i < MaxNrSerialSensors; i++) { string DeviceName = Sup.GetSensorsIniValue("SerialDevices", $"Serial{i}", ""); thisSerial[i] = new Serial(Sup, DeviceName); if (AirLinkEmulation && $"Serial{i}" == AirLinkPMDevice) { Sup.LogDebugMessage(message: $"Init : Serial{i} is AirLink device"); thisSerial[i].IsAirLinkSensor = true; thisEmulator.SetSerialDevice(thisSerial[i]); } if (i == 0 && string.IsNullOrEmpty(DeviceName)) { NoSerialDevice = true; break; } }// Serial devices // Do the i2c devices // Define the driver on this level so we only have one driver in the system on which we open all connections Sup.LogTraceInfoMessage(message: "Init : Creating the I2C driver"); ThisDriver = new I2cDriver(ProcessorPin.Gpio02, ProcessorPin.Gpio03, false); Sup.LogTraceInfoMessage(message: $"Init : created the I2cDriver {ThisDriver}"); I2C.DetectSensors(Sup); for (int i = 0; i < MaxNrI2cSensors; i++) { string DeviceName = Sup.GetSensorsIniValue("I2CDevices", $"I2C{i}", ""); thisI2C[i] = new I2C(Sup, DeviceName); if (AirLinkEmulation && $"I2C{i}" == AirLinkTHDevice) { Sup.LogDebugMessage(message: $"Init : I2C{i} is AirLink device"); thisI2C[i].IsAirLinkSensor = true; thisEmulator.SetI2cDevice(thisI2C[i]); } if (i == 0 && string.IsNullOrEmpty(DeviceName)) { NoI2cDevice = true; break; } }// i2c devices if (AirLinkEmulation && (NoI2cDevice || NoSerialDevice)) { Sup.LogDebugMessage("Init: At leat one serial and one I2c device is required for PM and T/H in AirLink emulation"); Environment.Exit(0); } if (AirLinkEmulation) { Sup.LogDebugMessage(message: $"Init : Starting the webserver"); thisWebserver.Start(); // Do the SensorCommunity Init DoSensorCommunity = Sup.GetSensorsIniValue("General", "SensorCommunity", "false").Equals("true", StringComparison.OrdinalIgnoreCase); Sup.LogDebugMessage(message: $"Init : Starting SensorCommunity: SensorCommunity is {DoSensorCommunity}"); if (DoSensorCommunity) { thisSensorCommunity = new SensorCommunity(Sup); } } } // Init
async Task RealMain() { Init(); Sup.LogDebugMessage(message: "ZeroWsensors : ----------------------------"); Sup.LogDebugMessage(message: "ZeroWsensors : Entering Main"); Console.WriteLine($"{Sup.Version()} {Sup.Copyright}"); Sup.LogDebugMessage($"{Sup.Version()} {Sup.Copyright}"); Console.WriteLine("This program comes with ABSOLUTELY NO WARRANTY;\n" + "This is free software, and you are welcome to redistribute it under certain conditions."); Sup.LogDebugMessage("This program comes with ABSOLUTELY NO WARRANTY;\n" + "This is free software, and you are welcome to redistribute it under certain conditions."); #region MainLoop // Start the loop using (StreamWriter of = new StreamWriter("CUSensorArray.txt", true)) { int Clock = 0; do { string thisLine = ""; // Do this condional because the ctrl-c interrupt can be given aanywhere. Sup.LogTraceInfoMessage(message: "ZeroWsensors : Getting sensor values from the Main 10 second loop"); if (Continue) { Clock++; for (int i = 0; i < MaxNrSerialSensors; i++) { thisSerial[i].DoWork(); // Takes care of the reading of the serial devices } for (int i = 0; i < MaxNrI2cSensors; i++) { thisI2C[i].DoWork(); // Takes care of the reading of the I2C devices } // So we came here 6 times every 10 seconds. Create the minute values and remove the existing list, create a new one // The average values are always real averages even if some fetches failed in which case the list is shorter // This is the basic work of the sensor handler: fetch data and write to local logfile if (Clock == 6) { Clock = 0; for (int i = 0; i < MaxNrSerialSensors; i++) { thisSerial[i].SetMinuteValuesFromObservations(); } for (int i = 0; i < MaxNrI2cSensors; i++) { thisI2C[i].SetMinuteValuesFromObservations(); } // Now we do the AirLink handling which is assumed to be called once per minute with the observation list to create // all other necessary lists and calculated values from there if (AirLinkEmulation) { thisEmulator.DoAirLink(); // When all done Write out the values to SensorCommunity if (DoSensorCommunity) { await thisSensorCommunity.Send(thisEmulator); } } // Write out to the logfile for (int i = 0; i < MaxNrSerialSensors; i++) { thisLine += $";{thisSerial[ i ].MinuteValues.Pm1_atm:F1};{thisSerial[ i ].MinuteValues.Pm25_atm:F1};{thisSerial[ i ].MinuteValues.Pm10_atm:F1}"; } for (int i = 0; i < MaxNrI2cSensors; i++) { thisLine += $";{thisI2C[ i ].MinuteValues.TemperatureC:F1};{thisI2C[ i ].MinuteValues.Humidity:F0}"; } Sup.LogTraceInfoMessage(message: "ZeroWsensors : Writing out the data to the logfile"); Sup.LogTraceInfoMessage(message: $"{DateTime.Now:dd-MM-yyyy HH:mm}{thisLine}"); of.WriteLine($"{DateTime.Now:dd-MM-yyyy HH:mm}{thisLine}"); of.Flush(); } } // This is really hardcoded and should NOT change. The whole thing is based on 6 measurements per minute, so loop every 10 seconds Thread.Sleep(10000); } while (Continue); // Do-While } // Using the datafile #endregion Sup.LogDebugMessage("SensorArray Gracefull exit... End"); Trace.Flush(); Trace.Close(); return; } // Real main()