private void _mjpg_Error(object sender, MjpegProcessor.ErrorEventArgs e) { Debug.WriteLine(e.Message); // RESET THE STREAM try { MJPGMaps grp = mjpegs[(MjpegDecoder)sender]; ((MjpegDecoder)sender).StopStream(); // restart stream ((MjpegDecoder)sender).ParseStream(new Uri(grp.ip)); /* * ((MjpegDecoder)sender).FrameReady += (o, ev) => * { * Dispatcher.BeginInvoke(new ThreadStart(delegate * { * grp.img.Source = ev.BitmapImage; * })); * }; * * ((MjpegDecoder)sender).Error += _mjpg_Error; */ } catch (Exception ev) { Debug.WriteLine(ev.Message); } }
// Second field is so that the stream connected from a popup is reused private void InitializeModule(Datum m, SshClient client = null) { // TODO: Replace debug writeline with proper error message if (socketMap.ContainsKey(m.ip)) { Debug.WriteLine("ERROR: Key already in dict"); return; } // Establish connection first string stream; try { if (client == null) { client = new SshClient(m.ip, username, password); client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(5); client.Connect(); } stream = "http://" + m.ip + ":8080/?action=stream"; } catch (Exception z) { // TODO: Make this display somewhere failedConn.Add(m); return; } // WPF visual stuff SolidColorBrush darkGray = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF333333")); SolidColorBrush bordGray = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF000000")); SolidColorBrush foreGray = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFEEEEEE")); GroupBox newGroup = new GroupBox { BorderThickness = new Thickness(0.1), Foreground = Brushes.White, FontWeight = FontWeights.Bold }; StackPanel newStack = new StackPanel(); newGroup.Content = newStack; Border border = new Border { BorderBrush = bordGray, BorderThickness = new Thickness(0.1), CornerRadius = new CornerRadius(8), Margin = new Thickness(3), Background = darkGray }; // Grid nonsense Grid minigrid = new Grid(); ColumnDefinition c1 = new ColumnDefinition(); c1.Width = new GridLength(1, GridUnitType.Star); ColumnDefinition c2 = new ColumnDefinition(); c2.Width = GridLength.Auto; minigrid.ColumnDefinitions.Add(c1); minigrid.ColumnDefinitions.Add(c2); TextBlock roomNum = new TextBlock { FontSize = 14, Text = m.num, Margin = new Thickness(5), Background = darkGray, TextAlignment = TextAlignment.Center, Foreground = foreGray, FontWeight = FontWeights.Bold }; // Module options Menu menu = new Menu(); MenuItem options = new MenuItem { Header = " + ", FontSize = 14, Background = foreGray }; MenuItem move = new MenuItem { Header = "Move to" }; MenuItem delete = new MenuItem { Header = "Delete this module" }; MenuItem reposition = new MenuItem { Header = "Move module position" }; MenuItem editRoom = new MenuItem { Header = "Edit Room #" }; MenuItem editName = new MenuItem { Header = "Edit Name" }; menu.Items.Add(options); options.Items.Add(move); options.Items.Add(delete); options.Items.Add(reposition); options.Items.Add(editRoom); options.Items.Add(editName); minigrid.Children.Add(roomNum); minigrid.Children.Add(menu); roomNum.SetValue(Grid.ColumnProperty, 0); menu.SetValue(Grid.ColumnProperty, 1); Image imgtest = new Image { MaxWidth = 288, MinWidth = 288 }; TextBlock personName = new TextBlock { FontSize = 14, Text = m.name, Margin = new Thickness(1), Background = Brushes.Gray, TextAlignment = TextAlignment.Center }; TextBlock status = new TextBlock { FontSize = 14, Text = "Status: Normal", Margin = new Thickness(1), Background = Brushes.ForestGreen, TextAlignment = TextAlignment.Center }; Button testBtn = new Button { Content = "Reset", Background = Brushes.DarkGray, Foreground = Brushes.White, }; Button disableBtn = new Button { Content = "Disable Alarms", Background = Brushes.DarkGray, Foreground = Brushes.White, }; border.Child = minigrid; newStack.Children.Add(border); newStack.Children.Add(imgtest); newStack.Children.Add(personName); newStack.Children.Add(status); newStack.Children.Add(testBtn); newStack.Children.Add(disableBtn); // TODO: CHANGE THIS LATER WHEN DEALING WITH GROUPS // m.group blah blah groupMap[m.group].Children.Add(newGroup); //Default.Children.Add(newGroup); // Create new stream thread var mjpeg = new MjpegDecoder(); mjpeg.ParseStream(new Uri(stream)); // Repeated code is bad, but I couldnt figure out a way to store the lambda as a method or a variable // Essentially sets the image component to update every frame mjpeg.FrameReady += (o, ev) => { Dispatcher.BeginInvoke(new ThreadStart(delegate { imgtest.Source = ev.BitmapImage; })); }; MJPGMaps grp = new MJPGMaps { img = imgtest, ip = stream }; mjpegs.Add(mjpeg, grp); mjpeg.Error += _mjpg_Error; // Ensure there are no duplicate python script instances running (MIGHT BE UNNECESSARY/BAD) client.RunCommand("sudo killall python3"); // REPLACE SCRIPT.PY WITH NAME OF SCRIPT, MAKE SURE IT TAKES A COMMAND ARGUMENT // Runs in background var script = client.CreateCommand("python3 script.py " + myIPString); script.BeginExecute(); // Associate reset button with the following lambda function testBtn.Click += (o, ev) => { // Kill currently running stream if it exists mjpeg.StopStream(); client.RunCommand("sudo killall mjpg_streamer"); // Line below Directly start from mjpg_streamer; unnecessary for now //client.RunCommand("mjpg_streamer -i \"input_raspicam.so - x 1280 - y 720 - fps 30\" -o output_http.so"); // Start script in background var cmd = client.CreateCommand("bash startcam.sh"); cmd.BeginExecute(); mjpeg.ParseStream(new Uri(stream)); // Need to reset stream source as well mjpeg.FrameReady += (o, ev) => { Dispatcher.BeginInvoke(new ThreadStart(delegate { imgtest.Source = ev.BitmapImage; })); }; mjpeg.Error += _mjpg_Error; //client.RunCommand("sudo killall mjpg_streamer"); //client.RunCommand("./startcam.sh"); }; SocketStuff sck = new SocketStuff { txt = status, enabled = true }; Button message = new Button(); message.ToolTip = new ToolTip { Content = "Cannot remove this until alarms are enabled" }; message.Content = DateTime.UtcNow.ToString("MM-dd-yyyy"); message.Content += " " + DateTime.Now.ToString("t"); message.Content += (" ALARMS DISABLED AT: "); // BEHOLD CRINGE message.Content += roomNum.Text; message.Background = Brushes.Blue; // Disables alarm receiving and sends a message to pi disableBtn.Click += (o, ev) => { byte[] msg; lock (sck) { sck.enabled = !sck.enabled; if (sck.enabled) { sck.txt.Text = "Status: Normal"; sck.txt.Background = Brushes.ForestGreen; disableBtn.Content = "Disable Alarms"; try { msg = Encoding.ASCII.GetBytes("ENABLE<EOF>"); sck.testSck.Send(msg); } catch (Exception exp) { Debug.WriteLine("Socket doesn't exist yet..."); } // Add disabled message to log as a reminder if (messagelog.Children.Contains(message)) { messagelog.Children.Remove(message); } } else { sck.txt.Text = "ALARMS DISABLED"; sck.txt.Background = Brushes.Blue; disableBtn.Content = "Enable Alarms"; try { msg = Encoding.ASCII.GetBytes("DISABLE<EOF>"); sck.testSck.Send(msg); } catch (Exception exp) { Debug.WriteLine("Socket doesn't exist yet..."); } messagelog.Children.Add(message); } } }; // Now to add the target IP address to the map //Debug.WriteLine(popup.ipAddr); try { socketMap.Add(m.ip, sck); } catch (Exception e) { // this should never be a problem as the check happens fairly early Debug.WriteLine("Cant add same key twice"); } // Settings button implementation List <MenuItem> temp = new List <MenuItem>(); foreach (string grptmp in module.group) { MenuItem tmp = new MenuItem { Header = grptmp }; move.Items.Add(tmp); temp.Add(tmp); tmp.Click += (o, exv) => { WrapPanel oldwrp = groupMap[m.group]; WrapPanel newwrp = groupMap[grptmp]; oldwrp.Children.Remove(newGroup); newwrp.Children.Add(newGroup); m.group = grptmp; string testy = JsonConvert.SerializeObject(module, Newtonsoft.Json.Formatting.Indented); Debug.WriteLine(testy); File.WriteAllText("config.json", testy); }; } delete.Click += (o, v) => { groupMap[m.group].Children.Remove(newGroup); mjpegs.Remove(mjpeg); }; reposition.Click += (o, v) => { }; StackPanel editRoomPanel = new StackPanel { Orientation = Orientation.Horizontal }; TextBox editRoomText = new TextBox { Width = 100 }; Button editRoomBtn = new Button { Content = "Submit" }; editRoomPanel.Children.Add(editRoomText); editRoomPanel.Children.Add(editRoomBtn); editRoom.Items.Add(editRoomPanel); editRoomBtn.Click += (o, v) => { if (editRoomText.Text == "") { return; } roomNum.Text = editRoomText.Text; }; StackPanel editNamePanel = new StackPanel { Orientation = Orientation.Horizontal }; TextBox editNameText = new TextBox { Width = 100 }; Button editNameBtn = new Button { Content = "Submit" }; editNamePanel.Children.Add(editNameText); editNamePanel.Children.Add(editNameBtn); editName.Items.Add(editNamePanel); editNameBtn.Click += (o, v) => { if (editNameText.Text == "") { return; } personName.Text = editNameText.Text; }; }