added my Recipes

This commit is contained in:
2024-07-11 14:16:35 +02:00
parent 38bc4f53ac
commit 09b621d929
7118 changed files with 525762 additions and 3 deletions

View File

@@ -0,0 +1,71 @@
How to deploy demonstration:
----------------------------
Materials:
* Nucleo extension board with mems, here IKS01A2
* connection between extension board and stm32mp15 board.
Pre-requisite:
--------------
1. Kernel:
You need to configure the kernel to support the Nucleo extension
board with the devitree configuration and the kernel configuration.
1.1 DeviceTree:
* Enable the sensor on I2C
For Discovery board (stm32mp157c-dk2), the sensors are linked on ic25.
Add the following line on your devicetree associateds to the board
&i2c5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_pins_a>;
pinctrl-1 = <&i2c5_pins_sleep_a>;
i2c-scl-rising-time-ns = <124>;
i2c-scl-falling-time-ns = <3>;
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
hts221@5f {
compatible = "st,hts221";
reg = <0x5f>;
};
lsm6dsl@6b {
compatible = "st,lsm6dsl";
reg = <0x6b>;
};
};
NOTE: the i2c depend of the pin-muxing of the board and could be different of
i2c5.
1.2 Kernel configuration:
Add the following config on your kernel configuraturation
(best way are via a new fragment)
CONFIG_IIO_BUFFER=y
CONFIG_IIO_KFIFO_BUF=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_HTS221=y
CONFIG_IIO_ST_PRESS=y
CONFIG_IIO_ST_LSM6DSX=y
CONFIG_IIO_ST_LSM6DSX_I2C=y
2. Software
You need to have some framework available on the board for executing the
python script:
List of packages already present on st-example-image-weston:
weston
gtk+3
python3 and several python3 addons
Execution of script on board:
-----------------------------
Files:
/usr/local/demo/
/usr/local/demo/sensors_temperature.py
Put the files on board and launch the python script:
BOARD > /usr/local/demo/sensors_temperature.py
To quit the application, just click on ST logo.

View File

@@ -0,0 +1,7 @@
CONFIG_IIO_BUFFER=y
CONFIG_IIO_KFIFO_BUF=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_HTS221=y
CONFIG_IIO_ST_PRESS=y
CONFIG_IIO_ST_LSM6DSX=y
CONFIG_IIO_ST_LSM6DSX_I2C=y

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -0,0 +1,269 @@
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import GdkPixbuf
import cairo
import random
import math
import os
from time import sleep, time
# time between each sensor mesearuement (1s)
TIME_UPATE = 2000
class Sensors():
def __init__(self):
''' '''
self.sensor_dictionnary = {}
def found_iio_device_with_name(self, data, name):
prefix = "/sys/bus/iio/devices/"
of_name = 'OF_NAME=' + name
try:
for filefolder in os.listdir(prefix):
with open(prefix + '/' + filefolder + '/uevent') as f:
for line in f:
if line.split('\n')[0] == of_name:
''' return directory which contains "data" '''
if os.path.exists(prefix + '/' + filefolder + '/' + data):
return (prefix + '/' + filefolder + '/')
except OSError:
pass
except Exception as exc:
pass
return None
def found_all_sensor_path(self):
self.sensor_dictionnary['temperature'] = self.found_iio_device_with_name("in_temp_raw", "hts221")
self.sensor_dictionnary['humidity'] = self.found_iio_device_with_name("in_humidityrelative_raw", "hts221")
self.sensor_dictionnary['accelerometer'] = self.found_iio_device_with_name("in_accel_x_raw", "lsm6dsl")
self.sensor_dictionnary['gyroscope'] = self.found_iio_device_with_name("in_anglvel_x_raw", "lsm6dsl")
print("[DEBUG] temperature -> ", self.sensor_dictionnary['temperature'], "<")
print("[DEBUG] humidity -> ", self.sensor_dictionnary['humidity'], "<")
print("[DEBUG] accelerometer -> ", self.sensor_dictionnary['accelerometer'], "<")
print("[DEBUG] gyroscope -> ", self.sensor_dictionnary['gyroscope'], "<")
def temperature_read(self):
prefix_path = self.sensor_dictionnary['temperature']
try:
with open(prefix_path + "in_temp_" + 'raw', 'r') as f:
raw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_temp_" + 'raw', exc)
raw = 0.0
try:
with open(prefix_path + "in_temp_" + 'scale', 'r') as f:
scale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_temp_" + 'scale', exc)
scale = 0.0
try:
with open(prefix_path + "in_temp_" + 'offset', 'r') as f:
offset = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_temp_" + 'offset', exc)
offset = 0.0
return (offset + raw) * scale
def humidity_read(self):
prefix_path = self.sensor_dictionnary['humidity']
try:
with open(prefix_path + "in_humidityrelative_" + 'raw', 'r') as f:
raw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'raw', exc)
raw = 0.0
try:
with open(prefix_path + "in_humidityrelative_" + 'scale', 'r') as f:
scale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'scale', exc)
scale = 0.0
try:
with open(prefix_path + "in_humidityrelative_" + 'offset', 'r') as f:
offset = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'offset', exc)
offset = 0.0
return (offset + raw) * scale
def accelerometer_read(self):
prefix_path = self.sensor_dictionnary['accelerometer']
try:
with open(prefix_path + "in_accel_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'scale', exc)
rscale = 0.0
try:
with open(prefix_path + "in_accel_" + 'x_raw', 'r') as f:
xraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'x_raw', exc)
xraw = 0.0
accel_x = int(xraw * rscale * 256.0 / 9.81)
try:
with open(prefix_path + "in_accel_" + 'y_raw', 'r') as f:
yraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'y_raw', exc)
yraw = 0.0
accel_y = int(yraw * rscale * 256.0 / 9.81)
try:
with open(prefix_path + "in_accel_" + 'z_raw', 'r') as f:
zraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'z_raw', exc)
zraw = 0.0
accel_z = int(zraw * rscale * 256.0 / 9.81)
return [ accel_x, accel_y, accel_z]
def gyroscope_read(self):
prefix_path = self.sensor_dictionnary['gyroscope']
try:
with open(prefix_path + "in_anglvel_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'scale', exc)
rscale = 0.0
try:
with open(prefix_path + "in_anglvel_" + 'x_raw', 'r') as f:
xraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'x_raw', exc)
xraw = 0.0
gyro_x = int(xraw * rscale * 256.0 / 9.81)
try:
with open(prefix_path + "in_anglvel_" + 'y_raw', 'r') as f:
yraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'y_raw', exc)
yraw = 0.0
gyro_y = int(yraw * rscale * 256.0 / 9.81)
try:
with open(prefix_path + "in_anglvel_" + 'z_raw', 'r') as f:
zraw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'z_raw', exc)
zraw = 0.0
gyro_z = int(zraw * rscale * 256.0 / 9.81)
return [ gyro_x, gyro_y, gyro_z]
# -------------------------------------------------------------------
# -------------------------------------------------------------------
class MainUIWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Sensor usage")
#self.set_decorated(False)
self.maximize()
self.screen_width = self.get_screen().get_width()
self.screen_height = self.get_screen().get_height()
self.set_default_size(self.screen_width, self.screen_height)
print("[DEBUG] screen size: %dx%d" % (self.screen_width, self.screen_height))
self.set_position(Gtk.WindowPosition.CENTER)
self.connect('destroy', Gtk.main_quit)
# search sensor interface
self.sensors = Sensors()
self.sensors.found_all_sensor_path()
sensor_box = Gtk.VBox(homogeneous=False, spacing=0)
# temperature
temp_label = Gtk.Label()
temp_label.set_markup("<span font_desc='LiberationSans 25'>Temperature</span>")
self.temp_value_label = Gtk.Label()
self.temp_value_label.set_markup("<span font_desc='LiberationSans 25'>--.-- °C</span>")
temp_box = Gtk.HBox(homogeneous=False, spacing=0)
temp_box.add(temp_label)
temp_box.add(self.temp_value_label)
sensor_box.add(temp_box)
# humidity
humidity_label = Gtk.Label()
humidity_label.set_markup("<span font_desc='LiberationSans 25'>Humidity</span>")
self.humidity_value_label = Gtk.Label()
self.humidity_value_label.set_markup("<span font_desc='LiberationSans 25'>--.-- %c</span>" % '%')
humidity_box = Gtk.HBox(homogeneous=False, spacing=0)
humidity_box.add(humidity_label)
humidity_box.add(self.humidity_value_label)
sensor_box.add(humidity_box)
# Accel
accel_label = Gtk.Label()
accel_label.set_markup("<span font_desc='LiberationSans 25'>Accelerometer</span>")
self.accel_value_label = Gtk.Label()
self.accel_value_label.set_markup("<span font_desc='LiberationSans 25'> [ --.--, --.--, --.--]</span>")
accel_box = Gtk.HBox(homogeneous=False, spacing=0)
accel_box.add(accel_label)
accel_box.add(self.accel_value_label)
sensor_box.add(accel_box)
# Gyroscope
gyro_label = Gtk.Label()
gyro_label.set_markup("<span font_desc='LiberationSans 25'>Gyroscope</span>")
self.gyro_value_label = Gtk.Label()
self.gyro_value_label.set_markup("<span font_desc='LiberationSans 25'> [ --.--, --.--, --.--]</span>")
gyro_box = Gtk.HBox(homogeneous=False, spacing=0)
gyro_box.add(gyro_label)
gyro_box.add(self.gyro_value_label)
sensor_box.add(gyro_box)
self.add(sensor_box)
# Add a timer callback to update
# this takes 2 args: (how often to update in millisec, the method to run)
GLib.timeout_add(TIME_UPATE, self.update_ui)
def destroy(self, widget, data=None):
Gtk.main_quit()
def update_ui(self):
# temperature
temp = self.sensors.temperature_read()
self.temp_value_label.set_markup("<span font_desc='LiberationSans 25'>%.02f °C</span>" % temp)
# humidity
hum = self.sensors.humidity_read()
self.humidity_value_label.set_markup("<span font_desc='LiberationSans 25'>%.02f %c</span>" % (hum, '%'))
# accel
accel = self.sensors.accelerometer_read()
self.accel_value_label.set_markup("<span font_desc='LiberationSans 25'>[ %.02f, %.02f, %.02f]</span>" % (accel[0], accel[1], accel[2]))
# gyro
gyro = self.sensors.gyroscope_read()
self.gyro_value_label.set_markup("<span font_desc='LiberationSans 25'>[ %.02f, %.02f, %.02f]</span>" % (gyro[0], gyro[1], gyro[2]))
# As this is a timeout function, return True so that it
# continues to get called
return True
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# Main
if __name__ == "__main__":
# add signal to catch CRTL+C
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
win = MainUIWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

View File

@@ -0,0 +1,91 @@
#!/bin/sh
for d in `ls -d1 /sys/bus/iio/devices/*device*`;
do
# for hts221: Temperature + Humidity
if grep -q hts221 $d/name ;
then
echo "============================="
echo "=== HTS221 ==="
echo "=== (temperature) ==="
echo "============================="
raw=`cat $d/in_temp_raw`
offset=`cat $d/in_temp_offset`
scale=`cat $d/in_temp_scale`
printf "Value read: raw %0f\n" $raw
printf "Value read: offset %0f\n" $offset
printf "Value read: scale %0f\n" $scale
temperature=`echo "scale=2;$raw*$scale + $offset*$scale" | bc`
echo "Temperature $temperature"
printf "Temperature %.02f\n" $temperature
echo "============================="
echo "=== HTS221 ==="
echo "=== (humidity) ==="
echo "============================="
raw=`cat $d/in_humidityrelative_raw`
offset=`cat $d/in_humidityrelative_offset`
scale=`cat $d/in_humidityrelative_scale`
printf "Value read: raw %0f\n" $raw
printf "Value read: offset %0f\n" $offset
printf "Value read: scale %0f\n" $scale
humidity=`echo "scale=2;$raw*$scale + $offset*$scale" | bc`
echo "Humidity $humidity"
printf "Humidity %.02f\n" $humidity
fi
# for lsm6dsl: accelerometer
if grep -q lsm6dsl_accel $d/name ;
then
echo "============================="
echo "=== LSM6DSL ==="
echo "=== (accelerometer) ==="
echo "============================="
rscale=`cat $d/in_accel_scale`
xraw=`cat $d/in_accel_x_raw`
yraw=`cat $d/in_accel_y_raw`
zraw=`cat $d/in_accel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
fi
# for lsm6dsl: gyroscope
if grep -q lsm6dsl_gyro $d/name ;
then
echo "============================="
echo "=== LSM6DSL ==="
echo "=== (gyroscope) ==="
echo "============================="
rscale=`cat $d/in_anglvel_scale`
xraw=`cat $d/in_anglvel_x_raw`
yraw=`cat $d/in_anglvel_y_raw`
zraw=`cat $d/in_anglvel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
fi
done

View File

@@ -0,0 +1,767 @@
#!/usr/bin/python3
# to debug this script:
# python3 -m pdb ./sensors_temperature.py
#
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import GdkPixbuf
import cairo
import random
import math
import os
import socket
from collections import deque
from time import sleep, time
#
# For simulating the presence of sensor, please use
# the variable SIMULATE_SENSORS = 1
# If SIMULATE_SENSORS = 1 then
# the picture/icon must be present on pictures directory
#
SIMULATE_SENSORS = 0
ICON_PICTURES_PATH = "/usr/local/demo/pictures"
WITH_PRESSURE = 0
WITH_GYRO = 1
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# CONSTANT VALUES
#
SIMULATE_SCREEN_SIZE_WIDTH = 480
SIMULATE_SCREEN_SIZE_HEIGHT = 800
DEFAULT_SCREEN_WIDTH = 400
DEFAULT_SCREEN_HEIGHT = 600
# time between each sensor mesearuement (1s)
TIME_UPATE = 2000
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# SPLASH SCREEN class
# the splash screen display a logo and the different step of boot
#
class SplashScreen():
def __init__(self, picture_filename, timeout):
#DONT connect 'destroy' event here!
self.window = Gtk.Window()
self.window.set_title('Sensor IKS01A2')
self.window.set_position(Gtk.WindowPosition.CENTER)
self.window.set_decorated(False)
if SIMULATE_SENSORS > 0:
screen_width = SIMULATE_SCREEN_SIZE_WIDTH
screen_height = SIMULATE_SCREEN_SIZE_HEIGHT
else:
self.window.fullscreen()
#self.maximize()
screen_width = self.window.get_screen().get_width()
screen_height = self.window.get_screen().get_height()
self.window.set_default_size(screen_width, screen_height)
self.window.set_border_width(1)
# Add Vbox with image and label
main_vbox = Gtk.VBox(False, 1)
self.window.add(main_vbox)
# load picture
print("[DEBUG] Splash screen with picture: %s" % picture_filename)
if os.path.exists(picture_filename):
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename=picture_filename,
width=400, # TODO: change size
height=600, # TODO: change size
preserve_aspect_ratio=True)
image = Gtk.Image.new_from_pixbuf(pixbuf)
main_vbox.pack_start(image, True, True, 0)
#self.lbl = Gtk.Label("Init: splash screen")
#self.lbl.set_alignment(0, 0.5)
#main_vbox.pack_start(self.lbl, True, True, 0)
self.window.set_auto_startup_notification(False)
self.window.show_all()
self.window.set_auto_startup_notification(True)
# Ensure the splash is completely drawn before moving on
GLib.timeout_add(1000, self.loop)
self.loops = 0
self.loops_timeout = timeout
self.loops_break = 0
def update_text(self, text):
self.lbl.set_text(text)
def loop_stop(self):
self.loops_break = 1
def loop(self):
global var
var = time ()
print ("[DEBUG] ", var)
self.loops += 1
if self.loops_break or self.loops == self.loops_timeout:
Gtk.main_quit()
self.window.destroy()
return False
return True
# -------------------------------------------------------------------
# -------------------------------------------------------------------
def _load_image_on_button(parent, filename, label_text, scale_w, scale_h):
# Create box for xpm and label
box1 = Gtk.HBox(homogeneous=False, spacing=0)
box1.set_border_width(2)
# Now on to the image stuff
#image = Gtk.Image()
#image.set_from_file(filename)
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename=filename,
width=scale_w,
height=scale_h,
preserve_aspect_ratio=True)
image = Gtk.Image.new_from_pixbuf(pixbuf)
# Create a label for the button
label = Gtk.Label(label_text)
# Pack the pixmap and label into the box
box1.pack_start(image, True, False, 3)
#box1.pack_start(label, False, False, 3)
image.show()
label.show()
return box1
# -------------------------------------------------------------------
# -------------------------------------------------------------------
def _load_image(parent, filename_without_prefix):
img = Gtk.Image()
img.set_from_file("%s/%s" % (ICON_PICTURES_PATH, filename_without_prefix))
return img
# scale_width and scale_height are sht siez disired after scale,
# It can be -1 for no scale on one value
def _load_image_constrained(parent, filename_without_prefix, scale_width, scale_height):
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename="%s/%s" % (ICON_PICTURES_PATH, filename_without_prefix),
width=scale_width,
height=scale_height,
preserve_aspect_ratio=True)
image = Gtk.Image.new_from_pixbuf(pixbuf)
return image
# -------------------------------------------------------------------
# -------------------------------------------------------------------
class Sensors():
key_temperature = 'temp'
key_humidity = 'humidity'
key_pressure = 'pressure'
key_accelerometer = 'accel'
key_gyroscope = 'gyro'
key_magnetometer = 'magneto'
driver_name_temperature = 'driver_temp'
driver_name_humidity = 'driver_humidity'
driver_name_pressure = 'driver_pressure'
driver_name_accelerometer = 'driver_accel'
driver_name_gyroscope = 'driver_gyro'
driver_name_magnetometer = 'driver_magneto'
prefix_temp = "in_temp_"
prefix_humidity = "in_humidityrelative_"
prefix_pressure = "in_pressure_"
prefix_accel = "in_accel_"
prefix_gyro = "in_anglvel_"
prefix_magneto = "in_magn_" # TODO: verify
def __init__(self):
''' '''
self.sensor_dictionnary = {}
def init_pressure_sampling_frequency(self):
if not self.sensor_dictionnary[self.key_pressure] is None and len(self.sensor_dictionnary[self.key_pressure]) > 5:
with open(self.sensor_dictionnary[self.key_pressure] + 'sampling_frequency', 'w') as f:
f.write('10')
def found_iio_device(self, data):
prefix = "/sys/bus/iio/devices/"
try:
for filefolder in os.listdir(prefix):
if os.path.exists(prefix + '/' + filefolder + '/' + data):
''' return directory which contains "data" '''
return (prefix + '/' + filefolder + '/')
except OSError:
pass
return None
def found_iio_device_with_name(self, data, name):
prefix = "/sys/bus/iio/devices/"
of_name = 'OF_NAME=' + name
try:
for filefolder in os.listdir(prefix):
with open(prefix + '/' + filefolder + '/uevent') as f:
for line in f:
if line.split('\n')[0] == of_name:
''' return directory which contains "data" '''
if os.path.exists(prefix + '/' + filefolder + '/' + data):
return (prefix + '/' + filefolder + '/')
except OSError:
pass
except Exception as exc:
pass
return None
def driver_name_iio_device(self, key):
if SIMULATE_SENSORS > 0:
val_name = "-Simulated-"
else:
if self.sensor_dictionnary[key] == None:
val_name = "-Not present / Simulated-"
else:
try:
with open(self.sensor_dictionnary[key] + "name", 'r') as f:
val_name = f.read()
except Exception as exc:
val_name = "-Not present-"
return val_name
def found_all_sensor_path(self):
self.sensor_dictionnary[self.key_temperature] = self.found_iio_device_with_name("in_temp_raw", "hts221")
self.sensor_dictionnary[self.key_humidity] = self.found_iio_device("in_humidityrelative_raw")
self.sensor_dictionnary[self.key_pressure] = self.found_iio_device("in_pressure_raw")
self.sensor_dictionnary[self.key_accelerometer] = self.found_iio_device("in_accel_x_raw")
if WITH_GYRO:
self.sensor_dictionnary[self.key_gyroscope] = self.found_iio_device("in_anglvel_x_raw")
else:
self.sensor_dictionnary[self.key_gyroscope] = ""
self.sensor_dictionnary[self.key_magnetometer] = "" #TODO
self.sensor_dictionnary[self.driver_name_temperature] = self.driver_name_iio_device(self.key_temperature)
self.sensor_dictionnary[self.driver_name_humidity] = self.driver_name_iio_device(self.key_humidity)
self.sensor_dictionnary[self.driver_name_pressure] = self.driver_name_iio_device(self.key_pressure)
self.sensor_dictionnary[self.driver_name_accelerometer] = self.driver_name_iio_device(self.key_accelerometer)
self.sensor_dictionnary[self.driver_name_gyroscope] = self.driver_name_iio_device(self.key_gyroscope)
self.sensor_dictionnary[self.driver_name_magnetometer] = self.driver_name_iio_device(self.key_magnetometer)
self.init_pressure_sampling_frequency()
print("[DEBUG] " , self.key_temperature, " -> ", self.sensor_dictionnary[self.key_temperature], "<")
print("[DEBUG] " , self.key_humidity, " -> ", self.sensor_dictionnary[self.key_humidity], "<")
print("[DEBUG] " , self.key_pressure, " -> ", self.sensor_dictionnary[self.key_pressure], "<")
print("[DEBUG] " , self.key_accelerometer, " -> ", self.sensor_dictionnary[self.key_accelerometer], "<")
print("[DEBUG] " , self.key_gyroscope, " -> ", self.sensor_dictionnary[self.key_gyroscope], "<")
print("[DEBUG] " , self.key_magnetometer, " -> ", self.sensor_dictionnary[self.key_magnetometer], "<")
def read_sensor_basic(self, key, prefix):
if SIMULATE_SENSORS > 0:
if self.key_temperature == key:
return random.uniform(0.0, 50.0)
elif self.key_humidity == key:
return random.uniform(0.0, 100.0)
else:
return random.uniform(800.0, 1200.0)
else:
if self.sensor_dictionnary[key] is None or len(self.sensor_dictionnary[key]) < 5:
return 0.0
try:
with open(self.sensor_dictionnary[key] + prefix + 'raw', 'r') as f:
raw = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % self.sensor_dictionnary[key] + prefix + 'raw', exc)
raw = 0.0
try:
with open(self.sensor_dictionnary[key] + prefix + 'scale', 'r') as f:
scale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % self.sensor_dictionnary[key] + prefix + 'scale', exc)
scale = 0.0
if self.key_pressure != key:
try:
with open(self.sensor_dictionnary[key] + prefix + 'offset', 'r') as f:
offset = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % self.sensor_dictionnary[key] + prefix + 'offset', exc)
offset = 0.0
else:
offset = 0.0
scale = scale * 10
temp = (offset + raw) * scale
#print("[DEBUG] [%s] %f" % (key, temp))
return temp
def read_sensor_move(self, key, prefix):
if SIMULATE_SENSORS > 0:
in_x = random.randint(-180, 180)
in_y = random.randint(-180, 180)
in_z = random.randint(-180, 180)
return [in_x, in_y, in_z]
else:
if self.sensor_dictionnary[key] is None or len(self.sensor_dictionnary[key]) < 5:
return [0, 0, 0]
try:
with open(self.sensor_dictionnary[key] + prefix + 'x_raw', 'r') as f:
scale = float(f.read())
with open(self.sensor_dictionnary[key] + prefix + 'x_scale', 'r') as f:
raw = float(f.read())
in_x = int(raw * scale * 256.0 / 9.81)
with open(self.sensor_dictionnary[key] + prefix + 'y_raw', 'r') as f:
scale = float(f.read())
with open(self.sensor_dictionnary[key] + prefix + 'y_scale', 'r') as f:
raw = float(f.read())
in_y = int(raw * scale * 256.0 / 9.81)
with open(self.sensor_dictionnary[key] + prefix + 'z_raw', 'r') as f:
scale = float(f.read())
with open(self.sensor_dictionnary[key] + prefix + 'z_scale', 'r') as f:
raw = float(f.read())
in_z = int(raw * scale * 256.0 / 9.81)
except Exception as exc:
print("[ERROR] read %s " % self.sensor_dictionnary[key] + prefix + '[x_ , y_ , z_ ]', exc)
return [0, 0, 0]
return [in_x, in_y, in_z]
def read_temperature(self):
return self.read_sensor_basic(self.key_temperature, self.prefix_temp)
def read_humidity(self):
return self.read_sensor_basic(self.key_humidity, self.prefix_humidity)
def read_pressure(self):
return self.read_sensor_basic(self.key_pressure, self.prefix_pressure)
def read_accelerometer(self):
return self.read_sensor_move(self.key_accelerometer, self.prefix_accel)
def read_gyroscope(self):
return self.read_sensor_move(self.key_gyroscope, self.prefix_gyro)
def read_magnetometer(self):
return self.read_sensor_move(self.key_magnetometer, self.prefix_magneto)
def get_driver_name_temperature(self):
return self.sensor_dictionnary[self.driver_name_temperature]
def get_driver_name_humidity(self):
return self.sensor_dictionnary[self.driver_name_humidity]
def get_driver_name_pressure(self):
return self.sensor_dictionnary[self.driver_name_pressure]
def get_driver_name_accelerometer(self):
return self.sensor_dictionnary[self.driver_name_accelerometer]
def get_driver_name_gyroscope(self):
return self.sensor_dictionnary[self.driver_name_gyroscope]
def get_driver_name_magnetometer(self):
return self.sensor_dictionnary[self.driver_name_magnetometer]
def calculate_imu(self, accel):
x = accel[0]
y = accel[1]
z = accel[2]
if x == 0 and y == 0 and z == 0:
return [0, 0, 0]
pitch = round(math.atan(x / math.sqrt(y * y + z * z)) * (180.0 / math.pi))
roll = round(math.atan(y / math.sqrt(x * x + z * z)) * (180.0 / math.pi))
yaw = round(math.atan(z / math.sqrt(x * x + z * z)) * (180.0 / math.pi))
return [pitch, roll, yaw]
def get_imu_orientation(self, pitch, roll):
if abs(pitch) > 35:
''' (rotation > 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP;'''
if pitch > 0:
return "left-up"
else:
return "right-up"
else:
if abs(roll) > 35:
'''ret = (rotation > 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL;'''
if roll > 0:
return "bottom-up"
else:
return "normal"
# -------------------------------------------------------------------
# -------------------------------------------------------------------
class MainUIWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Sensor usage")
self.set_decorated(False)
if SIMULATE_SENSORS > 0:
self.screen_width = SIMULATE_SCREEN_SIZE_WIDTH
self.screen_height = SIMULATE_SCREEN_SIZE_HEIGHT
else:
self.fullscreen()
#self.maximize()
self.screen_width = self.get_screen().get_width()
self.screen_height = self.get_screen().get_height()
self.set_default_size(self.screen_width, self.screen_height)
print("[DEBUG] screen size: %dx%d" % (self.screen_width, self.screen_height))
self.set_position(Gtk.WindowPosition.CENTER)
self.connect('destroy', Gtk.main_quit)
# search sensor interface
self.sensors = Sensors()
self.sensors.found_all_sensor_path()
# variable for sensor
self._axis_ranges = {} # {axis_num: [min_seen, max_seen]}
self._axis_values = {} # {axis_num: deque([val0, ..., valN])}
# create nodebook
self.notebook = Gtk.Notebook()
self.add(self.notebook)
# page for basic information
# current temperature / Humidity / Pressure
self.create_notebook_page_basic_sensor()
# page for accel / gyro / magentic
self.create_notebook_page_basic_accel()
# page for IMU
self.create_notebook_page_imu()
# page sensor information
self.create_notebook_page_sensor_information()
# page for quitting application
self.create_notebook_page_exit()
# Add a timer callback to update
# this takes 2 args: (how often to update in millisec, the method to run)
self.timer = GObject.timeout_add(TIME_UPATE, self.update_ui, None)
self.timer_enable = True
self.show_all()
def _set_basic_temperature(self, val):
self.temperature_basic_label.set_markup("<span font_desc='LiberationSans 25'>%.02f °C</span>" % val)
#self.temperature_basic_label.set_text("%.02f °C" % val)
def _set_basic_humidity(self, val):
self.humidity_basic_label.set_markup("<span font_desc='LiberationSans 25'>%.02f %c</span>" % (val, '%'))
#self.humidity_basic_label.set_text("%.02f %c" % (val, '%'))
def _set_basic_pressure(self, val):
self.pressure_basic_label.set_markup("<span font_desc='LiberationSans 25'>%.02f hP</span>" % val)
#self.pressure_basic_label.set_text("%.02f hP" % val)
def _set_basic_accelerometer(self, x, y, z):
self.liststore[self.accel_store][1] = '%d' % x
self.liststore[self.accel_store][2] = '%d' % y
self.liststore[self.accel_store][3] = '%d' % z
def _set_basic_gyroscope(self, x, y, z):
self.liststore[self.gyro_store][1] = '%d' % x
self.liststore[self.gyro_store][2] = '%d' % y
self.liststore[self.gyro_store][3] = '%d' % z
def _set_basic_magnetometer(self, x, y, z):
self.liststore[self.magneto_store][1] = '%d' % x
self.liststore[self.magneto_store][2] = '%d' % y
self.liststore[self.magneto_store][3] = '%d' % z
def _set_imu_roll(self, val):
self.imu_liststore[self.roll_store][1] = '%d' % val
def _set_imu_pitch(self, val):
self.imu_liststore[self.pitch_store][1] = '%d' % val
def _set_imu_yaw(self, val):
self.imu_liststore[self.yaw_store][1] = '%d' % val
def _update_orientation(self, val):
self.orientation_label.set_markup("<span font_desc='LiberationSans 25'>Orientation: %s</span>" % val)
def create_notebook_page_basic_sensor(self):
'''
create notebook page for displaying basic current
sensor information: temperature, humidity, pressure
'''
page_basic = Gtk.HBox(homogeneous=False, spacing=0)
page_basic.set_border_width(10)
# temperature
temp_box = Gtk.VBox(homogeneous=False, spacing=0)
temp_image = _load_image_constrained(self, "RS1069_climate_change_light_blue.png", -1, 100)
self.temperature_basic_label = Gtk.Label('--.-- °C')
temp_image.show()
self.temperature_basic_label.show()
temp_box.pack_start(temp_image, True, False, 1)
temp_box.add(self.temperature_basic_label)
# humidity
humidity_box = Gtk.VBox(homogeneous=False, spacing=0)
humidity_image = _load_image_constrained(self, "RS1902_humidity_light_blue.png", -1, 100)
self.humidity_basic_label = Gtk.Label('--.-- °C')
humidity_image.show()
self.humidity_basic_label.show()
humidity_box.pack_start(humidity_image, True, False, 1)
humidity_box.add(self.humidity_basic_label)
# Pressure
if WITH_PRESSURE:
pressure_box = Gtk.VBox(homogeneous=False, spacing=0)
pressure_image = _load_image_constrained(self, "RS6355_FORCE_PRESSURE_light_blue.png", -1, 100)
self.pressure_basic_label = Gtk.Label('--.-- °C')
pressure_image.show()
self.pressure_basic_label.show()
pressure_box.pack_start(pressure_image, True, False, 1)
pressure_box.add(self.pressure_basic_label)
page_basic.add(temp_box)
page_basic.add(humidity_box)
if WITH_PRESSURE:
page_basic.add(pressure_box)
notebook_title = Gtk.Label()
notebook_title.set_markup("<span font_desc='LiberationSans 25'>Sensors</span>")
self.notebook.append_page(page_basic, notebook_title)
def create_notebook_page_basic_accel(self):
'''
create notebook page for displaying movement
sensor information: accellerometer, gyroscope, magentometer
'''
page_basic_movement = Gtk.Box()
page_basic_movement.set_border_width(10)
self.liststore = Gtk.ListStore(str, str, str, str)
self.accel_store = self.liststore.append([ "Accelerometer", "0.0", "0.0", "0.0" ])
if WITH_GYRO:
self.gyro_store = self.liststore.append([ "Gyroscope", "0.0", "0.0", "0.0" ])
#if WITH_MAGNETO:
# self.magneto_store = self.liststore.append([ "Magnetometer", "0.0", "0.0", "0.0" ])
treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Sensor", renderer_text, text=0)
treeview.append_column(column_text)
renderer_x = Gtk.CellRendererText()
column_x = Gtk.TreeViewColumn("X", renderer_x, text=1)
treeview.append_column(column_x)
renderer_y = Gtk.CellRendererText()
column_y = Gtk.TreeViewColumn("Y", renderer_y, text=2)
treeview.append_column(column_y)
renderer_z = Gtk.CellRendererText()
column_z = Gtk.TreeViewColumn("Z", renderer_z, text=3)
treeview.append_column(column_z)
page_basic_movement.add(treeview)
notebook_title = Gtk.Label()
notebook_title.set_markup("<span font_desc='LiberationSans 25'>Move</span>")
self.notebook.append_page(page_basic_movement, notebook_title)
def create_notebook_page_imu(self):
'''
display the IMU: Inertial Measurement Unit
Roll(X-axis), Pitch(Y-axis) and Yaw(Z-axis).
'''
page_imu_all = Gtk.VBox(homogeneous=False, spacing=0)
imu_frame = Gtk.Frame(label="IMU")
orientation_frame = Gtk.Frame(label="Orientation")
page_imu = Gtk.VBox(homogeneous=False, spacing=0)
#page_imu_all.add(page_imu)
page_imu_all.add(imu_frame)
page_imu_all.add(orientation_frame)
page_imu.set_border_width(10)
# explanation
imu_label = Gtk.Label()
imu_label.set_markup("<span font_desc='LiberationSans 25'>Inertial Measurement Unit</span>")
page_imu.add(imu_label)
imu_h_box = Gtk.HBox(homogeneous=False, spacing=0)
# picture which describe IMU
picture_filename = "%s/RS10670_Aereo-lpr.jpg" % ICON_PICTURES_PATH
image_imu = _load_image(self, "RS10670_Aereo-lpr.jpg")
imu_h_box.pack_start(image_imu, True, True, 10)
# add tree view with roll, picth, yaw
self.imu_liststore = Gtk.ListStore(str, str)
self.roll_store = self.imu_liststore.append([ "Roll (X-axis)", "0.0"])
self.pitch_store = self.imu_liststore.append([ "Pitch (Y-axis)", "0.0"])
self.yaw_store = self.imu_liststore.append([ "Yaw (Z-axis)", "0.0"])
imu_treeview = Gtk.TreeView(model=self.imu_liststore)
imu_h_box.add(imu_treeview)
page_imu.add(imu_h_box)
imu_frame.add(page_imu)
self.orientation_label = Gtk.Label()
self.orientation_label.set_markup("<span font_desc='LiberationSans 25'>Orientation: --none--</span>")
orientation_frame.add(self.orientation_label)
renderer_text = Gtk.CellRendererText()
#renderer_text.set_property("size", 18)
column_imu_text = Gtk.TreeViewColumn('Type', renderer_text, text=0)
imu_treeview.append_column(column_imu_text)
renderer_val = Gtk.CellRendererText()
column_val = Gtk.TreeViewColumn("Value", renderer_val, text=1)
imu_treeview.append_column(column_val)
notebook_title = Gtk.Label()
notebook_title.set_markup("<span font_desc='LiberationSans 25'>IMU</span>")
self.notebook.append_page(page_imu_all, notebook_title)
def _create_frame_with_image_and_label(self, title, img_file_name, label_text):
frame = Gtk.Frame(label=title)
box = Gtk.VBox(homogeneous=False, spacing=0)
img = _load_image(self, img_file_name)
img = _load_image_constrained(self, img_file_name, -1, 100)
label = Gtk.Label()
label.set_markup("<span font_desc='LiberationSans 18'>%s</span>" % label_text)
box.add(img)
box.add(label)
frame.add(box)
return frame
def create_notebook_page_sensor_information(self):
''' Display all the sensor used for this demo '''
page_sensor_info = Gtk.Grid()
frame_temp = self._create_frame_with_image_and_label(
"%25s" % "Temperature",
"RS1069_climate_change_light_blue.png",
self.sensors.get_driver_name_temperature()
)
frame_humidity = self._create_frame_with_image_and_label(
"%25s" % "Humidity",
"RS1902_humidity_light_blue.png",
self.sensors.get_driver_name_humidity()
)
if WITH_PRESSURE:
frame_pressure = self._create_frame_with_image_and_label(
"%25s" % "Pressure",
"RS6355_FORCE_PRESSURE_light_blue.png",
self.sensors.get_driver_name_pressure()
)
frame_accel = self._create_frame_with_image_and_label(
"%25s" % "Accelerometer",
"RS1761_MEMS_accelerometer_light_blue.png",
self.sensors.get_driver_name_accelerometer()
)
if WITH_GYRO:
frame_gyro = self._create_frame_with_image_and_label(
"%25s" % "Gyroscope",
"RS1760_MEMS_gyroscope_light_blue.png",
self.sensors.get_driver_name_gyroscope()
)
#if WITH_MAGNETO:
# frame_magneto = self._create_frame_with_image_and_label(
# "%25s" % "Magnetometer",
# "RS1762_MEMS_compass_light_blue.png",
# self.sensors.get_driver_name_magnetometer()
# )
page_sensor_info.set_column_spacing(2)
page_sensor_info.set_row_spacing(2)
page_sensor_info.attach(frame_temp, 1, 1, 3, 1)
page_sensor_info.attach_next_to(frame_humidity, frame_temp,
Gtk.PositionType.RIGHT, 1, 1)
if WITH_PRESSURE:
page_sensor_info.attach_next_to(frame_pressure, frame_humidity,
Gtk.PositionType.RIGHT, 1, 1)
page_sensor_info.attach_next_to(frame_accel, frame_temp,
Gtk.PositionType.BOTTOM, 1, 1)
if WITH_GYRO:
page_sensor_info.attach_next_to(frame_gyro, frame_accel,
Gtk.PositionType.RIGHT, 1, 1)
#if WITH_MAGNETO:
# page_sensor_info.attach_next_to(frame_magneto, frame_gyro,
# Gtk.PositionType.RIGHT, 1, 1)
#self.notebook.append_page(page_sensor_info,
# Gtk.Image.new_from_icon_name(
# "dialog-information",
# Gtk.IconSize.MENU
# ))
notebook_title = Gtk.Label()
notebook_title.set_markup("<span font_desc='LiberationSans 25'>Infos</span>")
self.notebook.append_page(page_sensor_info, notebook_title)
def create_notebook_page_exit(self):
''' notebook page for quitting application '''
page = Gtk.VBox(homogeneous=False, spacing=0)
page.set_border_width(10)
''' button '''
lastbutton = Gtk.Button()
lastbutton.connect("clicked", self.destroy)
image_to_add = _load_image_on_button(self, "%s/RS70_ST_Logo_Qi.png" % ICON_PICTURES_PATH, "Quit", -1, 200)
lastbutton.add(image_to_add)
lastbutton.show()
page.pack_start(lastbutton, True, True, 0)
exit_label = Gtk.Label()
exit_label.set_markup("<span font_desc='LiberationSans 25'>To exit, click on logo.</span>")
page.pack_start(exit_label, False, False, 0)
notebook_title = Gtk.Label()
notebook_title.set_markup("<span font_desc='LiberationSans 25'>EXIT</span>")
self.notebook.append_page(page, notebook_title)
def destroy(self, widget, data=None):
Gtk.main_quit()
def rearm_timer(self):
if self.timer_enable:
self.timer = GObject.timeout_add(TIME_UPATE, self.update_ui, None)
def update_ui(self, user_data):
if False == self.timer_enable:
return False;
# temperature
temp = self.sensors.read_temperature()
self._set_basic_temperature(temp)
# humidity
hum = self.sensors.read_humidity()
self._set_basic_humidity(hum)
# pressure
if WITH_PRESSURE:
press = self.sensors.read_pressure()
self._set_basic_pressure(press)
# accel
accel = self.sensors.read_accelerometer()
self._set_basic_accelerometer(accel[0], accel[1], accel[2])
# gyro
if WITH_GYRO:
gyro = self.sensors.read_gyroscope()
self._set_basic_gyroscope(gyro[0], gyro[1], gyro[2])
# magneto
#if WITH_MAGNETO:
# magneto = self.sensors.read_magnetometer()
# self._set_basic_magnetometer(magneto[0], magneto[1], magneto[2])
# imu
pitch, roll, yaw = self.sensors.calculate_imu(accel)
self._set_imu_pitch(pitch)
self._set_imu_roll(roll)
self._set_imu_yaw(yaw)
self._update_orientation(self.sensors.get_imu_orientation(pitch, roll))
#print("[DEBUG] visibility: ", self.get_property("visible"))
# As this is a timeout function, return True so that it
# continues to get called
return True
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# Main
if __name__ == "__main__":
# add signal to catch CRTL+C
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
try:
#splScr = SplashScreen("%s/RS70_ST_Logo_Qi.png" % ICON_PICTURES_PATH, 5)
#Gtk.main()
win = MainUIWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
except Exception as exc:
print("Main Exception: ", exc )
Gtk.main()

View File

@@ -0,0 +1,505 @@
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject
from gi.repository import Gdk
import cairo
import random
import math
from collections import deque
import os
#for testing on PC without sensors, put REAL to 0
MAKE_REAL_MESUREMENT = 1
NUM_SAMPLES = 112
HMARGIN = 20
VMARGIN = 10
CHARTHEIGHT = 40
GRAPH_V_PADDING = 4
GRAPH_H_PADDING = 4
#TIME_UPATE = 5000
TIME_UPATE = 1000
# example of orientation
# https://github.com/hadess/iio-sensor-proxy/blob/master/src/test-orientation-gtk.c
ORIENTATION_UNDEFINED = 0
ORIENTATION_NORMAL = 1
ORIENTATION_BOTTOM_UP = 2
ORIENTATION_LEFT_UP = 3
ORIENTATION_RIGHT_UP = 4
def _load_image_on_button(parent, filename, label_text):
# Create box for xpm and label
box1 = Gtk.HBox(False, 0)
box1.set_border_width(2)
# Now on to the image stuff
image = Gtk.Image()
image.set_from_file(filename)
# Create a label for the button
label = Gtk.Label(label_text)
# Pack the pixmap and label into the box
box1.pack_start(image, True, False, 3)
#box1.pack_start(label, False, False, 3)
image.show()
label.show()
return box1
class SensorWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Temperature/Humidity")
if MAKE_REAL_MESUREMENT > 0:
self.fullscreen()
#self.maximize()
screen_width = self.get_screen().get_width()
screen_height = 600
else:
screen_width = 400
screen_height = 600
self.temperature_prefix_path = self.found_iio_device("in_temp_raw")
self.humidity_prefix_path = self.found_iio_device("in_humidityrelative_raw")
self.accelerometer_prefix_path = self.found_iio_device("in_accel_x_raw")
#screen_height = self.get_screen().get_height()
self.set_default_size(screen_width, screen_height)
# current, Max, Min
self.temperature_max = 0.0
self.temperature_min = 35.0
self.humidity_max = 0.0
self.humidity_min = 35.0
'''
0: "undefined"
1: "normal"
2: "bottom-up",
3: "left-up",
4: "right-up",
'''
self.previous_orientation = ORIENTATION_UNDEFINED
''' TreeView '''
self.liststore = Gtk.ListStore(str, str, str, str)
self.temperature_store = self.liststore.append([ "Temperature", "0.0", "0.0", "0.0" ])
self.humidity_store = self.liststore.append([ "Humidity", "0.0", "0.0", "0.0" ])
self.accel_store = self.liststore.append([ "Accelerometer", "0.0", "0.0", "0.0" ])
self.treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Sensor", renderer_text, text=0)
self.treeview.append_column(column_text)
renderer_current = Gtk.CellRendererText()
column_cur = Gtk.TreeViewColumn("Current", renderer_current, text=1)
self.treeview.append_column(column_cur)
renderer_max = Gtk.CellRendererText()
column_max = Gtk.TreeViewColumn("Max", renderer_max, text=2)
self.treeview.append_column(column_max)
renderer_min = Gtk.CellRendererText()
column_min = Gtk.TreeViewColumn("Min", renderer_min, text=3)
self.treeview.append_column(column_min)
# Add a timer callback to update
# this takes 2 args: (how often to update in millisec, the method to run)
self.timer = GObject.timeout_add(TIME_UPATE, self.update_ui, None)
''' DrawView '''
self.drawarea = Gtk.DrawingArea()
self.drawing_area_width = screen_width
self.drawing_area_height = screen_height/2
self.drawarea.set_size_request(self.drawing_area_width, self.drawing_area_height)
self.drawarea.connect("draw", self._draw_event)
self._axis_ranges = {} # {axis_num: [min_seen, max_seen]}
self._axis_values = {} # {axis_num: deque([val0, ..., valN])}
''' spinner '''
# add scale
grid_scale_hor = Gtk.Grid()
grid_scale_hor.set_column_spacing(10)
grid_scale_hor.set_column_homogeneous(True)
self.x_adj = Gtk.Adjustment(0, -256, 256, 2, 2, 0)
self.x_scale = Gtk.Scale(orientation=Gtk.Orientation.VERTICAL)
self.x_scale.set_orientation(Gtk.Orientation.VERTICAL)
self.x_scale.set_adjustment(self.x_adj)
self.x_scale.set_digits(0)
self.x_scale.set_draw_value(True)
self.x_scale.set_vexpand(True)
grid_scale_hor.attach(self.x_scale, 0, 0, 1, 1)
self.y_adj = Gtk.Adjustment(0, -256, 256, 2, 2, 0)
self.y_scale = Gtk.Scale()
self.y_scale.set_orientation(Gtk.Orientation.VERTICAL)
self.y_scale.set_adjustment(self.y_adj)
self.y_scale.set_digits(0)
self.y_scale.set_draw_value(True)
self.y_scale.set_vexpand(True)
grid_scale_hor.attach_next_to(self.y_scale, self.x_scale, Gtk.PositionType.RIGHT, 1, 1)
self.z_adj = Gtk.Adjustment(0.0, -256.0, 256.0, 2.0, 2.0, 0.0)
self.z_scale = Gtk.Scale()
self.z_scale.set_orientation(Gtk.Orientation.VERTICAL)
self.z_scale.set_adjustment(self.z_adj)
self.z_scale.set_digits(0)
self.z_scale.set_draw_value(True)
self.z_scale.set_vexpand(True)
grid_scale_hor.attach_next_to(self.z_scale, self.y_scale, Gtk.PositionType.RIGHT, 1, 1)
self.orientation = Gtk.Label("Orientation")
#grid_scale_hor.attach_next_to(self.orientation, self.z_scale, Gtk.PositionType.RIGHT, 1, 1)
grid_scale_hor.attach(self.orientation, 0, 1, 2, 1)
''' button '''
lastbutton = Gtk.Button()
lastbutton.connect("clicked", self.destroy)
if MAKE_REAL_MESUREMENT > 0:
image_to_add = _load_image_on_button(self, "/home/root/stlogo.png", "Quit")
else:
image_to_add = _load_image_on_button(self, "./stlogo.png", "Quit")
lastbutton.add(image_to_add)
lastbutton.show()
"""
UI:
---------------------------------------------------
| | |
| DrawingArea with two graph | Treeview |
| | |
---------------------------------------------------
| | |
| Spinner for accelerometer | Button with |
| | ST image |
---------------------------------------------------
"""
box_outer = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
self.add(box_outer)
# to activate draw area
boxdraw_vert = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
boxdraw_vert.pack_start(self.drawarea, False, True, 0)
boxdraw_vert.pack_start(grid_scale_hor, True, True, 0)
box_outer.pack_start(boxdraw_vert, False, True, 0)
box_vert = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.tree_frame = Gtk.Frame(label="Temperature & Humidity")
box_vert.pack_start(self.tree_frame, True, True, 0)
self.tree_frame.add(self.treeview)
box_vert.pack_start(lastbutton, True, True, 0)
box_outer.pack_start(box_vert, True, True, 0)
def destroy(self, widget, data=None):
Gtk.main_quit()
def found_iio_device(self, data):
prefix = "/sys/bus/iio/devices/"
try:
for filefolder in os.listdir(prefix):
if os.path.exists(prefix + '/' + filefolder + '/' + data):
''' return directory which contains "data" '''
return (prefix + '/' + filefolder + '/')
except OSError:
pass
return None
def _draw_cb(self, drawingarea, ctx):
width = self.drawing_area_width
height = self.drawing_area_height
axis_ids = set(self._axis_ranges.keys())
axis_ids.intersection_update(set(self._axis_values.keys()))
for i in sorted(axis_ids):
if i == 1:
# temperature value
#draw rectangle
ctx.set_source_rgb(0.8, 0.8, 0.8)
ctx.rectangle(0, 0, width, height/2)
ctx.fill()
#draw axes
ctx.set_source_rgb(0, 1, 1)
ctx.move_to(30 + 0.5, height/4)
ctx.line_to(width - 0.5, height/4)
ctx.stroke()
# value (text)
ctx.select_font_face("sans-serif")
ctx.set_font_size(20.0)
ctx.set_source_rgb(0, 0, 0)
ctx.move_to(0, 20)
ctx.show_text("T (°C)")
ctx.set_font_size(10.0)
ctx.move_to(0, height/4 + 4)
ctx.show_text("20 °C")
# temperateure between 0 and 40
values = self._axis_values[i]
ctx.set_source_rgb(0, 0, 0)
for x, v in enumerate(values):
val = 30 + x*GRAPH_H_PADDING
ctx.move_to(val, height/2)
ctx.line_to(val, (40.0 - v) * height/80)
ctx.stroke()
if i == 2:
# Humidity values
offset = 10
#draw rectangle
ctx.set_source_rgb(0.8, 0.8, 0.8)
ctx.rectangle(0, height/2 + offset, width, height/2)
ctx.fill()
#draw axes
ctx.set_source_rgb(0, 1, 1)
ctx.move_to(25 + 0.5, height/2 + offset + height/4)
ctx.line_to(width - 0.5, height/2 + offset + height/4)
ctx.stroke()
# value (text)
ctx.select_font_face("sans-serif")
ctx.set_font_size(20.0)
ctx.set_source_rgb(0, 0, 0)
ctx.move_to(0, height/2 + offset + 20)
ctx.show_text("H (%)")
ctx.set_font_size(10.0)
ctx.set_source_rgb(0, 0, 0)
ctx.move_to(0, height/2 + offset + height/4 + 4)
ctx.show_text("50 %")
values = self._axis_values[i]
ctx.set_source_rgb(0, 0, 0)
for x, v in enumerate(values):
val = 25 + x*GRAPH_H_PADDING
ctx.move_to(val, height/2 + offset + height/2)
ctx.line_to(val, height/2 + offset + (100.0 - v) * height/200)
ctx.stroke()
return False
def _orientation_calc(self, x, y, z):
rotation = round( math.atan(x / math.sqrt(y * y + z * z)) * 180.0 * math.pi)
if abs(rotation) > 35:
''' (rotation > 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP;'''
if self.previous_orientation == ORIENTATION_LEFT_UP or self.previous_orientation == ORIENTATION_NORMAL:
if abs(rotation) < 5:
self.update_movement(self.previous_orientation)
else:
if rotation > 0:
self.update_movement(ORIENTATION_LEFT_UP)
else:
self.update_movement(ORIENTATION_RIGHT_UP)
else:
rotation = round( math.atan(y / math.sqrt(x * x + z * z)) * 180.0 * math.pi)
if abs(rotation) > 35:
'''ret = (rotation > 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL;'''
if self.previous_orientation == ORIENTATION_BOTTOM_UP or self.previous_orientation == ORIENTATION_NORMAL:
if abs(rotation) < 5:
self.update_movement(self.previous_orientation)
else:
if rotation > 0:
self.update_movement(ORIENTATION_BOTTOM_UP)
else:
self.update_movement(ORIENTATION_NORMAL)
def orientation_calc(self, x, y, z):
rotation = round( math.atan(x / math.sqrt(y * y + z * z)) * 180.0 * math.pi)
if abs(rotation) > 35:
''' (rotation > 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP;'''
if rotation > 0:
self.update_movement(ORIENTATION_LEFT_UP)
else:
self.update_movement(ORIENTATION_RIGHT_UP)
else:
rotation = round( math.atan(y / math.sqrt(x * x + z * z)) * 180.0 * math.pi)
if abs(rotation) > 35:
'''ret = (rotation > 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL;'''
if rotation > 0:
self.update_movement(ORIENTATION_BOTTOM_UP)
else:
self.update_movement(ORIENTATION_NORMAL)
def udate_temperature(self, cur_val):
self.liststore[self.temperature_store][1] = '%.2f' % cur_val
if cur_val > self.temperature_max:
self.temperature_max = cur_val
if cur_val < self.temperature_min:
self.temperature_min = cur_val
self.liststore[self.temperature_store][2] = '%.2f' % self.temperature_max
self.liststore[self.temperature_store][3] = '%.2f' % self.temperature_min
''' for drawing '''
values = self._axis_values.get(1, None)
if values is None:
values = deque(maxlen=NUM_SAMPLES)
self._axis_values[1] = values
if len(list(values)) > (NUM_SAMPLES - 1):
values. popleft()
values.append(cur_val)
self._axis_ranges[1] = (0.0, 60.0)
#print("TEMPERATURE: cur_val = %0.2f Max: %0.2f" % (cur_val, self.temperature_max))
#print(self.liststore[self.temperature_store][0:])
def udate_humidity(self, cur_val):
self.liststore[self.humidity_store][1] = '%.2f' % cur_val
if cur_val > self.humidity_max:
self.humidity_max = cur_val
if cur_val < self.humidity_min:
self.humidity_min = cur_val
self.liststore[self.humidity_store][2] = '%.2f' % self.humidity_max
self.liststore[self.humidity_store][3] = '%.2f' % self.humidity_min
''' for drawing '''
values = self._axis_values.get(2, None)
if values is None:
values = deque(maxlen=NUM_SAMPLES)
self._axis_values[2] = values
values.append(cur_val)
self._axis_ranges[2] = (0.0, 60.0)
def update_accel(self, x, y, z):
self.liststore[self.accel_store][1] = '%d' % x
self.liststore[self.accel_store][2] = '%d' % y
self.liststore[self.accel_store][3] = '%d' % z
self.x_adj.set_value(x)
self.y_adj.set_value(y)
self.z_adj.set_value(z)
def update_movement(self, m):
self.previous_orientation = m
if m == ORIENTATION_UNDEFINED:
self.orientation.set_text("undefined")
elif m == ORIENTATION_NORMAL:
self.orientation.set_text("normal")
elif m == ORIENTATION_BOTTOM_UP:
self.orientation.set_text("bottom-up")
elif m == ORIENTATION_LEFT_UP:
self.orientation.set_text("left-up")
elif m == ORIENTATION_RIGHT_UP:
self.orientation.set_text("right-up")
else:
self.orientation.set_text("undefined")
def read_temperature(self):
offset = 0.0
raw = 0.0
scale = 0.0
temp = 0.0
if MAKE_REAL_MESUREMENT > 0:
if self.temperature_prefix_path:
with open(self.temperature_prefix_path + 'in_temp_offset', 'r') as f:
offset = float(f.read())
with open(self.temperature_prefix_path + 'in_temp_raw', 'r') as f:
raw = float(f.read())
with open(self.temperature_prefix_path + 'in_temp_scale', 'r') as f:
scale = float(f.read())
temp = (offset + raw) * scale
self.udate_temperature(temp)
else:
# randomly generated
self.udate_temperature(random.uniform(18.0, 35.0))
else:
# randomly generated
self.udate_temperature(random.uniform(18.0, 35.0))
def read_humidity(self):
offset = 0.0
raw = 0.0
scale = 0.0
temp = 0.0
if MAKE_REAL_MESUREMENT > 0:
if self.humidity_prefix_path:
with open(self.humidity_prefix_path + 'in_humidityrelative_offset', 'r') as f:
offset = float(f.read())
with open(self.humidity_prefix_path + 'in_humidityrelative_raw', 'r') as f:
raw = float(f.read())
with open(self.humidity_prefix_path + 'in_humidityrelative_scale', 'r') as f:
scale = float(f.read())
temp = (offset + raw) * scale
self.udate_humidity(temp)
else:
# randomly generated
self.udate_humidity(random.uniform(18.0, 35.0))
else:
# randomly generated
self.udate_humidity(random.uniform(18.0, 35.0))
def read_accel(self):
raw = 0.0
scale = 0.0
in_x = 0.0
in_y = 0.0
in_z = 0.0
if MAKE_REAL_MESUREMENT > 0:
if self.accelerometer_prefix_path:
with open(self.accelerometer_prefix_path + 'in_accel_x_raw', 'r') as f:
scale = float(f.read())
with open(self.accelerometer_prefix_path + 'in_accel_x_scale', 'r') as f:
raw = float(f.read())
in_x = int(raw * scale * 256.0 / 9.81)
with open(self.accelerometer_prefix_path + 'in_accel_y_raw', 'r') as f:
scale = float(f.read())
with open(self.accelerometer_prefix_path + 'in_accel_y_scale', 'r') as f:
raw = float(f.read())
in_y = int(raw * scale * 256.0 / 9.81)
with open(self.accelerometer_prefix_path + 'in_accel_z_raw', 'r') as f:
scale = float(f.read())
with open(self.accelerometer_prefix_path + 'in_accel_z_scale', 'r') as f:
raw = float(f.read())
in_z = int(raw * scale * 256.0 / 9.81)
self.update_accel(in_x, in_y, in_z)
else:
in_x = random.randint(-256, 256)
in_y = random.randint(-256, 256)
in_z = random.randint(-256, 256)
self.update_accel(in_x, in_y, in_z)
else:
in_x = random.randint(-256, 256)
in_y = random.randint(-256, 256)
in_z = random.randint(-256, 256)
self.update_accel(in_x, in_y, in_z)
self.orientation_calc(in_x, in_y, in_z)
def _draw_event(self, drawingarea, user_data):
win = self.drawarea.get_window()
ctx = win.cairo_create()
self._draw_cb(win, ctx)
def update_ui(self, user_data):
self.read_temperature()
self.read_humidity()
self.read_accel()
win = self.drawarea.get_window()
ctx = win.cairo_create()
self._draw_cb(win, ctx)
# As this is a timeout function, return True so that it
# continues to get called
return True
win = SensorWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()