private void ScheduleLights() { Debug.Print("Scheduling lights: " + m_services.Now.ToString(m_config.DATETIME_FORMAT)); bool isDstToday = m_config.IsDstInEffect(m_services.Now); if (isDstToday && !m_isDst) { // Spring a head m_services.SetLocalTime(m_services.Now + new TimeSpan(1, 0, 0)); Debug.Print("DST starting. Time now: " + m_services.Now.ToString(m_config.DATETIME_FORMAT)); m_isDst = isDstToday; } else if (m_isDst && !isDstToday) { // Fall back m_services.SetLocalTime(m_services.Now - new TimeSpan(1, 0, 0)); Debug.Print("DST over. Time now: " + m_services.Now.ToString(m_config.DATETIME_FORMAT)); m_isDst = isDstToday; } lock (m_lightTimesLock) { m_lightTimes = new LightTimes(m_services.Now, m_config); } // Get an order list of events for the day ArrayList les = LightEventsForDate(m_lightTimes); // Iterate over the list looking for previous event and next event based on current time int prevIndex = -1; for (int i = 0; i < les.Count; i++) { LightEvent le = (LightEvent)les[i]; if (le.DT < m_services.Now) prevIndex = i; else break; } // Turn the light on if the previous event was an on event if (prevIndex > -1) { LightEvent prev = (LightEvent)les[prevIndex]; if (prev.Type == LightEventType.Scheduled_On || prev.Type == LightEventType.Sunset_On) { Debug.Print("Turning light ON due to missed event"); m_relay.TurnOn(); } } // Iterate over the remaining events adding each to the event queue if (prevIndex + 1 < les.Count) { for (int i = prevIndex + 1; i < les.Count; i++) { LightEvent le = (LightEvent)les[i]; Debug.Print("Enqueing LE: " + le.ToString(m_config.DATETIME_FORMAT)); m_events.Enqueue(le); } } // Schedule the event to schedule tomorrows events LightEvent scheduleEvent = new LightEvent(m_services.Now.Date + new TimeSpan(1, 0, 0, 0), LightEventType.Tomorrow); Debug.Print("Enqueing LE: " + scheduleEvent.ToString(m_config.DATETIME_FORMAT)); m_events.Enqueue(scheduleEvent); }
/* * [ ] is period where the light is on * * |012345678901234567890123|012345678901234567890123|012345678901234567890123| * |------------------------|------------------------|------------------------| * | ] [ ] [ | ] [ ] [ | ] [ ] [ | */ /* Example of shifting sunrise and sunset in polar regions |123456789012123456789012| |------------------------| |012345678901234567890123| | ] [ | | ] [ ][ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [] [| |[] | | | | | | | |[] | | ] [] [| | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ] [ | | ] [ ][ | | ] [ | */ // Return an order list of light events for the specified day. private ArrayList LightEventsForDate(LightTimes lt) { ArrayList les = new ArrayList(); if (lt.LightsOffPM > lt.LightsOnAM) { // Scheduled lights off late night if (lt.LightsOnAM < lt.LightsOffAM) { les.Add(new LightEvent(lt.LightsOnAM, LightEventType.Scheduled_On)); } if (lt.Sunrise < lt.Sunset) { les.Add(new LightEvent(lt.LightsOffAM, LightEventType.Sunrise_Off)); les.Add(new LightEvent(lt.LightsOnPM, LightEventType.Sunset_On)); } if (lt.LightsOffPM > lt.LightsOnPM) { les.Add(new LightEvent(lt.LightsOffPM, LightEventType.Scheduled_Off)); } } else { // Scheduled lights off early morning if (lt.LightsOffPM < lt.LightsOffAM) { les.Add(new LightEvent(lt.LightsOffPM, LightEventType.Scheduled_Off)); } if (lt.LightsOnAM < lt.LightsOffAM) { les.Add(new LightEvent(lt.LightsOnAM, LightEventType.Scheduled_On)); } if (lt.Sunrise < lt.Sunset) { les.Add(new LightEvent(lt.LightsOffAM, LightEventType.Sunrise_Off)); les.Add(new LightEvent(lt.LightsOnPM, LightEventType.Sunset_On)); } } return les; }