main: add image hashing
build md5 sum over the resulting assembled image(s) and check against a stored hash file to determine if we really need to update the screen. Option can be controlled by new image_hash global option. If info_section is enabled while image_hash is on, the time of update will be stripped from the section, as it is clearly not hashable. In the end this enables us to update the information in the background way more frequent without increasing the stress caused to the display Signed-off-by: Konrad Weihmann <kweihmann@outlook.com>
This commit is contained in:
parent
8d788b06ca
commit
026b3c1da0
@ -6,7 +6,10 @@ Main class for inkycal Project
|
|||||||
Copyright by aceisace
|
Copyright by aceisace
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
@ -168,6 +171,9 @@ class Inkycal:
|
|||||||
# Path to store images
|
# Path to store images
|
||||||
self.image_folder = image_folder
|
self.image_folder = image_folder
|
||||||
|
|
||||||
|
# Remove old hashes
|
||||||
|
self._remove_hashes(self.image_folder)
|
||||||
|
|
||||||
# Give an OK message
|
# Give an OK message
|
||||||
print('loaded inkycal')
|
print('loaded inkycal')
|
||||||
|
|
||||||
@ -235,6 +241,45 @@ class Inkycal:
|
|||||||
|
|
||||||
self._assemble()
|
self._assemble()
|
||||||
|
|
||||||
|
def _image_hash(self, _in):
|
||||||
|
"""Create a md5sum of a path or a bytes stream."""
|
||||||
|
if not isinstance(_in, str):
|
||||||
|
image_bytes = _in.tobytes()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
with open(_in) as i:
|
||||||
|
return i.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
image_bytes = None
|
||||||
|
return hashlib.md5(image_bytes).hexdigest() if image_bytes else ""
|
||||||
|
|
||||||
|
def _remove_hashes(self, basepath):
|
||||||
|
for _file in glob.glob(f"{basepath}/*.hash"):
|
||||||
|
try:
|
||||||
|
os.remove(_file)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _write_image_hash(self, path, _in):
|
||||||
|
"""Write hash to a file."""
|
||||||
|
with open(path, "w") as o:
|
||||||
|
o.write(self._image_hash(_in))
|
||||||
|
|
||||||
|
def _needs_image_update(self, _list):
|
||||||
|
"""Check if any image has been updated or not.
|
||||||
|
Input a list of tuples(str, image)."""
|
||||||
|
res = False
|
||||||
|
for item in _list:
|
||||||
|
_a = self._image_hash(item[0])
|
||||||
|
_b = self._image_hash(item[1])
|
||||||
|
print("{f1}:{h1} -> {h2}".format(f1=item[0], h1=_a, h2=_b))
|
||||||
|
if _a != _b:
|
||||||
|
res = True
|
||||||
|
self._write_image_hash(item[0], item[1])
|
||||||
|
print("Refresh needed: {a}".format(a=res))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Runs main program in nonstop mode.
|
"""Runs main program in nonstop mode.
|
||||||
|
|
||||||
@ -264,7 +309,10 @@ class Inkycal:
|
|||||||
errors = [] # store module numbers in here
|
errors = [] # store module numbers in here
|
||||||
|
|
||||||
# short info for info-section
|
# short info for info-section
|
||||||
self.info = f"{current_time.format('D MMM @ HH:mm')} "
|
if not self.settings.get('image_hash', False):
|
||||||
|
self.info = f"{current_time.format('D MMM @ HH:mm')} "
|
||||||
|
else:
|
||||||
|
self.info = ""
|
||||||
|
|
||||||
for number in range(1, self._module_number):
|
for number in range(1, self._module_number):
|
||||||
|
|
||||||
@ -299,6 +347,9 @@ class Inkycal:
|
|||||||
display = self.Display
|
display = self.Display
|
||||||
|
|
||||||
self._calibration_check()
|
self._calibration_check()
|
||||||
|
if self._calibration_state:
|
||||||
|
# after calibration we have to forcefully rewrite the screen
|
||||||
|
self._remove_hashes(self.image_folder)
|
||||||
|
|
||||||
if self.supports_colour:
|
if self.supports_colour:
|
||||||
im_black = Image.open(f"{self.image_folder}canvas.png")
|
im_black = Image.open(f"{self.image_folder}canvas.png")
|
||||||
@ -310,7 +361,12 @@ class Inkycal:
|
|||||||
im_colour = upside_down(im_colour)
|
im_colour = upside_down(im_colour)
|
||||||
|
|
||||||
# render the image on the display
|
# render the image on the display
|
||||||
display.render(im_black, im_colour)
|
if not self.settings.get('image_hash', False) or self._needs_image_update([
|
||||||
|
(f"{self.image_folder}/canvas.png.hash", im_black),
|
||||||
|
(f"{self.image_folder}/canvas_colour.png.hash", im_colour)
|
||||||
|
]):
|
||||||
|
# render the image on the display
|
||||||
|
display.render(im_black, im_colour)
|
||||||
|
|
||||||
# Part for black-white ePapers
|
# Part for black-white ePapers
|
||||||
elif not self.supports_colour:
|
elif not self.supports_colour:
|
||||||
@ -321,7 +377,10 @@ class Inkycal:
|
|||||||
if self.settings['orientation'] == 180:
|
if self.settings['orientation'] == 180:
|
||||||
im_black = upside_down(im_black)
|
im_black = upside_down(im_black)
|
||||||
|
|
||||||
display.render(im_black)
|
if not self.settings.get('image_hash', False) or self._needs_image_update([
|
||||||
|
(f"{self.image_folder}/canvas.png.hash", im_black),
|
||||||
|
]):
|
||||||
|
display.render(im_black)
|
||||||
|
|
||||||
print(f'\nNo errors since {counter} display updates \n'
|
print(f'\nNo errors since {counter} display updates \n'
|
||||||
f'program started {runtime.humanize()}')
|
f'program started {runtime.humanize()}')
|
||||||
|
Loading…
Reference in New Issue
Block a user