/// <summary> /// Takes in a BlockingCollection and removes data. Sends data to be assessed elsewhere /// </summary> /// <param name="source">Blocking collection used to hold data for producer consumer pattern</param> public void ReceiveGreenhouseData(BlockingCollection <byte[]> source) { // Create a container for the TLH and moisture packets so we can deserialize them easily TLHPacketContainer tlhContainer = new TLHPacketContainer(); MoisturePacketContainer moistureContainer = new MoisturePacketContainer(); // Take the bytes out of the queue and turn them back into a string source.TryTake(out _data); string json = Encoding.ASCII.GetString(_data); // Take the string to a JObject and deserialize according to the appropriate Type value JObject received = JObject.Parse(json); Console.WriteLine(received.ToString()); switch (received["Type"].Value <int>()) { case 0: tlhContainer = JsonConvert.DeserializeObject <TLHPacketContainer>(json); _tlhInformation = tlhContainer.Packets; break; case 1: moistureContainer = JsonConvert.DeserializeObject <MoisturePacketContainer>(json); _moistureInformation = moistureContainer.Packets; break; case 2: _limits = JsonConvert.DeserializeObject <LimitPacket>(json); break; case 3: _manual = JsonConvert.DeserializeObject <ManualPacket>(json); break; } // If we have all the TLH information, moisture information, limit and manual information we need... if (_tlhInformation != null && _moistureInformation != null && _limits != null && _manual != null) { Console.WriteLine("Sending to analyzers"); // Put everything into temporary variables and clear their values afterwards TLHPacket[] tlhToSend = new TLHPacket[_tlhInformation.Count]; _tlhInformation.CopyTo(tlhToSend); _tlhInformation.Clear(); MoisturePacket[] moistureToSend = new MoisturePacket[_moistureInformation.Count]; _moistureInformation.CopyTo(moistureToSend); _moistureInformation.Clear(); ManualPacket tempManual = _manual; _manual = null; LimitPacket tempLimits = _limits; _limits = null; // Send the temporary variables off to be analyzed DataAnalyzer data = new DataAnalyzer(); data.ExecuteActions(tlhToSend, moistureToSend, tempManual, tempLimits); } }
/// <summary> /// Execute the actions required for proper greenhouse functioning, based on the input data /// </summary> /// <param name="temperature">Array of temperature, lighting, and humidity information packets</param> /// <param name="moisture">Array of moisture information packets</param> /// <param name="manual">Packet containing any manual commands we may have received</param> /// <param name="limits">Packet containng the greenhouse automation limits</param> public void ExecuteActions(TLHPacket[] temperature, MoisturePacket[] moisture, ManualPacket manual, LimitPacket limits) { ArduinoControlSender.Instance.CheckArduinoStatus(); // Process limit changes LimitsAnalyzer limitAnalyzer = new LimitsAnalyzer(); limitAnalyzer.ChangeGreenhouseLimits(limits); // Process manual controls ArduinoControlSender.Instance.CheckArduinoStatus(); ManualPacketAnalyzer manualAnalyzer = new ManualPacketAnalyzer(); manualAnalyzer.SetManualValues(manual); // Process sensor data ArduinoControlSender.Instance.CheckArduinoStatus(); AnalyzeData(temperature, moisture); }
/// <summary> /// Changes the greenhouse limits based on the limit packet data /// </summary> /// <param name="limits"></param> public void ChangeGreenhouseLimits(LimitPacket limits) { if (StateMachineContainer.Instance.Temperature.HighLimit != limits.TempHi) { StateMachineContainer.Instance.Temperature.HighLimit = limits.TempHi; } if (StateMachineContainer.Instance.Temperature.LowLimit != limits.TempLo) { StateMachineContainer.Instance.Temperature.LowLimit = limits.TempLo; } if (StateMachineContainer.Instance.Shading.HighLimit != limits.ShadeLim) { StateMachineContainer.Instance.Shading.HighLimit = limits.ShadeLim; } foreach (ZoneSchedule schedule in limits.Light) { switch (schedule.zone) { case 1: StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].Begin = schedule.start; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].End = schedule.end; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].OverrideThreshold = schedule.threshold; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].ScheduleType = schedule.type; break; case 2: StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].Begin = schedule.start; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].End = schedule.end; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].OverrideThreshold = schedule.threshold; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].ScheduleType = schedule.type; break; case 3: StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].Begin = schedule.start; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].End = schedule.end; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].OverrideThreshold = schedule.threshold; StateMachineContainer.Instance.LightStateMachines[schedule.zone - 1].ScheduleType = schedule.type; break; } } foreach (ZoneSchedule schedule in limits.Water) { StateMachineContainer.Instance.WateringStateMachines[schedule.zone - 1].Begin = schedule.start; StateMachineContainer.Instance.WateringStateMachines[schedule.zone - 1].End = schedule.end; StateMachineContainer.Instance.WateringStateMachines[schedule.zone - 1].OverrideThreshold = schedule.threshold; StateMachineContainer.Instance.WateringStateMachines[schedule.zone - 1].ScheduleType = schedule.type; } Console.WriteLine($"Temperature High Limit: {StateMachineContainer.Instance.Temperature.HighLimit}"); Console.WriteLine($"Temperature Low Limit: {StateMachineContainer.Instance.Temperature.LowLimit}"); Console.WriteLine($"Shading Limit: {StateMachineContainer.Instance.Shading.HighLimit}"); for (int i = 0; i < StateMachineContainer.Instance.LightStateMachines.Count; i++) { Console.WriteLine($"LZone {StateMachineContainer.Instance.LightStateMachines[i].Zone}" + $"Start: {StateMachineContainer.Instance.LightStateMachines[i].Begin}" + $"\nLZone {StateMachineContainer.Instance.LightStateMachines[i].Zone}" + $"End: {StateMachineContainer.Instance.LightStateMachines[i].End}" ); } for (int i = 0; i < StateMachineContainer.Instance.WateringStateMachines.Count; i++) { Console.WriteLine($"WZone {StateMachineContainer.Instance.WateringStateMachines[i].Zone}" + $"Start: {StateMachineContainer.Instance.WateringStateMachines[i].Begin}" + $"\nWZone {StateMachineContainer.Instance.WateringStateMachines[i].Zone}" + $"End: {StateMachineContainer.Instance.WateringStateMachines[i].End}"); } }
/// <summary> /// Takes in a BlockingCollection and removes data. Sends data to be assessed elsewhere /// </summary> /// <param name="source">Blocking collection used to hold data for producer consumer pattern</param> public void ReceiveGreenhouseData(BlockingCollection <byte[]> source) { // TODO: Fix this up so that it doesn't mess with things already happening within state machines, etc. if (source.Count != 0) { try { source.TryTake(out _data); var data = JObject.Parse(Encoding.ASCII.GetString(_data)); Console.WriteLine(data.ToString()); if (data["Type"].Value <int>() == 0) { _currentTime = data["TimeOfSend"].Value <DateTime>(); var deserializedData = JsonConvert.DeserializeObject <TLHPacket>(Encoding.ASCII.GetString(_data)); // Check for repeat zones, and if we have any, throw out the old zone data if (_tlhInformation.Where(p => p.ID == deserializedData.ID) != null) { _tlhInformation.RemoveAll(p => p.ID == deserializedData.ID); } _tlhInformation.Add(deserializedData); } // if it's a moisture packet else if (data["Type"].Value <int>() == 1) { var deserializedData = JsonConvert.DeserializeObject <MoisturePacket>(Encoding.ASCII.GetString(_data)); // Check for repeat zones, and if we have any, throw out the old zone data if (_moistureInformation.Where(p => p.ID == deserializedData.ID) != null) { _moistureInformation.RemoveAll(p => p.ID == deserializedData.ID); } _moistureInformation.Add(deserializedData); } else if (data["Type"].Value <int>() == 2) { var deserializedData = JsonConvert.DeserializeObject <LimitPacket>(Encoding.ASCII.GetString(_data)); _limits = deserializedData; } else if (data["Type"].Value <int>() == 3) { var deserializedData = JsonConvert.DeserializeObject <ManualPacket>(Encoding.ASCII.GetString(_data)); _manual = deserializedData; } } catch (Exception ex) { Console.WriteLine(ex); } if (_tlhInformation.Count == 5 && _moistureInformation.Count == 6 && _limits != null && _manual != null) { TLHPacket[] tlhToSend = new TLHPacket[_tlhInformation.Count]; _tlhInformation.CopyTo(tlhToSend); _tlhInformation.Clear(); MoisturePacket[] moistureToSend = new MoisturePacket[_moistureInformation.Count]; _moistureInformation.CopyTo(moistureToSend); _moistureInformation.Clear(); ManualPacket tempManual = _manual; _manual = null; LimitPacket tempLimits = _limits; _limits = null; DataAnalyzer data = new DataAnalyzer(); Task.Run(() => data.ExecuteActions(tlhToSend, moistureToSend, tempManual, tempLimits)); } } }
/// <summary> /// Changes the greenhouse limits based on the limit packet data /// </summary> /// <param name="limits"></param> public void ChangeGreenhouseLimits(LimitPacket limits) { if (StateMachineContainer.Instance.Temperature.HighLimit != limits.TempHi) { StateMachineContainer.Instance.Temperature.HighLimit = limits.TempHi; } if (StateMachineContainer.Instance.Temperature.LowLimit != limits.TempLo) { StateMachineContainer.Instance.Temperature.LowLimit = limits.TempLo; } if (StateMachineContainer.Instance.Shading.HighLimit != limits.ShadeLim) { StateMachineContainer.Instance.Shading.HighLimit = limits.ShadeLim; } foreach (KeyValuePair <int, DateTime> kvp in limits.LightStarts) { switch (kvp.Key) { case 1: StateMachineContainer.Instance.LightStateMachines[0].Begin = kvp.Value; break; case 3: StateMachineContainer.Instance.LightStateMachines[1].Begin = kvp.Value; break; case 5: StateMachineContainer.Instance.LightStateMachines[1].Begin = kvp.Value; break; default: break; } } foreach (KeyValuePair <int, DateTime> kvp in limits.LightEnds) { switch (kvp.Key) { case 1: StateMachineContainer.Instance.LightStateMachines[0].End = kvp.Value; break; case 3: StateMachineContainer.Instance.LightStateMachines[1].End = kvp.Value; break; case 5: StateMachineContainer.Instance.LightStateMachines[2].End = kvp.Value; break; default: break; } } foreach (KeyValuePair <int, DateTime> kvp in limits.WaterStarts) { switch (kvp.Key) { case 1: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; case 2: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; case 3: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; case 4: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; case 5: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; case 6: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].Begin = kvp.Value; break; default: break; } } foreach (KeyValuePair <int, DateTime> kvp in limits.WaterEnds) { switch (kvp.Key) { case 1: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; case 2: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; case 3: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; case 4: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; case 5: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; case 6: StateMachineContainer.Instance.WateringStateMachines[kvp.Key - 1].End = kvp.Value; break; default: break; } } Console.WriteLine($"Temperature High Limit: {StateMachineContainer.Instance.Temperature.HighLimit}"); Console.WriteLine($"Temperature Low Limit: {StateMachineContainer.Instance.Temperature.LowLimit}"); Console.WriteLine($"Shading Limit: {StateMachineContainer.Instance.Shading.HighLimit}"); for (int i = 0; i < StateMachineContainer.Instance.LightStateMachines.Count; i++) { Console.WriteLine($"LZone {StateMachineContainer.Instance.LightStateMachines[i].Zone}" + $"Start: {StateMachineContainer.Instance.LightStateMachines[i].Begin}" + $"\nLZone {StateMachineContainer.Instance.LightStateMachines[i].Zone}" + $"End: {StateMachineContainer.Instance.LightStateMachines[i].End}" ); } for (int i = 0; i < StateMachineContainer.Instance.WateringStateMachines.Count; i++) { Console.WriteLine($"WZone {StateMachineContainer.Instance.WateringStateMachines[i].Zone}" + $"Start: {StateMachineContainer.Instance.WateringStateMachines[i].Begin}" + $"\nWZone {StateMachineContainer.Instance.WateringStateMachines[i].Zone}" + $"End: {StateMachineContainer.Instance.WateringStateMachines[i].End}"); } }