force-ip-dialog.cc
Go to the documentation of this file.
1 /*
2 * Roboception GmbH
3 * Munich, Germany
4 * www.roboception.com
5 *
6 * Copyright (c) 2017 Roboception GmbH
7 * All rights reserved
8 *
9 * Author: Raphael Schaller
10 */
11 #include "rcdiscover/force_ip.h"
12 
13 #include "force-ip-dialog.h"
14 
15 #include "event-ids.h"
16 
17 #include <sstream>
18 
19 #include <wx/stattext.h>
20 #include <wx/sizer.h>
21 #include <wx/panel.h>
22 #include <wx/textctrl.h>
23 #include <wx/button.h>
24 #include <wx/cshelp.h>
25 #include <wx/msgdlg.h>
26 
27 ForceIpDialog::ForceIpDialog(wxHtmlHelpController *help_ctrl,
28  wxWindow *parent, wxWindowID id,
29  const wxPoint &pos,
30  long style,
31  const wxString &name) :
32  SensorCommandDialog(help_ctrl, parent, id, "Set temporary IP address", 3,
33  pos, style, name)
34 {
35  auto *const panel = getPanel();
36  auto *const vbox = getVerticalBox();
37  auto *const grid = getGrid();
38 
39  auto *ip_text = new wxStaticText(panel, wxID_ANY, "IP address");
40  grid->Add(ip_text);
41  auto *ip_box = new wxBoxSizer(wxHORIZONTAL);
43  grid->Add(ip_box);
44 
45  auto *subnet_text = new wxStaticText(panel, wxID_ANY, "Subnet mask");
46  grid->Add(subnet_text);
47  auto *subnet_box = new wxBoxSizer(wxHORIZONTAL);
49  grid->Add(subnet_box);
50 
51  auto *gateway_text = new wxStaticText(panel, wxID_ANY, "Default gateway");
52  grid->Add(gateway_text);
53  auto *gateway_box = new wxBoxSizer(wxHORIZONTAL);
55  grid->Add(gateway_box);
56 
57  auto *button_box = new wxBoxSizer(wxHORIZONTAL);
58  auto *set_ip_button = new wxButton(panel, ID_Force_IP,
59  "Set temporary IP address");
60  button_box->Add(set_ip_button, 1);
61  auto *clear_button = new wxButton(panel, ID_Clear_IP_Form,
62  "Clear form");
63  button_box->Add(clear_button, 0);
64 
65  button_box->AddSpacer(20);
66 
67  int w, h;
68  set_ip_button->GetSize(&w, &h);
69  auto *help_button = new wxContextHelpButton(panel, ID_Help_Force_IP,
70  wxDefaultPosition, wxSize(h,h));
71  button_box->Add(help_button, 0);
72 
73  vbox->Add(button_box, 0, wxLEFT | wxRIGHT | wxBOTTOM, 15);
74  vbox->Fit(this);
75 
76  Connect(ID_Force_IP,
77  wxEVT_BUTTON,
78  wxCommandEventHandler(ForceIpDialog::onForceIpButton));
79  Connect(ID_Clear_IP_Form,
80  wxEVT_BUTTON,
81  wxCommandEventHandler(ForceIpDialog::onClearButton));
82  Connect(ID_Help_Force_IP,
83  wxEVT_BUTTON,
84  wxCommandEventHandler(ForceIpDialog::onHelpButton));
85 
86  Centre();
87 }
88 
89 void ForceIpDialog::onClearButton(wxCommandEvent &)
90 {
91  for (auto &x : ip_)
92  {
93  x->ChangeValue("");
94  }
95  for (auto &x : subnet_)
96  {
97  x->ChangeValue("");
98  }
99  for (auto &x : gateway_)
100  {
101  x->ChangeValue("");
102  }
103 
104  for (auto &x : changed_by_user_)
105  {
106  x.second = false;
107  }
108 }
109 
110 void ForceIpDialog::addIpToBoxSizer(wxBoxSizer *sizer,
111  std::array<wxTextCtrl *, 4> &ip,
112  int id)
113 {
114  bool first = true;
115  for (auto &i : ip)
116  {
117  if (!first)
118  {
119  sizer->Add(new wxStaticText(getPanel(), ID_IP_Textbox, "."));
120  }
121  i = new wxTextCtrl(getPanel(), id, wxEmptyString, wxDefaultPosition,
122  wxSize(45, -1));
123  changed_by_user_.emplace(i, false);
124  Connect(id, wxEVT_TEXT, wxCommandEventHandler(ForceIpDialog::onIpChanged));
125  sizer->Add(i, 1);
126  first = false;
127  }
128 }
129 
130 uint32_t ForceIpDialog::parseIp(const std::array<wxTextCtrl *, 4> &ip)
131 {
132  std::uint32_t result{};
133 
134  for (std::uint8_t i = 0; i < 4; ++i)
135  {
136  const auto s = ip[i]->GetValue().ToStdString();
137 
138  try
139  {
140  const auto v = std::stoul(s, nullptr, 10);
141  if (v > 255)
142  {
143  throw std::invalid_argument("");
144  }
145  result |= (static_cast<std::uint32_t>(v) << ((4 - 1 - i) * 8));
146  }
147  catch(const std::invalid_argument &)
148  {
149  throw std::runtime_error(
150  std::string("Each ip address, subnet and gateway segment must ") +
151  "contain a decimal value ranging from 0 to 255.");
152  }
153  }
154 
155  return result;
156 }
157 
159  const std::string &v)
160 {
161  if (ctrl->HasFocus())
162  {
163  return;
164  }
165 
166  if (ctrl->GetValue().empty())
167  {
168  changed_by_user_[ctrl] = false;
169  }
170 
171  if (!changed_by_user_[ctrl])
172  {
173  ctrl->ChangeValue(v);
174  ctrl->SetBackgroundColour(wxColour(240, 240, 240));
175  }
176 }
177 
178 void ForceIpDialog::onIpChanged(wxCommandEvent &event)
179 {
180  auto *const text_ctrl =
181  dynamic_cast<wxTextCtrl *>(event.GetEventObject());
182  if (text_ctrl != nullptr)
183  {
184  if (!text_ctrl->GetValue().empty())
185  {
186  changed_by_user_[text_ctrl] = true;
187  text_ctrl->SetBackgroundColour(wxColor(255, 255, 255));
188  }
189  }
190 
191  if (event.GetId() == ID_ForceIp_IpChanged ||
192  event.GetId() == ID_ForceIp_SubnetChanged)
193  {
194  try
195  {
196  const auto ip = parseIp(ip_);
197 
198  // 10.0.0.0/8 addresses
199  if (static_cast<std::uint8_t>(ip >> 24) == 10)
200  {
205  }
206 
207  // 172.16.0.0/12 addresses
208  if (static_cast<std::uint8_t>(ip >> 24) == 172 &&
209  (static_cast<std::uint8_t>(ip >> 16) & 16) != 0)
210  {
215  }
216 
217  // 192.168.0.0/16 addresses
218  if (static_cast<std::uint8_t>(ip >> 24) == 192
219  && static_cast<std::uint8_t>(ip >> 16) == 168)
220  {
225  }
226 
227  // 169.254.0.0/16 addresses
228  if (static_cast<std::uint8_t>(ip >> 24) == 169
229  && static_cast<std::uint8_t>(ip >> 16) == 254)
230  {
235  }
236 
237  const auto subnet = parseIp(subnet_);
238 
239  const auto predicted_gateway = (ip & subnet) | 0x1;
240 
242  std::to_string(static_cast<std::uint8_t>(predicted_gateway >> 24)));
244  std::to_string(static_cast<std::uint8_t>(predicted_gateway >> 16)));
246  std::to_string(static_cast<std::uint8_t>(predicted_gateway >> 8)));
248  std::to_string(static_cast<std::uint8_t>(predicted_gateway >> 0)));
249  }
250  catch(const std::runtime_error &)
251  { }
252  }
253 }
254 
255 void ForceIpDialog::onForceIpButton(wxCommandEvent &)
256 {
257  try
258  {
259  std::array<uint8_t, 6> mac = getMac();
260  std::string mac_string = getMacString();
261 
262  const auto ip = parseIp(ip_);
263  const auto subnet = parseIp(subnet_);
264  const auto gateway = parseIp(gateway_);
265 
266  if ((ip & subnet) != (gateway & subnet))
267  {
268  std::ostringstream oss;
269  oss << "IP address and gateway appear to be in different subnets. " <<
270  "Are you sure to proceed?";
271  const int answer = wxMessageBox(oss.str(), "", wxYES_NO);
272  if (answer == wxNO)
273  {
274  return;
275  }
276  }
277 
278  rcdiscover::ForceIP force_ip;
279 
280  std::ostringstream oss;
281  oss << "Are you sure to set the IP address of the device with MAC-address "
282  << mac_string << "?";
283  const int answer = wxMessageBox(oss.str(), "", wxYES_NO);
284 
285  if (answer == wxYES)
286  {
287  std::uint64_t m = 0;
288  m |= static_cast<std::uint64_t>(mac[0]) << 40;
289  m |= static_cast<std::uint64_t>(mac[1]) << 32;
290  m |= static_cast<std::uint64_t>(mac[2]) << 24;
291  m |= static_cast<std::uint64_t>(mac[3]) << 16;
292  m |= static_cast<std::uint64_t>(mac[4]) << 8;
293  m |= static_cast<std::uint64_t>(mac[5]) << 0;
294  force_ip.sendCommand(m, ip, subnet, gateway);
295  }
296 
297  Hide();
298  }
299  catch(const std::runtime_error &ex)
300  {
301  wxMessageBox(ex.what(), "Error", wxOK | wxICON_ERROR);
302  }
303 }
304 
305 void ForceIpDialog::onHelpButton(wxCommandEvent &)
306 {
307  displayHelp("forceip");
308 }
309 
310 BEGIN_EVENT_TABLE(ForceIpDialog, SensorCommandDialog)
311 END_EVENT_TABLE()
void sendCommand(std::uint64_t mac, std::uint32_t ip, std::uint32_t subnet, std::uint32_t gateway)
Send FORCEIP_CMD.
Definition: force_ip.cc:29
std::string getMacString() const
void onIpChanged(wxCommandEvent &event)
std::array< wxTextCtrl *, 4 > ip_
Class for sending GigE Vision FORCEIP_CMD to camera.
Definition: force_ip.h:26
ForceIpDialog()=default
Dialog for sending FORCEIP_CMD to camera.
std::array< wxTextCtrl *, 4 > gateway_
std::map< const wxTextCtrl *, bool > changed_by_user_
wxFlexGridSizer * getGrid()
void onClearButton(wxCommandEvent &event)
Base class for dialogs for sending commands to a camera.
std::array< wxTextCtrl *, 4 > subnet_
void displayHelp(const std::string &section)
static std::uint32_t parseIp(const std::array< wxTextCtrl *, 4 > &ip)
void onForceIpButton(wxCommandEvent &event)
void onHelpButton(wxCommandEvent &event)
std::array< uint8_t, 6 > getMac() const
void addIpToBoxSizer(wxBoxSizer *sizer, std::array< wxTextCtrl *, 4 > &ip, int id)
void changeTextCtrlIfNotChangedByUser(wxTextCtrl *ctrl, const std::string &v)


rcdiscover
Author(s): Heiko Hirschmueller , Raphael Schaller
autogenerated on Sun Apr 18 2021 02:16:32