public async Task <List <EnergyPriceClass> > QueryEnergyPriceAsync() { Methods = new METHOD(); string fileToday = $"CurrentEnergyPrice{METHOD.DateTimeTZ():dd-MM-yyyy}"; string fileYesterday = $"CurrentEnergyPrice{METHOD.DateTimeTZ().AddDays(-1):dd-MM-yyyy}"; fileToday = Methods.GetFilePath(fileToday); //delete yesterday file, we dont need to collect them fileYesterday = Methods.GetFilePath(fileYesterday); if (File.Exists(fileYesterday)) { File.Delete(fileYesterday); } if (File.Exists(fileToday)) //is there already file with today energy prices { var dataFromFile = await Methods.OpenExistingFile(fileToday); energyPriceToday = JsonSerializer.Deserialize <List <EnergyPriceClass> >(dataFromFile.ToString()); } if (!File.Exists(fileToday)) //file with today energy price is missing { try { string MarketPriceToday = METHOD.DateTimeTZ().ToString("dd.MM.yyyy"); energyPriceToday = await GetMarketPrice(MarketPriceToday); var jsonString = JsonSerializer.Serialize(energyPriceToday); await Methods.SaveStringToLocalFile(fileToday, jsonString); } catch (Exception e) { Console.WriteLine("Receive energy price from Cosmos exception: " + e.Message); } } return(energyPriceToday); }
public async void CheckHeatingTime() { while (true) { if (TelemetryDataClass.SaunaStartedTime == DateTime.MinValue) { var filename = Methods.GetFilePath(CONSTANT.FILENAME_SAUNA_TIME); if (File.Exists(filename)) //this mean that sauna has been started and system has suddenly restarted/updated { var result = await Methods.OpenExistingFile(filename); if (DateTime.TryParseExact(result, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out var SaunaStartedTime)) { TelemetryDataClass.SaunaStartedTime = SaunaStartedTime; } } } if (TelemetryDataClass.SaunaStartedTime != DateTime.MinValue) { int TotalTimeSaunaHeatedInMinutes = (int)(METHOD.DateTimeTZ().DateTime - TelemetryDataClass.SaunaStartedTime).TotalMinutes; string cmd = CommandNames.NO_COMMAND; //turn saun on if it has heating time but not turned on if (TotalTimeSaunaHeatedInMinutes < CONSTANT.MAX_SAUNA_HEATING_TIME && !TelemetryDataClass.isSaunaOn) { cmd = CommandNames.TURN_ON_SAUNA; } //turn sauna off if the time is over if (TotalTimeSaunaHeatedInMinutes > CONSTANT.MAX_SAUNA_HEATING_TIME) { cmd = CommandNames.TURN_OFF_SAUNA; } _receiveData.ProcessCommand(cmd); } await Task.Delay(TimeSpan.FromMinutes(1)); //check every minute } }
public async void ReadTemperature() { var _receiveData = new ReceiveData(); var _sensorsClient = new RinsenOneWireClient(); var _sendListData = new SendDataAzure(); var Methods = new METHOD(); //currentSumOfTempDeltas is some bigger number than the delta (0,5) is used to determine temperature changes double SumOfTemperatureDeltas = 10; //initiate the list with the temps and names ListOfAllSensors = await _sensorsClient.ReadSensors(); //fill out LastTemperatures and initial Temperature trend which is initially always TRUE ListOfAllSensors = UpdateSensorsTrendAndLastTemp(ListOfAllSensors, ListOfAllSensors); var filename = Methods.GetFilePath(CONSTANT.FILENAME_ROOM_TEMPERATURES); if (File.Exists(filename)) { var dataFromFile = await Methods.OpenExistingFile(filename); List <SensorReading> SetRoomTemps = JsonSerializer.Deserialize <List <SensorReading> >(dataFromFile); SetTemperatures(SetRoomTemps); } while (true) { //get a new sensor readings and then update SensorReadings sensorReadings = await _sensorsClient.ReadSensors(); ListOfAllSensors = UpdateSensorsTrendAndLastTemp(ListOfAllSensors, sensorReadings); //summing all the room temperature changes together add new deltas until it bigger that 4 degrees SumOfTemperatureDeltas += ListOfAllSensors.Temperatures.Where(x => x.isRoom).Sum(x => Math.Abs(x.Temperature - x.LastTemperature)); //manage Livingroom heating actuator if (ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == LIVING).isHeatingRequired) { Pins.PinWrite(Pins.livingRoomHeatControlOut, PinValue.High); } else { Pins.PinWrite(Pins.livingRoomHeatControlOut, PinValue.Low); } //manage Office heating actuator if (ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == OFFICE).isHeatingRequired) { Pins.PinWrite(Pins.homeOfficeHeatControlOut, PinValue.High); } else { Pins.PinWrite(Pins.homeOfficeHeatControlOut, PinValue.Low); } //manage Piano heating actuator bool isPianoHeatingOn = ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == PIANO).isHeatingRequired; await Shelly.SetShellySwitch(isPianoHeatingOn, Shelly.PianoHeating, nameof(Shelly.PianoHeating)); //manage Bedroom heating actuator bool isBedroomHeatingOn = ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == BEDROOM).isHeatingRequired; await Shelly.SetShellySwitch(isBedroomHeatingOn, Shelly.BedroomHeating, nameof(Shelly.BedroomHeating)); //manage sauna temperature if (ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == SAUNA).isHeatingRequired&& TelemetryDataClass.isSaunaOn) { Pins.PinWrite(Pins.saunaHeatOutPin, PinValue.Low); } else { Pins.PinWrite(Pins.saunaHeatOutPin, PinValue.High); } //if sauna extremely hot, then turn off if (ListOfAllSensors.Temperatures.FirstOrDefault(x => x.RoomName == SAUNA).Temperature > CONSTANT.EXTREME_SAUNA_TEMP) { _receiveData.ProcessCommand(CommandNames.TURN_OFF_SAUNA); } //if all rooms has achieved their target temperature then turn system off if (ListOfAllSensors.Temperatures.Where(x => x.isRoom).All(x => !x.isHeatingRequired)) { _receiveData.ProcessCommand(CommandNames.REDUCE_TEMP_COMMAND); } //if all room temperatures together has changed more that 3 degrees then send it out to database if (Math.Abs(SumOfTemperatureDeltas) > 4) { TelemetryDataClass.SourceInfo = $"Room temp changed {SumOfTemperatureDeltas:0.0}"; var monitorData = new { DeviceID = "RoomTemperatures", UtcOffset = METHOD.DateTimeTZ().Offset.Hours, DateAndTime = METHOD.DateTimeTZ().DateTime, time = METHOD.DateTimeTZ().ToString("HH:mm"), TelemetryDataClass.SourceInfo, ListOfAllSensors.Temperatures }; await _sendListData.PipeMessage(monitorData, Program.IoTHubModuleClient, TelemetryDataClass.SourceInfo, "output"); SumOfTemperatureDeltas = 0; //resetting to start summing up again } await Task.Delay(TimeSpan.FromMinutes(1)); //check temperatures every minute } }
public async void QueryWiFiProbes() { http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"))); var filename = Methods.GetFilePath(CONSTANT.FILENAME_HOME_DEVICES); try { //open file and -> list of devices from Raspberry if the file exists if (File.Exists(filename)) { var result = await Methods.OpenExistingFile(filename); WiFiDevice.WellKnownDevices = JsonSerializer.Deserialize <List <WiFiDevice> >(result).ToList(); } else { double unixTimestamp = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; //following will happen only if there is no file on Raspberry and the list will be loaded from the environment variables WiFiDevice.WellKnownDevices.ForEach(x => x.StatusUnixTime = unixTimestamp); } } catch (Exception e) { Console.WriteLine($"open file {e}"); } await SendMacAddressToCosmos(WiFiDevice.WellKnownDevices); bool isAnyDeviceChanged = true; var UnknownDevices = new List <WiFiDevice>(); while (true) { double unixTimestamp = METHOD.DateTimeToUnixTimestamp(DateTime.UtcNow); double timeOffset = METHOD.DateTimeTZ().Offset.TotalHours; //if there are some items from PowerApps then proceed if (WiFiDevicesFromPowerApps.Any()) { //Add, Remove or Change WiFiDevices list according to WiFiDevices From PowerApps WiFiDevice.WellKnownDevices = AddRemoveChangeDevices(WiFiDevicesFromPowerApps, WiFiDevice.WellKnownDevices); WiFiDevicesFromPowerApps.Clear(); //send all devices to CosmosDB await SendMacAddressToCosmos(WiFiDevice.WellKnownDevices); } //prepare multimac query //create a list of the MAC Addresses for multimac query List <string> deviceMacs = new List <string>(); WiFiDevice.WellKnownDevices.ForEach(x => deviceMacs.Add(x.MacAddress)); string jsonMacAddresses = JsonSerializer.Serialize(deviceMacs); string urlMultiMac = $"{urlKismet}/devices/multimac/devices.json"; string jsonContentFieldsMac = "json={\"fields\":" + jsonFields + ",\"devices\":" + jsonMacAddresses + "}"; List <WiFiDevice> KismetKnownDevices = await GetDevices(urlMultiMac, jsonContentFieldsMac); //clear devices list. WiFiDevicesToPowerApps.Clear(); //building list of the local devices which are last seen foreach (var knownDevice in WiFiDevice.WellKnownDevices) { foreach (var kismet in KismetKnownDevices) { if (knownDevice.MacAddress == kismet.MacAddress) { knownDevice.LastUnixTime = kismet.LastUnixTime; knownDevice.LastSignal = kismet.LastSignal; knownDevice.SignalType = kismet.SignalType; knownDevice.SSID = kismet.SSID; knownDevice.WiFiName = kismet.ProbedSSID; if (kismet.SignalType.Contains("Wi-Fi")) { knownDevice.AccessPoint = WiFiDevice.WellKnownDevices.Where(x => x.MacAddress == kismet.LastBSSID).Select(x => x.DeviceName).DefaultIfEmpty("No AP").First(); if (string.IsNullOrEmpty(knownDevice.WiFiName) || knownDevice.WiFiName == "0") { knownDevice.WiFiName = WiFiDevice.WellKnownDevices.Where(x => x.MacAddress == kismet.LastBSSID).Select(x => x.SSID).DefaultIfEmpty("No AP").First(); } } break; } } //checking active devices and setting Active/NonActive statuses. Each device can have individual timewindow knownDevice.IsChanged = false; //this is just for debugging, no other reason var durationUntilNotActive = (unixTimestamp - knownDevice.LastUnixTime) / 60; //timestamp in minutes knownDevice.IsPresent = durationUntilNotActive < knownDevice.ActiveDuration; if (knownDevice.IsPresent && !knownDevice.StatusChange) { knownDevice.StatusUnixTime = unixTimestamp; knownDevice.StatusChange = true; isAnyDeviceChanged = true; knownDevice.IsChanged = true; } if (!knownDevice.IsPresent && knownDevice.StatusChange) { knownDevice.StatusUnixTime = knownDevice.LastUnixTime; knownDevice.StatusChange = false; isAnyDeviceChanged = true; knownDevice.IsChanged = true; } //following list WiFiDevicesToPowerApps is used to send minimal data to PowerApps (sending only userdevices) //this list will be sent as a response after PowerApps asks something or refreshing it's data if (knownDevice.DeviceType != WiFiDevice.DEVICE) { WiFiDevicesToPowerApps.Add(new Localdevice() { DeviceOwner = knownDevice.DeviceOwner, DeviceName = knownDevice.DeviceName, DeviceType = knownDevice.DeviceType, IsPresent = knownDevice.IsPresent, StatusFrom = METHOD.UnixTimeStampToDateTime(knownDevice.StatusUnixTime), ActiveDuration = knownDevice.ActiveDuration, MacAddress = knownDevice.MacAddress, SignalType = knownDevice.SignalType, IsChanged = knownDevice.IsChanged }); } //build a list with the names who is expected to track //this list will be sent through Azure Functions to the owners e-mail if (knownDevice.DeviceType == WiFiDevice.MOBILE || knownDevice.DeviceType == WiFiDevice.WATCH || knownDevice.DeviceType == WiFiDevice.CAR) { //to be sure that every person is listed just once if (!WiFiDevicesWhoIsChanged.Any(x => x.DeviceOwner == knownDevice.DeviceOwner) || !WiFiDevicesWhoIsChanged.Any()) { WiFiDevicesWhoIsChanged.Add(new Localdevice() { DeviceOwner = knownDevice.DeviceOwner, DeviceName = knownDevice.DeviceName, IsPresent = knownDevice.IsPresent, StatusFrom = METHOD.UnixTimeStampToDateTime(knownDevice.StatusUnixTime), SignalType = knownDevice.SignalType, IsChanged = knownDevice.IsChanged }); } } } //update the list of the correct statuses, are they home or away foreach (var item in WiFiDevicesWhoIsChanged) { item.IsChanged = false; foreach (var device in WiFiDevicesToPowerApps) { if (item.DeviceOwner == device.DeviceOwner && (device.DeviceType == WiFiDevice.MOBILE || device.DeviceType == WiFiDevice.WATCH || device.DeviceType == WiFiDevice.CAR)) { if (device.IsChanged) { item.IsChanged = device.IsChanged; item.DeviceName = device.DeviceName; item.StatusFrom = device.StatusFrom.AddHours(timeOffset); item.SignalType = device.SignalType; item.IsPresent = device.IsPresent; } //if device is exist and has'nt been changed, then mark it as unchanged and move to next item //if device is not exist (not seen) but has been changed then mark it as unchanged and move to next item = do not notify leaving devices //this is XOR if (device.IsPresent ^ device.IsChanged) { item.IsChanged = false; break; } } } } //save the data locally into Raspberry var jsonString = JsonSerializer.Serialize(WiFiDevice.WellKnownDevices); await Methods.SaveStringToLocalFile(filename, jsonString); //send an e-mail only if someone has arrived at home or left the home if (WiFiDevicesWhoIsChanged.Any(x => x.IsChanged)) { string status = "Look who is at home:\n\n"; WiFiDevicesWhoIsChanged.ForEach(x => status += $"{(x.IsPresent ? x.DeviceOwner + " " + x.DeviceName + " at home from" : x.DeviceOwner + " not seen since")} {x.StatusFrom:HH:mm dd.MM.yyyy} \n "); var x = WiFiDevicesWhoIsChanged.First(x => x.IsChanged); string whoChanged = $"{(x.IsPresent ? x.DeviceOwner + " at home " : x.DeviceOwner + " not seen since")} {x.StatusFrom:HH:mm dd.MM.yyyy}"; _sendListData = new SendDataAzure(); TelemetryDataClass.SourceInfo = $"{whoChanged}"; //send data to CosmosDB var monitorData = new { DeviceID = "HomeController", TelemetryDataClass.SourceInfo, status, DateAndTime = METHOD.DateTimeTZ().DateTime, isHomeSecured = true }; await _sendListData.PipeMessage(monitorData, Program.IoTHubModuleClient, TelemetryDataClass.SourceInfo, "output"); } //if any mobile phone or watch is present then someone is at home IsAnyMobileAtHome = WiFiDevice.WellKnownDevices.Any(x => x.IsPresent && (x.DeviceType == WiFiDevice.MOBILE || x.DeviceType == WiFiDevice.WATCH || x.DeviceType == WiFiDevice.CAR)); //if security mode automatic and home secured then unsecure home if any known mobile device is seen if (IsAnyMobileAtHome && TelemetryDataClass.isHomeSecured && !SomeoneAtHome.IsSecurityManuallyOn) { SomeoneAtHome.SomeoneAtHomeChanged(); } #region Known Device Listing, only for debugging //for local debugging only show the active/non active devices in console window if (isAnyDeviceChanged) { isAnyDeviceChanged = false; var sortedList = WiFiDevice.WellKnownDevices.OrderByDescending(y => y.IsPresent).ThenBy(w => w.AccessPoint).ThenBy(z => z.SignalType).ThenBy(x => x.DeviceName).ToList(); Console.WriteLine(); Console.WriteLine($"All known devices at: {METHOD.DateTimeTZ().DateTime:G}"); Console.WriteLine(); Console.WriteLine($" | From | Status | Device | WiFi network | AccessPoint | SignalType"); Console.WriteLine($" | ------ | ------- | -------- | ----- | ----- | -------- "); foreach (var device in sortedList) { if (device.LastUnixTime > 0 && device.SignalType != "Wi-Fi AP" && device.DeviceOwner != "Unknown" && device.DeviceType != WiFiDevice.DEVICE) //show only my own ever seen LocalUserDevices devices { Console.WriteLine($" {(device.IsChanged ? "1" : " ")} " + $"| {METHOD.UnixTimeStampToDateTime(device.StatusUnixTime).AddHours(timeOffset):T} " + $"| {(device.IsPresent ? "Active " : "Not Act")} " + $"| {device.DeviceName}{"".PadRight(26 - (device.DeviceName.Length > 26 ? 26 : device.DeviceName.Length))}" + $"| {device.WiFiName}{"".PadRight(26 - (!string.IsNullOrEmpty(device.WiFiName) ? (device.WiFiName.Length > 26 ? 26 : device.WiFiName.Length) : 0))}" + $"| {device.AccessPoint}{"".PadRight(26 - (!string.IsNullOrEmpty(device.AccessPoint) ? (device.AccessPoint.Length > 26 ? 26 : device.AccessPoint.Length) : 0))}" + $"| {device.SignalType} "); } } Console.WriteLine(); } #endregion #region Unknown Devices Debugging //prepare last active devices query string urlLastActive = $"{urlKismet}/devices/last-time/{CONSTANT.ACTIVE_DEVICES_IN_LAST}/devices.json"; string jsonContentFields = "json={\"fields\":" + jsonFields + "}"; List <WiFiDevice> KismetActiveDevices = await GetDevices(urlLastActive, jsonContentFields); //removing all known devices from the last seen devices list //known devices are all locally registered devices in the list WiFiDevice.WifiDevices var tempDelList = new List <WiFiDevice>(); var AllActiveDevices = new List <WiFiDevice>(KismetActiveDevices); foreach (var kismet in KismetActiveDevices) { foreach (var knownDevice in WiFiDevice.WellKnownDevices) { if (kismet.MacAddress == knownDevice.MacAddress || kismet.LastSignal < CONSTANT.SIGNAL_TRESHOLD || (kismet.CommonName == kismet.MacAddress && kismet.Manufacture == "Unknown")) { tempDelList.Add(kismet); break; } } } KismetActiveDevices.RemoveAll(i => tempDelList.Contains(i)); //adding new members to the close devices list if (KismetActiveDevices.Any()) { var tempAddList = new List <WiFiDevice>(); bool isNewItem = true; foreach (var kismet in KismetActiveDevices) { foreach (var unknownDevice in UnknownDevices) { if (kismet.MacAddress == unknownDevice.MacAddress) { unknownDevice.Count++; unknownDevice.LastUnixTime = kismet.LastUnixTime; unknownDevice.WiFiName = kismet.ProbedSSID; if (kismet.SignalType.Contains("Wi-Fi")) { //get device AccessPoint and WIFI network names from Kismet (if reported by device) List <WiFiDevice> KismetOneMac = new List <WiFiDevice>(); string urlOneMac = $"{urlKismet}/devices/by-mac/{kismet.MacAddress}/devices.json"; KismetOneMac = await GetDevices(urlOneMac, jsonContentFields); //have to check KismetOneMac list because sometimes it is empty if (KismetOneMac.Any()) { unknownDevice.AccessPoint = AllActiveDevices.Where(x => x.MacAddress == KismetOneMac.First().LastBSSID).Select(x => x.BaseName).DefaultIfEmpty("No AP").First(); if (string.IsNullOrEmpty(kismet.ProbedSSID) || unknownDevice.WiFiName == "0") { unknownDevice.WiFiName = AllActiveDevices.Where(x => x.MacAddress == KismetOneMac.First().LastBSSID).Select(x => x.SSID).DefaultIfEmpty("No AP").First(); } } } isNewItem = false; break; } else { isNewItem = true; } } if (isNewItem) { tempAddList.Add(kismet); } } UnknownDevices.AddRange(tempAddList.ToArray()); UnknownDevices.RemoveAll(x => (unixTimestamp - x.LastUnixTime) / 60 > 120); //remove all entries older that 2 hour //local debugging: show the devices list in console only if some device has been added if (tempAddList.Any() && UnknownDevices.Any()) { var sortedList = UnknownDevices.OrderBy(x => x.SignalType).ThenByDescending(y => y.LastUnixTime).ToList(); Console.WriteLine(); Console.WriteLine($"All unknown devices at: {METHOD.DateTimeTZ().DateTime:G}"); Console.WriteLine(); Console.WriteLine($"dB | First | Last | Mac Address |Count | SignalType | WiFi network | AccessPoint | Common Name | Manufacturer "); Console.WriteLine($" - | ---- | ---- | ----------- | --- | ---------- | --------- | --------- | ----------- | ----------- "); foreach (var device in sortedList) { Console.WriteLine($"{device.LastSignal}{"".PadRight(device.LastSignal < 0 ? 1 : 3)}" + $"| {METHOD.UnixTimeStampToDateTime(device.FirstUnixTime).AddHours(timeOffset):t} " + $"| {METHOD.UnixTimeStampToDateTime(device.LastUnixTime).AddHours(timeOffset):t} " + $"| {device.MacAddress} " + $"| {device.Count}{"".PadRight(device.Count < 10 ? 3 : device.Count < 100 ? 2 : 1)} " + $"| {device.SignalType}{"".PadRight(14 - (!string.IsNullOrEmpty(device.SignalType) ? (device.SignalType.Length > 14 ? 14 : device.SignalType.Length) : 0))}" + $"| {device.WiFiName}{"".PadRight(26 - (!string.IsNullOrEmpty(device.WiFiName) ? (device.WiFiName.Length > 26 ? 26 : device.WiFiName.Length) : 0))}" + $"| {device.AccessPoint}{"".PadRight(26 - (!string.IsNullOrEmpty(device.AccessPoint) ? (device.AccessPoint.Length > 26 ? 26 : device.AccessPoint.Length) : 0))}" + $"| {device.CommonName}{"".PadRight(19 - (!string.IsNullOrEmpty(device.CommonName) ? (device.CommonName.Length > 19 ? 19 : device.CommonName.Length) : 0))}" + $"| {device.Manufacture}"); } Console.WriteLine(); } } #endregion await Task.Delay(TimeSpan.FromSeconds(60)); //check statuses every 10 millisecond } }