void NotificationPattern(object sender, PatternSendEventArgs e) { Boolean found = false; TriggeredEvent ev = new TriggeredEvent(sender as CustomNotification, e.Channel, e.FirstLed, e.LastLed, e.Device, e.Pattern, e.Repeat, e.Duration); lock (e.Device.EventQueue) { foreach (TriggeredEvent pendingEvent in e.Device.EventQueue.ToArray()) { if (pendingEvent.Notification == sender) { found = true; break; } } if (found) { log.InfoFormat("Notification {0} already pending to play. Skipping.", (sender as CustomNotification).Name); } else { e.Device.EventQueue.Enqueue(ev); } } if (!found) { e.Device.Start(); } }
Boolean CanPlayEvent(TriggeredEvent ev) { if (ev.NotificationSnapshot is PatternNotification) { PatternNotification notification = (PatternNotification)ev.NotificationSnapshot; int channel = notification.GetValidChannel(); for (int i = notification.LedFirstIndex; i <= notification.LedLastIndex; i++) { //If there is at least one LED currently in use, event needs to wait if (LedBusy[channel][i]) { return(false); } } } else { for (int i = ev.FirstLed; i <= ev.LastLed; i++) { if (LedBusy[ev.Channel][i]) { return(false); } } } return(true); }
public void SetColor(TriggeredEvent evnt, byte r, byte g, byte b) { if (BrightnessLimit < 100 && BrightnessLimit >= 0) { r = (byte)(BrightnessLimit / 100.0 * r); g = (byte)(BrightnessLimit / 100.0 * g); b = (byte)(BrightnessLimit / 100.0 * b); } lock (this) { for (int i = evnt.FirstLed; i <= evnt.LastLed; i++) { LedFrame[evnt.Channel][i * 3] = g; LedFrame[evnt.Channel][i * 3 + 1] = r; LedFrame[evnt.Channel][i * 3 + 2] = b; OnSendColor((byte)evnt.Channel, (byte)i, r, g, b); } NeedsLedUpdate = true; } if (!Running) { this.Start(); } }
void AssignBusyLeds(TriggeredEvent ev, Boolean busy) { if (ev.NotificationSnapshot is PatternNotification) { PatternNotification notification = (PatternNotification)ev.NotificationSnapshot; int channel = notification.GetValidChannel(); for (int i = notification.LedFirstIndex; i <= notification.LedLastIndex; i++) { LedBusy[channel][i] = busy; } } else { for (int i = ev.FirstLed; i <= ev.LastLed; i++) { LedBusy[ev.Channel][i] = busy; } } }
private void NotificationTriggered(object sender, TriggeredEventArgs e) { log.InfoFormat("Notification [{0}] \"{1}\" triggered. Message: {2}", (sender as CustomNotification).GetTypeName(), (sender as CustomNotification).Name, e.Message); PatternNotification notification = sender as PatternNotification; TriggeredEvent ev = new TriggeredEvent(notification, e.Message); if (e.Message != "") { DataModel.TriggeredEvents.Add(ev); } if (notification.Pattern == null) { log.WarnFormat("({0}) Pattern is not assigned", notification.Name); return; } BlinkStickDeviceSettings settings = DataModel.FindBySerial(notification.BlinkStickSerial); if (settings == null) { log.WarnFormat("({0}) BlinkStick with serial {1} not known", notification.Name, notification.BlinkStickSerial); return; } if (settings.Led == null) { log.WarnFormat("({0}) BlinkStick with serial {1} is not connected", notification.Name, notification.BlinkStickSerial); return; } Boolean found = false; lock (settings.EventQueue) { foreach (TriggeredEvent pendingEvent in settings.EventQueue.ToArray()) { if (pendingEvent.Notification == notification) { found = true; break; } } if (found) { log.InfoFormat("Notification {0} already pending to play. Skipping.", notification.Name); } else { settings.EventQueue.Enqueue(ev); } } if (!found) { settings.Start(); } }
void patternAnimator_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = (BackgroundWorker)sender; try { log.InfoFormat("[{0}] Starting pattern playback", this.Serial); List <TriggeredEvent> eventsPlaying = new List <TriggeredEvent>(); while (!worker.CancellationPending) { TriggeredEvent ev = null; lock (EventQueue) { for (int i = 0; i < EventQueue.Count; i++) { ev = EventQueue.Dequeue(); for (int j = eventsPlaying.Count - 1; j >= 0; j--) { if (ev.Notification == eventsPlaying[j].Notification && (eventsPlaying[j].Repeat < 0 || eventsPlaying[j].Duration > 0)) { log.DebugFormat("Removing infinite playback notifications as there is another pending"); TriggeredEvent evPlaying = eventsPlaying[j]; eventsPlaying.RemoveAt(j); AssignBusyLeds(evPlaying, false); } } if (CanPlayEvent(ev)) { break; } else { EventQueue.Enqueue(ev); ev = null; } } } if (ev != null) { if (ev.NotificationSnapshot is PatternNotification) { ev.EventStarted = DateTime.Now; ev.AnimationStarted = DateTime.Now; PatternNotification notification = ev.NotificationSnapshot as PatternNotification; foreach (Animation animation in notification.Pattern.Animations) { Animation copyAnimation = new Animation(); copyAnimation.Assign(animation); ev.Animations.Add(copyAnimation); } ev.Animations[0].ReferenceColor = GetColor(ev.NotificationSnapshot); AssignBusyLeds(ev, true); eventsPlaying.Add(ev); } else { ev.AnimationStarted = DateTime.Now; ev.EventStarted = DateTime.Now; foreach (Animation animation in ev.Pattern.Animations) { Animation copyAnimation = new Animation(); copyAnimation.Assign(animation); ev.Animations.Add(copyAnimation); } ev.Animations[0].ReferenceColor = GetColor(ev.NotificationSnapshot); AssignBusyLeds(ev, true); eventsPlaying.Add(ev); } } //Prepare next frame of data to send to LEDs for (int ii = eventsPlaying.Count - 1; ii >= 0; ii--) { TriggeredEvent evnt = eventsPlaying[ii]; RgbColor color = evnt.Animations[evnt.AnimationIndex].GetColor(evnt.AnimationStarted.Value, DateTime.Now, evnt.Animations[evnt.AnimationIndex].ReferenceColor); PatternNotification notification = evnt.NotificationSnapshot as PatternNotification; lock (this) { SetColor(evnt, color.R, color.G, color.B); } if (evnt.Animations[evnt.AnimationIndex].AnimationFinished) { evnt.AnimationIndex += 1; if (evnt.Duration > 0 && evnt.EventStarted.Value.AddMilliseconds(evnt.Duration) <= DateTime.Now) { eventsPlaying.RemoveAt(ii); AssignBusyLeds(evnt, false); } else if (evnt.AnimationIndex == evnt.Animations.Count) { evnt.RepeatCount += 1; if (evnt.Duration > 0 || evnt.Repeat < 0 || evnt.RepeatCount < evnt.Repeat) { evnt.AnimationStarted = DateTime.Now; evnt.AnimationIndex = 0; evnt.Animations.ForEach(delegate(Animation a) { a.Reset(); }); } else { eventsPlaying.RemoveAt(ii); AssignBusyLeds(evnt, false); } } else { evnt.Animations[evnt.AnimationIndex].ReferenceColor = GetColor(evnt.NotificationSnapshot); evnt.AnimationStarted = DateTime.Now; } } } if (Led != null && NeedsLedUpdate) { lock (this) { NeedsLedUpdate = false; } int retryCount = 5; if (Led.BlinkStickDevice == BlinkStickDeviceEnum.BlinkStick || Led.BlinkStickDevice == BlinkStickDeviceEnum.BlinkStickPro && Led.Mode < 2) { while (retryCount > 0) //Retry loop { try { Led.SetColor(LedFrame[0][1], LedFrame[0][0], LedFrame[0][2]); retryCount = 0; } catch (Exception ex) { retryCount--; log.ErrorFormat("Failed to set color: {0}", ex); if (retryCount > 0) { Thread.Sleep(20); log.InfoFormat("Retry set color #{0}", 5 - retryCount); } else { log.Warn("Failed to set color 5 times, giving up..."); } } } } else { byte[] frame = new byte[this.LedsR * 3]; Array.Copy(LedFrame[0], 0, frame, 0, frame.Length); while (retryCount > 0) //Retry loop { try { Led.SetColors(0, frame); retryCount = 0; } catch (Exception ex) { retryCount--; log.ErrorFormat("Failed to set color: {0}", ex); if (retryCount > 0) { Thread.Sleep(20); log.InfoFormat("Retry set color #{0}", 5 - retryCount); } else { log.Warn("Failed to set color 5 times, giving up..."); } } } int sleep = Math.Max(2, (int)(this.LedsR * 3 * 8f / 400f * 1.2)); //number of LEDs times 3 color elements times 8 bytes divided by speed Thread.Sleep(sleep); if (Led != null && Led.BlinkStickDevice == BlinkStickDeviceEnum.BlinkStickPro) { frame = new byte[this.LedsG * 3]; Array.Copy(LedFrame[1], 0, frame, 0, frame.Length); while (retryCount > 0) //Retry loop { try { Led.SetColors(1, frame); retryCount = 0; } catch (Exception ex) { retryCount--; log.ErrorFormat("Failed to set color: {0}", ex); if (retryCount > 0) { Thread.Sleep(20); log.InfoFormat("Retry set color #{0}", 5 - retryCount); } else { log.Warn("Failed to set color 5 times, giving up..."); } } } sleep = Math.Max(2, (int)(this.LedsG * 3 * 8f / 400f * 1.2)); Thread.Sleep(sleep); frame = new byte[this.LedsB * 3]; Array.Copy(LedFrame[2], 0, frame, 0, frame.Length); while (retryCount > 0) //Retry loop { try { Led.SetColors(2, frame); retryCount = 0; } catch (Exception ex) { retryCount--; log.ErrorFormat("Failed to set color: {0}", ex); if (retryCount > 0) { Thread.Sleep(20); log.InfoFormat("Retry set color #{0}", 5 - retryCount); } else { log.Warn("Failed to set color 5 times, giving up..."); } } } sleep = Math.Max(2, (int)(this.LedsB * 3 * 8f / 400f * 1.2)); Thread.Sleep(sleep); } } } else { Thread.Sleep(1); } } } catch (Exception ex) { log.ErrorFormat("Pattern playback crash {0}", ex); } log.InfoFormat("[{0}] Pattern playback stopped", this.Serial); Running = false; }