Initial commit
This commit is contained in:
BIN
raspberry/__pycache__/datacam.cpython-32.pyc
Executable file
BIN
raspberry/__pycache__/datacam.cpython-32.pyc
Executable file
Binary file not shown.
361
raspberry/cameteo-rpi.py
Executable file
361
raspberry/cameteo-rpi.py
Executable file
@ -0,0 +1,361 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF8 -*-
|
||||
|
||||
"""datacam
|
||||
|
||||
datacam is design to take a picture with the PiCamera and collect environnemental
|
||||
data from the PiSense HAT, (almost) at the same time.
|
||||
|
||||
"""
|
||||
|
||||
#################
|
||||
# Configuration #
|
||||
#################
|
||||
|
||||
#General
|
||||
version = "v0.4"
|
||||
#time_lapse = 20 # Time between photos et data captures
|
||||
verbose = True
|
||||
|
||||
# Pictures
|
||||
ajust_time = 1 #Time waiting for the camera to ajust before taking the photo (in seconds)
|
||||
x_res = 2592 #X resolution (max = 2592)
|
||||
y_res = 1944 #Y resolution (max = 1944)
|
||||
photo_dir = "pictures" #Photo directory
|
||||
photo_file = "Test_%Y-%m-%d_%H%M%S" # Picture files name (strftime() compatible)
|
||||
photo_rotation = "180" # Image rotation in degree
|
||||
#camera_LED = True # Set to False to disable red camera LED during capture, need root privileges
|
||||
sense_LED_flash = True
|
||||
|
||||
# Data
|
||||
|
||||
#Data to collect :
|
||||
# - 'temperature_h' : temperature from humidity sensor
|
||||
# - 'temperature_p' : temperature from pressure sensor
|
||||
# - 'temperature_cpu' : temperature from CPU
|
||||
# - 'pressure' : pressure
|
||||
# - 'humidity' : relative humidity
|
||||
data_collection = ['temperature_p',
|
||||
'pressure',
|
||||
'temperature_h',
|
||||
'humidity',
|
||||
'temperature_cpu',
|
||||
'blabla',
|
||||
]
|
||||
data_display = ['pressure',
|
||||
'temperature_h',
|
||||
'humidity',
|
||||
'blabla',
|
||||
]
|
||||
data_dir = 'data'
|
||||
data_log = ['date', 'value', 'quality']
|
||||
|
||||
# Fonts
|
||||
fonts_dir = '/usr/share/fonts/truetype/freefont/'
|
||||
font_bold = 'FreeMonoBold.ttf'
|
||||
font_basic = 'FreeMono.ttf'
|
||||
font_italic = 'FreeMonoOblique.ttf'
|
||||
font_bold_italic = 'FreeMonoBoldOblique.ttf'
|
||||
font_default = font_basic
|
||||
|
||||
|
||||
#################
|
||||
# Imports #
|
||||
#################
|
||||
|
||||
from os import path, popen
|
||||
from time import sleep, strftime
|
||||
import csv
|
||||
|
||||
# Picture management with the Pi Cam
|
||||
from picamera import PiCamera
|
||||
|
||||
#Pi Sense HAT module (sensors)
|
||||
from sense_hat import SenseHat
|
||||
|
||||
# Traitement d'images
|
||||
import PIL
|
||||
from PIL import ImageFont
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
|
||||
# For picture metadata (EXIF, IPTC...)
|
||||
import piexif
|
||||
|
||||
#Divers
|
||||
from pprint import pprint
|
||||
|
||||
#########################
|
||||
# Déclarations globales #
|
||||
#########################
|
||||
|
||||
sense = SenseHat()
|
||||
data = {}
|
||||
data_dir = path.join('/home/pi/datacam', version, data_dir)
|
||||
photo_dir = path.join('/home/pi/datacam', version, photo_dir)
|
||||
|
||||
#############
|
||||
# Fonctions #
|
||||
#############
|
||||
|
||||
#Get one data from one sensors and return the value in a dict object with some metadata
|
||||
# like time/date, description, unit...
|
||||
|
||||
class Raw_Data:
|
||||
"""Data class.
|
||||
"""
|
||||
dtype = ''
|
||||
date = ''
|
||||
value = ''
|
||||
quality = -1 # -1 : default value/data type unknown, 0 : OK, 1 : non-available
|
||||
metadata = {'desc' : 'Unknow',
|
||||
'unit' : '',
|
||||
}
|
||||
|
||||
def __init__(self, data_type):
|
||||
"Initialize new data object of the defined type."
|
||||
self.dtype = data_type
|
||||
if self.dtype == 'temperature_p':
|
||||
self.metadata = {'desc' : 'Air temperature (pressure sensors)',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'Environnement/Temperature',
|
||||
}
|
||||
elif self.dtype == 'temperature_h':
|
||||
self.metadata = {'desc' : 'Air temperature (pressure sensors)',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'Environnement/Temperature',
|
||||
}
|
||||
elif self.dtype == 'pressure':
|
||||
self.metadata = {'desc' : 'Atmospheric Pressure',
|
||||
'unit' : 'mbar',
|
||||
'short' : 'Pression',
|
||||
'category' : 'Environnement/Pressure',
|
||||
}
|
||||
elif self.dtype == 'humidity':
|
||||
self.metadata = {'desc' : 'Relative air humidity',
|
||||
'unit' : '%',
|
||||
'short' : 'Humidity',
|
||||
'category' : 'Environnement/Humidity',
|
||||
}
|
||||
elif self.dtype == 'temperature_cpu':
|
||||
self.metadata = {'desc' : 'CPU temperature',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'System/Temperature',
|
||||
}
|
||||
else:
|
||||
print(data_type + " is unknown.")
|
||||
|
||||
def get_raw(self):
|
||||
"Get raw data from sensors and update information about this data."
|
||||
|
||||
self.date = strftime('%Y-%m-%d_%H:%M:%S')
|
||||
|
||||
if self.dtype == 'temperature_p':
|
||||
try:
|
||||
self.value = float(sense.get_temperature_from_pressure())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'temperature_h':
|
||||
try:
|
||||
self.value = float(sense.get_temperature_from_humidity())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'pressure':
|
||||
try:
|
||||
self.value = float(sense.get_pressure())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'humidity':
|
||||
try:
|
||||
self.value = float(sense.get_humidity())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'temperature_cpu':
|
||||
try:
|
||||
temp = popen('/opt/vc/bin/vcgencmd measure_temp').readline()
|
||||
self.value = float(temp.replace('temp=','').replace("'C\n",""))
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
else:
|
||||
print(data_type + " is unknown.")
|
||||
self.metadata.update({'desc' : 'Unknown'})
|
||||
self.value = None
|
||||
self.quality = -1
|
||||
|
||||
def write_csv(self, file_path):
|
||||
"Write data in CSV file. Creates CSV file and metadata text file if they do not exist."
|
||||
|
||||
if path.isfile(file_path):
|
||||
with open(file_path, 'a') as csvfile:
|
||||
datawriter = csv.DictWriter(csvfile, fieldnames=data_log, delimiter=';')
|
||||
datawriter.writerow({n : v for n, v in vars(data[data_type]).items() if n in data_log })
|
||||
|
||||
else:
|
||||
#Creation of metadata file
|
||||
if data[data_type]['desc'] != 'Unknown':
|
||||
with open(path.join(data_dir, data_type + '_desc.txt'), 'w') as metadata_file:
|
||||
for desc, value in data[data_type].items():
|
||||
if desc not in data_log:
|
||||
metadata_file.write(desc + " : " + str(value) + '\n')
|
||||
#Creation of data file
|
||||
with open(csvfile_path, 'w') as csvfile:
|
||||
datawriter = csv.DictWriter(csvfile, fieldnames=data_log, delimiter=';')
|
||||
datawriter.writeheader()
|
||||
datawriter.writerow({n : v for n, v in vars(data[data_type]).items() if n in data_log})
|
||||
|
||||
def __repr__(self):
|
||||
"For debug"
|
||||
if self.metadata['desc'] == 'Unknown':
|
||||
return '<Data {t:} = {d:} at {dt}>'.format(d=self.metadata['desc'],
|
||||
t=self.dtype,
|
||||
dt=self.date,
|
||||
)
|
||||
elif type(self.value) == float:
|
||||
return '<Data {d:} = {v:.1f}{u} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
elif self.value == None:
|
||||
return '<Data {d:} = {v} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
else:
|
||||
return '<Data {d:} = {v} {u} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
return
|
||||
|
||||
def __str__(self):
|
||||
"For print (to user)"
|
||||
if self.metadata['desc'] == 'Unknown':
|
||||
return '{data_type:} = {desc:}'.format(desc=self.metadata['desc'],
|
||||
data_type=self.dtype,
|
||||
)
|
||||
elif type(self.value) == float:
|
||||
return '{d:} = {v:.1f}{u}'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
)
|
||||
elif self.value == None:
|
||||
return '{d:} = {v}'.format(d=self.metadata['desc'],
|
||||
v='NA',
|
||||
)
|
||||
else:
|
||||
return '{d:} = {v} {u}'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
)
|
||||
|
||||
def __call__(self):
|
||||
return self.value
|
||||
|
||||
# Take a picture
|
||||
def get_pict():
|
||||
with PiCamera() as camera:
|
||||
camera.resolution = (x_res, y_res)
|
||||
camera.rotation = photo_rotation
|
||||
#camera.led = camera_LED # !!! need root privileges !!!
|
||||
if sense_LED_flash:
|
||||
sense.show_message(text_string="",
|
||||
back_colour=[255, 255, 255],
|
||||
)
|
||||
camera.start_preview()
|
||||
sleep(ajust_time)
|
||||
sense.set_rotation(r=180, redraw=True)
|
||||
#sense.show_message(text_string=":-)",
|
||||
#scroll_speed=0.1 ,
|
||||
#text_colour=[255, 0, 0],
|
||||
#back_colour=[0, 0, 255])
|
||||
|
||||
pict_path = path.join(photo_dir, strftime(photo_file) + '.jpg')
|
||||
camera.capture(pict_path)
|
||||
sense.clear()
|
||||
#camera.led = True # !!! need root privileges !!!
|
||||
|
||||
return pict_path
|
||||
|
||||
########
|
||||
# MAIN #
|
||||
########
|
||||
|
||||
# Collect asked data from sensors
|
||||
for data_type in data_collection:
|
||||
data[data_type] = Raw_Data(data_type)
|
||||
|
||||
data[data_type].get_raw()
|
||||
|
||||
if verbose :
|
||||
print(data[data_type].__repr__())
|
||||
print(data[data_type]())
|
||||
|
||||
#Save data in CSV file
|
||||
|
||||
csvfile_path = path.join(data_dir, data_type + '.csv')
|
||||
|
||||
data[data_type].write_csv(csvfile_path)
|
||||
|
||||
#Take a picture
|
||||
#picture_path = get_pict()
|
||||
|
||||
## Write data on picture in new picture file
|
||||
#pict = Image.open(picture_path)
|
||||
|
||||
#draw = ImageDraw.Draw(pict)
|
||||
## Text line height (=font size) and line space calculation
|
||||
#line_height = int(y_res / 40)
|
||||
#line_space = int(line_height / 10)
|
||||
|
||||
#text = ''
|
||||
#l = line_space
|
||||
|
||||
## Add a line with data for each data to display
|
||||
#for d in data_display:
|
||||
#text = str(data[d]) #.__str__()
|
||||
## Select color and font to match data quality
|
||||
#if data[d].quality == 0:
|
||||
#text_color = (0, 255, 0) # Quality OK : text in green
|
||||
#font = font_default
|
||||
#elif data[d].quality < 0:
|
||||
#text_color = (100, 100, 100) # Unknown in grey
|
||||
#font = font_italic
|
||||
#elif data[d].quality == 1:
|
||||
#text_color = (255, 255, 0) # Sensor unavailable : yellow
|
||||
#font = font_italic
|
||||
#else:
|
||||
#text_color = (255, 0, 0) # Other = error in red
|
||||
#font = font_bold
|
||||
|
||||
#img_font = ImageFont.truetype(path.join(fonts_dir, font), line_height)
|
||||
#draw.text((5,l), text, text_color, img_font)
|
||||
#draw = ImageDraw.Draw(pict)
|
||||
#l = l + line_height + line_space
|
||||
|
||||
##Get EXIF metadata and delete embedded thumbnail
|
||||
#pict_exif = piexif.load(pict.info['exif'])
|
||||
#del(pict_exif['thumbnail'])
|
||||
|
||||
#pict.save(picture_path, 'jpeg', exif=piexif.dump(pict_exif) )
|
||||
|
||||
#if verbose :
|
||||
#print('Picture = ' + picture_path)
|
||||
|
362
raspberry/datacam.py
Executable file
362
raspberry/datacam.py
Executable file
@ -0,0 +1,362 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF8 -*-
|
||||
|
||||
"""datacam
|
||||
v0.3
|
||||
|
||||
datacam is design to take a picture with the PiCamera and collect environnemental
|
||||
data from the PiSense HAT, (almost) at the same time.
|
||||
|
||||
"""
|
||||
|
||||
#################
|
||||
# Configuration #
|
||||
#################
|
||||
|
||||
#General
|
||||
version = "v0.3"
|
||||
#time_lapse = 20 # Time between photos et data captures
|
||||
verbose = True
|
||||
|
||||
# Pictures
|
||||
ajust_time = 1 #Time waiting for the camera to ajust before taking the photo (in seconds)
|
||||
x_res = 2592 #X resolution (max = 2592)
|
||||
y_res = 1944 #Y resolution (max = 1944)
|
||||
photo_dir = "pictures" #Photo directory
|
||||
photo_file = "Test_%Y-%m-%d_%H%M%S" # Picture files name (strftime() compatible)
|
||||
photo_rotation = "180" # Image rotation in degree
|
||||
#camera_LED = True # Set to False to disable red camera LED during capture, need root privileges
|
||||
sense_LED_flash = True
|
||||
|
||||
# Data
|
||||
|
||||
#Data to collect :
|
||||
# - 'temperature_h' : temperature from humidity sensor
|
||||
# - 'temperature_p' : temperature from pressure sensor
|
||||
# - 'temperature_cpu' : temperature from CPU
|
||||
# - 'pressure' : pressure
|
||||
# - 'humidity' : relative humidity
|
||||
data_collection = ['temperature_p',
|
||||
'pressure',
|
||||
'temperature_h',
|
||||
'humidity',
|
||||
'temperature_cpu',
|
||||
'blabla',
|
||||
]
|
||||
data_display = ['pressure',
|
||||
'temperature_h',
|
||||
'humidity',
|
||||
'blabla',
|
||||
]
|
||||
data_dir = 'data'
|
||||
data_log = ['date', 'value', 'quality']
|
||||
|
||||
# Fonts
|
||||
fonts_dir = '/usr/share/fonts/truetype/freefont/'
|
||||
font_bold = 'FreeMonoBold.ttf'
|
||||
font_basic = 'FreeMono.ttf'
|
||||
font_italic = 'FreeMonoOblique.ttf'
|
||||
font_bold_italic = 'FreeMonoBoldOblique.ttf'
|
||||
font_default = font_basic
|
||||
|
||||
|
||||
#################
|
||||
# Imports #
|
||||
#################
|
||||
|
||||
from os import path, popen
|
||||
from time import sleep, strftime
|
||||
import csv
|
||||
|
||||
# Picture management with the Pi Cam
|
||||
from picamera import PiCamera
|
||||
|
||||
#Pi Sense HAT module (sensors)
|
||||
from sense_hat import SenseHat
|
||||
|
||||
# Traitement d'images
|
||||
import PIL
|
||||
from PIL import ImageFont
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
|
||||
# For picture metadata (EXIF, IPTC...)
|
||||
import piexif
|
||||
|
||||
#Divers
|
||||
from pprint import pprint
|
||||
|
||||
#########################
|
||||
# Déclarations globales #
|
||||
#########################
|
||||
|
||||
sense = SenseHat()
|
||||
data = {}
|
||||
data_dir = path.join('/home/pi/datacam', version, data_dir)
|
||||
photo_dir = path.join('/home/pi/datacam', version, photo_dir)
|
||||
|
||||
#############
|
||||
# Fonctions #
|
||||
#############
|
||||
|
||||
#Get one data from one sensors and return the value in a dict object with some metadata
|
||||
# like time/date, description, unit...
|
||||
|
||||
class Raw_Data:
|
||||
"""Data class.
|
||||
"""
|
||||
dtype = ''
|
||||
date = ''
|
||||
value = ''
|
||||
quality = -1 # -1 : default value/data type unknown, 0 : OK, 1 : non-available
|
||||
metadata = {'desc' : 'Unknow',
|
||||
'unit' : '',
|
||||
}
|
||||
|
||||
def __init__(self, data_type):
|
||||
"Initialize new data object of the defined type."
|
||||
self.dtype = data_type
|
||||
if self.dtype == 'temperature_p':
|
||||
self.metadata = {'desc' : 'Air temperature (pressure sensors)',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'Environnement/Temperature',
|
||||
}
|
||||
elif self.dtype == 'temperature_h':
|
||||
self.metadata = {'desc' : 'Air temperature (pressure sensors)',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'Environnement/Temperature',
|
||||
}
|
||||
elif self.dtype == 'pressure':
|
||||
self.metadata = {'desc' : 'Atmospheric Pressure',
|
||||
'unit' : 'mbar',
|
||||
'short' : 'Pression',
|
||||
'category' : 'Environnement/Pressure',
|
||||
}
|
||||
elif self.dtype == 'humidity':
|
||||
self.metadata = {'desc' : 'Relative air humidity',
|
||||
'unit' : '%',
|
||||
'short' : 'Humidity',
|
||||
'category' : 'Environnement/Humidity',
|
||||
}
|
||||
elif self.dtype == 'temperature_cpu':
|
||||
self.metadata = {'desc' : 'CPU temperature',
|
||||
'unit' : '°C',
|
||||
'short' : 'Temperature',
|
||||
'category' : 'System/Temperature',
|
||||
}
|
||||
else:
|
||||
print(data_type + " is unknown.")
|
||||
|
||||
def get_raw(self):
|
||||
"Get raw data from sensors and update information about this data."
|
||||
|
||||
self.date = strftime('%Y-%m-%d_%H:%M:%S')
|
||||
|
||||
if self.dtype == 'temperature_p':
|
||||
try:
|
||||
self.value = float(sense.get_temperature_from_pressure())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'temperature_h':
|
||||
try:
|
||||
self.value = float(sense.get_temperature_from_humidity())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'pressure':
|
||||
try:
|
||||
self.value = float(sense.get_pressure())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'humidity':
|
||||
try:
|
||||
self.value = float(sense.get_humidity())
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
elif self.dtype == 'temperature_cpu':
|
||||
try:
|
||||
temp = popen('/opt/vc/bin/vcgencmd measure_temp').readline()
|
||||
self.value = float(temp.replace('temp=','').replace("'C\n",""))
|
||||
self.quality = 0
|
||||
except:
|
||||
self.value = None
|
||||
self.quality = 1
|
||||
else:
|
||||
print(data_type + " is unknown.")
|
||||
self.metadata.update({'desc' : 'Unknown'})
|
||||
self.value = None
|
||||
self.quality = -1
|
||||
|
||||
def write_csv(self, file_path):
|
||||
"Write data in CSV file. Creates CSV file and metadata text file if they do not exist."
|
||||
|
||||
if path.isfile(file_path):
|
||||
with open(file_path, 'a') as csvfile:
|
||||
datawriter = csv.DictWriter(csvfile, fieldnames=data_log, delimiter=';')
|
||||
datawriter.writerow({n : v for n, v in vars(data[data_type]).items() if n in data_log })
|
||||
|
||||
else:
|
||||
#Creation of metadata file
|
||||
if data[data_type]['desc'] != 'Unknown':
|
||||
with open(path.join(data_dir, data_type + '_desc.txt'), 'w') as metadata_file:
|
||||
for desc, value in data[data_type].items():
|
||||
if desc not in data_log:
|
||||
metadata_file.write(desc + " : " + str(value) + '\n')
|
||||
#Creation of data file
|
||||
with open(csvfile_path, 'w') as csvfile:
|
||||
datawriter = csv.DictWriter(csvfile, fieldnames=data_log, delimiter=';')
|
||||
datawriter.writeheader()
|
||||
datawriter.writerow({n : v for n, v in vars(data[data_type]).items() if n in data_log})
|
||||
|
||||
def __repr__(self):
|
||||
"For debug"
|
||||
if self.metadata['desc'] == 'Unknown':
|
||||
return '<Data {t:} = {d:} at {dt}>'.format(d=self.metadata['desc'],
|
||||
t=self.dtype,
|
||||
dt=self.date,
|
||||
)
|
||||
elif type(self.value) == float:
|
||||
return '<Data {d:} = {v:.1f}{u} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
elif self.value == None:
|
||||
return '<Data {d:} = {v} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
else:
|
||||
return '<Data {d:} = {v} {u} ({q}) at {dt}>'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
q=self.quality,
|
||||
dt=self.date,
|
||||
)
|
||||
return
|
||||
|
||||
def __str__(self):
|
||||
"For print (to user)"
|
||||
if self.metadata['desc'] == 'Unknown':
|
||||
return '{data_type:} = {desc:}'.format(desc=self.metadata['desc'],
|
||||
data_type=self.dtype,
|
||||
)
|
||||
elif type(self.value) == float:
|
||||
return '{d:} = {v:.1f}{u}'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
)
|
||||
elif self.value == None:
|
||||
return '{d:} = {v}'.format(d=self.metadata['desc'],
|
||||
v='NA',
|
||||
)
|
||||
else:
|
||||
return '{d:} = {v} {u}'.format(d=self.metadata['desc'],
|
||||
v=self.value,
|
||||
u=self.metadata['unit'],
|
||||
)
|
||||
|
||||
def __call__(self):
|
||||
return self.value
|
||||
|
||||
# Take a picture
|
||||
def get_pict():
|
||||
with PiCamera() as camera:
|
||||
camera.resolution = (x_res, y_res)
|
||||
camera.rotation = photo_rotation
|
||||
#camera.led = camera_LED # !!! need root privileges !!!
|
||||
if sense_LED_flash:
|
||||
sense.show_message(text_string="",
|
||||
back_colour=[255, 255, 255],
|
||||
)
|
||||
camera.start_preview()
|
||||
sleep(ajust_time)
|
||||
sense.set_rotation(r=180, redraw=True)
|
||||
#sense.show_message(text_string=":-)",
|
||||
#scroll_speed=0.1 ,
|
||||
#text_colour=[255, 0, 0],
|
||||
#back_colour=[0, 0, 255])
|
||||
|
||||
pict_path = path.join(photo_dir, strftime(photo_file) + '.jpg')
|
||||
camera.capture(pict_path)
|
||||
sense.clear()
|
||||
#camera.led = True # !!! need root privileges !!!
|
||||
|
||||
return pict_path
|
||||
|
||||
########
|
||||
# MAIN #
|
||||
########
|
||||
|
||||
# Collect asked data from sensors
|
||||
for data_type in data_collection:
|
||||
data[data_type] = Raw_Data(data_type)
|
||||
|
||||
data[data_type].get_raw()
|
||||
|
||||
if verbose :
|
||||
print(data[data_type].__repr__())
|
||||
print(data[data_type]())
|
||||
|
||||
#Save data in CSV file
|
||||
|
||||
csvfile_path = path.join(data_dir, data_type + '.csv')
|
||||
|
||||
data[data_type].write_csv(csvfile_path)
|
||||
|
||||
#Take a picture
|
||||
picture_path = get_pict()
|
||||
|
||||
# Write data on picture in new picture file
|
||||
pict = Image.open(picture_path)
|
||||
|
||||
draw = ImageDraw.Draw(pict)
|
||||
# Text line height (=font size) and line space calculation
|
||||
line_height = int(y_res / 40)
|
||||
line_space = int(line_height / 10)
|
||||
|
||||
text = ''
|
||||
l = line_space
|
||||
|
||||
# Add a line with data for each data to display
|
||||
for d in data_display:
|
||||
text = str(data[d]) #.__str__()
|
||||
# Select color and font to match data quality
|
||||
if data[d].quality == 0:
|
||||
text_color = (0, 255, 0) # Quality OK : text in green
|
||||
font = font_default
|
||||
elif data[d].quality < 0:
|
||||
text_color = (100, 100, 100) # Unknown in grey
|
||||
font = font_italic
|
||||
elif data[d].quality == 1:
|
||||
text_color = (255, 255, 0) # Sensor unavailable : yellow
|
||||
font = font_italic
|
||||
else:
|
||||
text_color = (255, 0, 0) # Other = error in red
|
||||
font = font_bold
|
||||
|
||||
img_font = ImageFont.truetype(path.join(fonts_dir, font), line_height)
|
||||
draw.text((5,l), text, text_color, img_font)
|
||||
draw = ImageDraw.Draw(pict)
|
||||
l = l + line_height + line_space
|
||||
|
||||
#Get EXIF metadata and delete embedded thumbnail
|
||||
pict_exif = piexif.load(pict.info['exif'])
|
||||
del(pict_exif['thumbnail'])
|
||||
|
||||
pict.save(picture_path, 'jpeg', exif=piexif.dump(pict_exif) )
|
||||
|
||||
if verbose :
|
||||
print('Picture = ' + picture_path)
|
||||
|
5
raspberry/pi_dev_sync.sh
Executable file
5
raspberry/pi_dev_sync.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
#Synchronise le répertoire de développement de datacam vers aro-W840
|
||||
|
||||
rsync --archive --compress --delete --verbose -e ssh pi@aro-pi:~/datacam/* ~/Dev/Python/datacam/
|
69
raspberry/serial_module.py
Executable file
69
raspberry/serial_module.py
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF8 -*-
|
||||
|
||||
# Reception de données depuis un arduino via port série
|
||||
|
||||
version = "0.1"
|
||||
|
||||
#Configuration du port série
|
||||
port_serie = "/dev/ttyACM1"
|
||||
#port_serie_alt = "/dev/ttyACM1"
|
||||
|
||||
baud_rate = 115200
|
||||
|
||||
#############
|
||||
import serial
|
||||
from pprint import pprint
|
||||
|
||||
str_line = [] #une ligne de donnée lue sur le port série et prétraitée
|
||||
data = dict() #une donnée d'un capteur
|
||||
data_package = dict() #un paquet de donnée à un moment
|
||||
data_set = dict() #ensemble des paquets de données
|
||||
|
||||
with serial.Serial(port_serie, baud_rate) as comm: #, timeout = 0
|
||||
|
||||
print("Initialization du microcontroleur en cours...")
|
||||
|
||||
while True:
|
||||
line = comm.readline()
|
||||
if line == b'###Init_end###\r\n' :
|
||||
break
|
||||
else:
|
||||
print(".")
|
||||
|
||||
while True:
|
||||
line = comm.readline()
|
||||
if line == b'###Data_start###\r\n' :
|
||||
break
|
||||
else:
|
||||
print("En attente d'un nouveau paquet de données...")
|
||||
|
||||
while True:
|
||||
line = comm.readline()
|
||||
if line == b'###Data_start###\r\n' :
|
||||
print("Nouveau paquet de données !")
|
||||
#break
|
||||
elif line == b'###Data_end###\r\n' :
|
||||
print("Fin du paquet de données !")
|
||||
else:
|
||||
#Nettoyage des caractères spéciaux inutile (retour chariot...) et
|
||||
# conversion en liste de chaînes de caractères
|
||||
str_line = line.decode("ascii").strip().split('\t')
|
||||
#Mise en tableau de données
|
||||
data['type'] = str_line[0].strip()
|
||||
data['sensor'] = str_line[1].strip()
|
||||
data['value'] = str_line[2].strip()
|
||||
if len(str_line) > 3 and str_line[3].strip() != "-":
|
||||
data['unit'] = str_line[3].strip()
|
||||
else:
|
||||
data['unit'] = None
|
||||
|
||||
if len(str_line) > 4:
|
||||
data['comment'] = str_line[4]
|
||||
else:
|
||||
data['comment'] = None
|
||||
|
||||
data_package[data['type'] + "_" + data['sensor']] = data
|
||||
data = {}
|
||||
|
||||
pprint(data_package)
|
Reference in New Issue
Block a user