Source code for sensors.GUIclasses.info

from bokeh.models import Panel
from bokeh.layouts import column
from bokeh.models import Div

from os.path import dirname, join
import os
import sys
import subprocess
import socket
import pyudev


[docs]class InfoTab: """Class to create a Bokeh tab that displays information about the system and the peripherical devices. :param init_dev: picamera and audio device object initialized in :mod:`sensors.app_hooks` \ with :class:`sensors.Utilities.initdevices.InitDevices` :type init_dev: object """ def __init__(self, config): self.config = config self.camera = config.camera self.audio_devices = config.audio_devices self.system_info = Div(text=self.get_system_info(), render_as_text=False, width=1000) self.camera_info = Div(text=self.get_camera_info(), render_as_text=False, width=1000) self.audio_info = Div(text=self.get_audio_info(), render_as_text=False, width=1000) self.sensors_info = Div(text=self.get_sensors_info(), render_as_text=False, width=1000) # self.storage_info = Div(text=self.get_storage_info(), # render_as_text=False, width=1000) # Information tab header loaded from html template filename = join(dirname(__file__), "info_template.html") desc = Div(text=open(filename).read(), render_as_text=False, width=800) layout = column(desc, self.system_info, self.camera_info, self.audio_info, self.sensors_info) # Make a tab with the layout self._tab = Panel(child=layout, title='Information') @property def tab(self): """Creates and arranges the elements of the corresponding Bokeh tab. :return: Bokeh panel for visualization of general information on system and devices :rtype: Bokeh object """ return self._tab
[docs] def get_system_info(self): """Creates general system information. :return: html code for corresponding information :rtype: string """ info = '<h2>System and User Information</h2>\n' info += '<table style="width:100%; margin: 0 20px 0 0">' info += '<tr><td>Operating system: </td><td>'f'{sys.platform}''</td></tr>' info += '<tr><td>Python version:</td><td>' + sys.version.replace('\n', '') + '</td></tr>' info += '<tr><td>Hostname:</td><td>'f'{socket.gethostname()}''</td></tr>' try: login = f'{os.getlogin()}' except Exception as e: login = '' info += '<tr><td>Login name:</td><td>' + login + '</td></tr>' if self.config.custom_config_filename is None: custom_config_filename = 'Default <i>config.yaml</i> file loaded! A <i>custom_config.yaml</i> has been ' \ 'created in <i>/sensors/custom_config_files</i>!<br>If you rename it, change ' \ 'the <i>custom_config_filename</i> in the default config.yaml in ' \ '<i>/sensors</i>! ' \ '<br><b>Please change your settings in your custom config file!</b>' else: custom_config_filename = self.config.custom_config_filename info += '<tr><td>Configuration file: </td><td>' + custom_config_filename + '</td></tr>' KInsect_web_app = '<a href="https://webapp-test.kinsecta.org/login">KInsecta Web App</a>' if self.config.user_id is None: user_id = 'Not set yet! Please register to the ' + KInsect_web_app + ' to get assigned an ID and ' \ 'change the user_id in your <br> custom config.yaml file accordingly!' else: user_id = f'{self.config.user_id}' info += '<tr><td>User ID:</td><td>' + user_id + '</td></tr>' if self.config.sensor_id is None: sensor_id = 'Not set yet! After your first data upload to the ' + KInsect_web_app + ' a new sensor ID ' \ 'will be assigned to this sensor. <br> Please change the sensor_id in your custom ' \ 'config.yaml file accordingly!' else: sensor_id = f'{self.config.sensor_id}' info += '<tr><td>Sensor ID:</td><td>' + sensor_id + '</td></tr>' if self.config.name is None or self.config.postcode is None: name_postcode = 'Not set yet! Please provide information about the sensor location and its postcode in ' \ 'your custom config.yaml file!' else: name_postcode = f'{self.config.name}, {self.config.postcode}' info += '<tr><td>Sensor location:</td><td>' + name_postcode + '</td></tr>' info += '<tr><td>Masked GPS data:</td><td>'f'{self.config.gps_masked}''</td></tr>' if self.config.latitude is None or self.config.latitude is None: gps_data = 'Not set yet! Please provide GPS information in your custom config.yaml!' else: gps_data = f'{self.config.latitude}, {self.config.longitude}' info += '<tr><td>GPS data:</td><td>' + gps_data + '</td></tr>' info += '</table>' return info
[docs] def get_camera_info(self): """Creates PiCamera information. :return: html code for corresponding information :rtype: string """ info = '<h2>Camera Information</h2>\n' if self.camera is None: info = '<h2>No PiCamera found!<h2>' else: resolution = self.camera.MAX_RESOLUTION info += '<table style="width:100%; margin: 0 20px 0 0">' info += '<tr><td>PiCamera type:</td><td>'f'{self.camera.revision}''</td></tr>' info += '<tr><td>Maximum resolution:</td><td>'f'{resolution.width} x {resolution.height}''</td></tr>' info += '</table>' return info
[docs] def get_audio_info(self): """Creates audio system information. :return: html code for corresponding information :rtype: string """ info = '<h2>Audio Device Information</h2>\n' speaker, mic = self.audio_devices info += '<table style="width:100%; margin: 0 20px 0 0">' if mic is not None: info += '<tr><td>Microphone input ('f'{mic.channels}'' channels):</td><td>'f'{mic.id}''</td></tr>' else: info += '<tr><td>No USB microphone found!</td></tr>' if speaker is not None: info += '<tr><td>Speaker output ('f'{speaker.channels}'' channels):</td><td>'f'{speaker.id}''</td></tr>' else: info += '<tr><td>No USB speaker found!</td></tr>' info += '</table>' return info
[docs] def get_sensors_info(self): """Creates information about available sensors for measurement of meta data. :return: html code for corresponding information :rtype: string """ info = '<h2>Environmental Sensors Information</h2>\n' info += '<table style="width:100%; margin: 0 20px 0 0">' url_bme280 = '<a href="https://www.raspberrypi-spy.co.uk/2016/07/' \ 'using-bme280-i2c-temperature-pressure-sensor-in-python/">BME280</a>' if self.config.bme280_sensor[2] is not None: info += '<tr><td>Humidity sensor:</td><td>' + url_bme280 + '</td></tr>' else: info += '<tr><td>Humidity sensor:</td><td>n.a. (for more info visit ' + url_bme280 + ')</td></tr>' url_bh1750 = '<a href="https://learn.adafruit.com/adafruit-bh1750-ambient-light-sensor/python-circuitpython">' \ 'BH1750</a>' if self.config.bh1750_sensor is not None: info += '<tr><td>Ambient light sensor:</td><td>' + url_bh1750 + '</td></tr>' else: info += '<tr><td>Ambient light sensor:</td><td>n.a. (for more info visit ' + url_bh1750 + ')</td></tr>' url_as7341 = '<a href="https://learn.adafruit.com/adafruit-as7341-10-channel-light-color-sensor-breakout/' \ 'python-circuitpython">AS7341</a>' if self.config.as7341_sensor is not None: info += '<tr><td>Spectral color sensor:</td><td>' + url_as7341 + '</td></tr>' else: info += '<tr><td>Spectral color sensor:</td><td>n.a. (for more info visit ' + url_as7341 + ')</td></tr>' url_pmsa003i = '<a href="https://learn.adafruit.com/pmsa003i/python-circuitpython">PMSA003I</a>' if self.config.pmsa003i_sensor is not None: info += '<tr><td>Particulate matter sensor:</td><td>' + url_pmsa003i + '</td></tr>' else: info += '<tr><td>Particulate matter sensor:</td><td>n.a. ' \ '(for more info visit ' + url_pmsa003i + ')</td></tr>' info += '</table>' return info