moel@420: /* moel@420: moel@420: This Source Code Form is subject to the terms of the Mozilla Public moel@420: License, v. 2.0. If a copy of the MPL was not distributed with this moel@420: file, You can obtain one at http://mozilla.org/MPL/2.0/. moel@420: moel@420: Copyright (C) 2013 Michael Möller moel@420: moel@420: */ moel@420: moel@420: using System; moel@420: using System.Collections.Generic; moel@420: using System.Globalization; moel@420: using System.IO; moel@420: using System.Linq; moel@420: using OpenHardwareMonitor.Hardware; moel@420: moel@420: namespace OpenHardwareMonitor.Utilities { moel@420: public class Logger { moel@420: moel@420: private const string fileNameFormat = moel@420: "OpenHardwareMonitorLog-{0:yyyy-MM-dd}.csv"; moel@420: moel@420: private readonly IComputer computer; moel@420: moel@420: private DateTime day = DateTime.MinValue; moel@420: private string fileName; moel@421: private string[] identifiers; moel@420: private ISensor[] sensors; moel@420: moel@422: private DateTime lastLoggedTime = DateTime.MinValue; moel@422: moel@420: public Logger(IComputer computer) { moel@420: this.computer = computer; moel@420: this.computer.HardwareAdded += HardwareAdded; moel@422: this.computer.HardwareRemoved += HardwareRemoved; moel@420: } moel@420: moel@420: private void HardwareRemoved(IHardware hardware) { moel@421: hardware.SensorAdded -= SensorAdded; moel@420: hardware.SensorRemoved -= SensorRemoved; moel@420: foreach (ISensor sensor in hardware.Sensors) moel@420: SensorRemoved(sensor); moel@420: foreach (IHardware subHardware in hardware.SubHardware) moel@420: HardwareRemoved(subHardware); moel@420: } moel@420: moel@420: private void HardwareAdded(IHardware hardware) { moel@421: foreach (ISensor sensor in hardware.Sensors) moel@421: SensorAdded(sensor); moel@421: hardware.SensorAdded += SensorAdded; moel@420: hardware.SensorRemoved += SensorRemoved; moel@420: foreach (IHardware subHardware in hardware.SubHardware) moel@420: HardwareAdded(subHardware); moel@420: } moel@420: moel@421: private void SensorAdded(ISensor sensor) { moel@421: if (sensors == null) moel@421: return; moel@421: moel@421: for (int i = 0; i < sensors.Length; i++) { moel@421: if (sensor.Identifier.ToString() == identifiers[i]) moel@421: sensors[i] = sensor; moel@421: } moel@421: } moel@421: moel@420: private void SensorRemoved(ISensor sensor) { moel@421: if (sensors == null) moel@421: return; moel@421: moel@420: for (int i = 0; i < sensors.Length; i++) { moel@420: if (sensor == sensors[i]) moel@420: sensors[i] = null; moel@420: } moel@420: } moel@420: moel@420: private static string GetFileName(DateTime date) { moel@420: return AppDomain.CurrentDomain.BaseDirectory + moel@420: Path.DirectorySeparatorChar + string.Format(fileNameFormat, date); moel@420: } moel@420: moel@420: private bool OpenExistingLogFile() { moel@420: if (!File.Exists(fileName)) moel@420: return false; moel@420: moel@420: try { moel@420: String line; moel@420: using (StreamReader reader = new StreamReader(fileName)) moel@420: line = reader.ReadLine(); moel@420: moel@420: if (string.IsNullOrEmpty(line)) moel@420: return false; moel@420: moel@420: identifiers = line.Split(',').Skip(1).ToArray(); moel@420: } catch { moel@421: identifiers = null; moel@420: return false; moel@420: } moel@420: moel@421: if (identifiers.Length == 0) { moel@421: identifiers = null; moel@420: return false; moel@421: } moel@420: moel@420: sensors = new ISensor[identifiers.Length]; moel@420: SensorVisitor visitor = new SensorVisitor(sensor => { moel@420: for (int i = 0; i < identifiers.Length; i++) moel@420: if (sensor.Identifier.ToString() == identifiers[i]) moel@420: sensors[i] = sensor; moel@420: }); moel@420: visitor.VisitComputer(computer); moel@420: return true; moel@420: } moel@420: moel@420: private void CreateNewLogFile() { moel@420: IList list = new List(); moel@420: SensorVisitor visitor = new SensorVisitor(sensor => { moel@420: list.Add(sensor); moel@420: }); moel@420: visitor.VisitComputer(computer); moel@421: sensors = list.ToArray(); moel@421: identifiers = sensors.Select(s => s.Identifier.ToString()).ToArray(); moel@420: moel@420: using (StreamWriter writer = new StreamWriter(fileName, false)) { moel@420: writer.Write(","); moel@420: for (int i = 0; i < sensors.Length; i++) { moel@420: writer.Write(sensors[i].Identifier); moel@420: if (i < sensors.Length - 1) moel@420: writer.Write(","); moel@420: else moel@420: writer.WriteLine(); moel@420: } moel@420: moel@420: writer.Write("Time,"); moel@420: for (int i = 0; i < sensors.Length; i++) { moel@420: writer.Write('"'); moel@420: writer.Write(sensors[i].Name); moel@420: writer.Write('"'); moel@420: if (i < sensors.Length - 1) moel@420: writer.Write(","); moel@420: else moel@420: writer.WriteLine(); moel@420: } moel@420: } moel@420: } moel@420: moel@422: public TimeSpan LoggingInterval { get; set; } moel@422: moel@422: public void Log() { moel@420: var now = DateTime.Now; moel@422: moel@422: if (lastLoggedTime + LoggingInterval - new TimeSpan(5000000) > now) moel@422: return; moel@422: moel@421: if (day != now.Date || !File.Exists(fileName)) { moel@420: day = now.Date; moel@420: fileName = GetFileName(day); moel@420: moel@420: if (!OpenExistingLogFile()) moel@420: CreateNewLogFile(); moel@420: } moel@420: moel@421: try { moel@421: using (StreamWriter writer = new StreamWriter(new FileStream(fileName, moel@421: FileMode.Append, FileAccess.Write, FileShare.ReadWrite))) { moel@421: writer.Write(now.ToString("G", CultureInfo.InvariantCulture)); moel@421: writer.Write(","); moel@421: for (int i = 0; i < sensors.Length; i++) { moel@421: if (sensors[i] != null) { moel@421: float? value = sensors[i].Value; moel@421: if (value.HasValue) moel@421: writer.Write( moel@421: value.Value.ToString("R", CultureInfo.InvariantCulture)); moel@421: } moel@421: if (i < sensors.Length - 1) moel@421: writer.Write(","); moel@421: else moel@421: writer.WriteLine(); moel@420: } moel@420: } moel@421: } catch (IOException) { } moel@422: moel@422: lastLoggedTime = now; moel@420: } moel@420: } moel@420: }