wlan_monitor.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 import re
18 import os
19 import getpass
20 import traceback
21 import paramiko
22 from subprocess import Popen, PIPE
23 from packaging import version
24 
25 import rospy
26 from diagnostic_msgs.msg import DiagnosticArray, DiagnosticStatus, KeyValue
27 
28 class IwConfigParser(object):
29  def _parse_info(self, info):
30  values = []
31  # split by either double-space or newline
32  for information in re.split(" |\n",info):
33  # split by either : or =
34  content = re.split(":|=", information)
35  if len(content) == 2:
36  try:
37  content[0] = content[0].decode() #python3
38  content[1] = content[1].decode() #python3
39  except (UnicodeDecodeError, AttributeError):
40  pass
41  values.append(KeyValue(content[0].lstrip(), content[1].rstrip()))
42  return values
43 
45  def __init__(self):
46  IwConfigParser.__init__(self)
47 
48  self.interfaces = []
49  self.stat = DiagnosticStatus()
50  self.stat.level = DiagnosticStatus.OK
51  self.stat.message = "OK"
52  self.stat.values = []
53  try:
54  p = Popen("iw dev | awk '$1==\"Interface\"{print $2}'", stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
55  res = p.wait()
56  (stdout,stderr) = p.communicate()
57  try:
58  stdout = stdout.decode() #python3
59  except (UnicodeDecodeError, AttributeError):
60  pass
61  self.interfaces = sorted(os.linesep.join([s for s in stdout.splitlines() if s]).split('\n'))
62  except Exception as e:
63  message = "IwConfigLocal init exception: %s" % e
64  self.stat.level = DiagnosticStatus.ERROR
65  self.stat.message = message
66  self.stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
67  rospy.logerr(message)
68 
69  def update(self):
70  self.stat.level = DiagnosticStatus.OK
71  self.stat.message = "OK"
72  self.stat.values = []
73  for interface in self.interfaces:
74  self.stat.values.append(KeyValue(key = str(interface), value = "======================="))
75  try:
76  p = Popen(["iwconfig", interface], stdout=PIPE, stdin=PIPE, stderr=PIPE)
77  res = p.wait()
78  (stdout,stderr) = p.communicate()
79  try:
80  stdout = stdout.decode() #python3
81  except (UnicodeDecodeError, AttributeError):
82  pass
83 
84  if res != 0:
85  self.stat.values.append(KeyValue(key = 'iwconfig stderr', value = stderr))
86  self.stat.values.append(KeyValue(key = 'iwconfig stdout', value = stdout))
87  else:
88  self.stat.values += self._parse_info(stdout)
89  except Exception as e:
90  message = "IwConfigLocal update exception: %s" % e
91  self.stat.level = DiagnosticStatus.ERROR
92  self.stat.message = message
93  self.stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
94  rospy.logerr(message)
95 
97  def __init__(self, hostname, user, password):
98  IwConfigParser.__init__(self)
99 
100  self.hostname = str(hostname)
101  self.user = user
102  self.password = password
103  self.ssh = paramiko.SSHClient()
104  self.ssh.load_system_host_keys()
105  self.ssh_key_file = os.getenv("HOME")+'/.ssh/id_rsa.pub'
106  self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())# no known_hosts error
107  self.connect()
108 
109  self.interfaces = []
110  self.stat = DiagnosticStatus()
111  self.stat.level = DiagnosticStatus.OK
112  self.stat.message = "OK"
113  self.stat.values = []
114  try:
115  (stdin, stdout, stderr) = self.ssh.exec_command("iw dev | awk '$1==\"Interface\"{print $2}'")
116  output = ''.join(stdout.readlines())
117  self.interfaces = sorted(os.linesep.join([s for s in output.splitlines() if s]).split('\n'))
118  except Exception as e:
119  message = "IwConfigSSH init exception: %s" % e
120  self.stat.level = DiagnosticStatus.ERROR
121  self.stat.message = message
122  self.stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
123  rospy.logerr(message)
124 
125  def connect(self):
126  if version.parse(paramiko.__version__) < version.parse("2.11.0"):
127  self.ssh.connect(
128  self.hostname,
129  username=self.user,
130  key_filename=self.ssh_key_file,
131  ) # no passwd needed
132  else:
133  self.ssh.connect( # pylint: disable=unexpected-keyword-arg
134  self.hostname,
135  username=self.user,
136  key_filename=self.ssh_key_file,
137  disabled_algorithms={"pubkeys": ["rsa-sha2-256", "rsa-sha2-512"]}
138  ) # no passwd needed
139 
140  def update(self):
141  self.stat.level = DiagnosticStatus.OK
142  self.stat.message = "OK"
143  self.stat.values = []
144 
145  # Reconnect if connection is not active
146  if self.ssh.get_transport() is None or not self.ssh.get_transport().is_active():
147  try:
148  self.connect()
149  except Exception as e:
150  message = "IwConfigSSH connect exception: %s" % e
151  self.stat.level = DiagnosticStatus.ERROR
152  self.stat.message = message
153  self.stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
154  rospy.logerr(message)
155  return
156 
157  for interface in self.interfaces:
158  self.stat.values.append(KeyValue(key = str(interface), value = "======================="))
159  try:
160  (stdin, stdout, stderr) = self.ssh.exec_command("iwconfig %s" % interface)
161  output = ''.join(stdout.readlines())
162  self.stat.values += self._parse_info(output)
163  except Exception as e:
164  message = "IwConfigSSH update exception: %s" % e
165  self.stat.level = DiagnosticStatus.ERROR
166  self.stat.message = message
167  self.stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
168  rospy.logerr(message)
169 
170 class WlanMonitor():
171  def __init__(self):
172  rospy.init_node("wlan_monitor")
173  self.get_params()
174 
175  self._wlan_stat = DiagnosticStatus()
176  self._wlan_stat.name = '%s WLAN Info' % self.diag_hostname
177  self._wlan_stat.hardware_id = self.diag_hostname
178  self._wlan_stat.level = DiagnosticStatus.OK
179  self._wlan_stat.message = 'No Data'
180  self._wlan_stat.values = []
181  self.msg = DiagnosticArray()
182  self.msg.header.stamp = rospy.get_rostime()
183  self.msg.status = [self._wlan_stat]
184 
185  self.diag_pub = rospy.Publisher("/diagnostics", DiagnosticArray, queue_size=1)
186  self.diag_timer = rospy.Timer(rospy.Duration(1.0), self.publish_diagnostics)
187 
188  if self.monitor_local:
190  else:
191  try:
192  self.iwconfig = IwConfigSSH(self.diag_hostname, self.user, self.password)
193  except Exception as e:
194  msg = "Cannot connect to router via ssh. Please check if ssh key of user '{}' is contained in the router configuration or password is provided. Error message: {}".format(getpass.getuser(), e)
195  rospy.logerr(msg)
196  self._wlan_stat.level = DiagnosticStatus.ERROR
197  self._wlan_stat.message = msg
198  self._wlan_stat.values = [ KeyValue(key = 'Exception', value = str(e)), KeyValue(key = 'Traceback', value = str(traceback.format_exc())) ]
199  self.msg.status = [self._wlan_stat]
200  return
201 
202  self.monitor_timer = rospy.Timer(rospy.Duration(1.0), self.update_diagnostics)
203 
204  def update_diagnostics(self, event):
205  self.iwconfig.update()
206 
207  self.msg = DiagnosticArray()
208  self.msg.header.stamp = rospy.get_rostime()
209  self._wlan_stat.level = self.iwconfig.stat.level
210  self._wlan_stat.message = self.iwconfig.stat.message
211  self._wlan_stat.values = self.iwconfig.stat.values
212  self.msg.status = [self._wlan_stat]
213 
214  def publish_diagnostics(self, event):
215  self.diag_pub.publish(self.msg)
216 
217  def get_params(self):
218  self.diag_hostname = rospy.get_param('~diag_hostname', "localhost")
219  self.monitor_local = rospy.get_param("~monitor_local", True)
220  self.user = rospy.get_param('~user', "")
221  self.password = rospy.get_param('~password', "")
222 
223 if __name__ == "__main__":
224  monitor = WlanMonitor()
225  rospy.spin()
wlan_monitor.IwConfigSSH.ssh
ssh
Definition: wlan_monitor.py:103
wlan_monitor.WlanMonitor.__init__
def __init__(self)
Definition: wlan_monitor.py:171
wlan_monitor.IwConfigSSH
Definition: wlan_monitor.py:96
wlan_monitor.WlanMonitor.diag_pub
diag_pub
Definition: wlan_monitor.py:185
wlan_monitor.IwConfigParser._parse_info
def _parse_info(self, info)
Definition: wlan_monitor.py:29
wlan_monitor.WlanMonitor.get_params
def get_params(self)
Definition: wlan_monitor.py:217
wlan_monitor.WlanMonitor.monitor_local
monitor_local
Definition: wlan_monitor.py:219
wlan_monitor.IwConfigParser
Definition: wlan_monitor.py:28
wlan_monitor.WlanMonitor.diag_hostname
diag_hostname
Definition: wlan_monitor.py:218
wlan_monitor.WlanMonitor.publish_diagnostics
def publish_diagnostics(self, event)
Definition: wlan_monitor.py:214
wlan_monitor.WlanMonitor.update_diagnostics
def update_diagnostics(self, event)
Definition: wlan_monitor.py:204
wlan_monitor.WlanMonitor._wlan_stat
_wlan_stat
Definition: wlan_monitor.py:175
wlan_monitor.IwConfigSSH.hostname
hostname
Definition: wlan_monitor.py:100
wlan_monitor.IwConfigSSH.ssh_key_file
ssh_key_file
Definition: wlan_monitor.py:105
wlan_monitor.IwConfigLocal.interfaces
interfaces
Definition: wlan_monitor.py:48
wlan_monitor.WlanMonitor.diag_timer
diag_timer
Definition: wlan_monitor.py:186
wlan_monitor.IwConfigLocal.update
def update(self)
Definition: wlan_monitor.py:69
wlan_monitor.IwConfigSSH.update
def update(self)
Definition: wlan_monitor.py:140
wlan_monitor.WlanMonitor.msg
msg
Definition: wlan_monitor.py:181
wlan_monitor.IwConfigLocal.stat
stat
Definition: wlan_monitor.py:49
wlan_monitor.WlanMonitor
Definition: wlan_monitor.py:170
wlan_monitor.WlanMonitor.password
password
Definition: wlan_monitor.py:221
wlan_monitor.WlanMonitor.user
user
Definition: wlan_monitor.py:220
wlan_monitor.IwConfigSSH.interfaces
interfaces
Definition: wlan_monitor.py:109
wlan_monitor.WlanMonitor.iwconfig
iwconfig
Definition: wlan_monitor.py:189
wlan_monitor.IwConfigSSH.stat
stat
Definition: wlan_monitor.py:110
wlan_monitor.IwConfigSSH.__init__
def __init__(self, hostname, user, password)
Definition: wlan_monitor.py:97
wlan_monitor.IwConfigSSH.connect
def connect(self)
Definition: wlan_monitor.py:125
wlan_monitor.IwConfigLocal.__init__
def __init__(self)
Definition: wlan_monitor.py:45
wlan_monitor.IwConfigLocal
Definition: wlan_monitor.py:44
wlan_monitor.WlanMonitor.monitor_timer
monitor_timer
Definition: wlan_monitor.py:202
wlan_monitor.IwConfigSSH.password
password
Definition: wlan_monitor.py:102
wlan_monitor.IwConfigSSH.user
user
Definition: wlan_monitor.py:101


cob_monitoring
Author(s): Florian Weisshardt , Felix Messmer
autogenerated on Fri Aug 2 2024 09:45:52