Skip to content

Commit

Permalink
Add function that swaps two colours.
Browse files Browse the repository at this point in the history
Swap the black and colour pixels of night weather icons.
Add `DARK_MODE` as environment variable. It swaps black and white
pixels of the final image.
Make weather text scaling and icon positioning based on display height.
Make swap colours False by defualt.
Fix 02d.png and 02n.png position for small screens.
Limit dark mode to weather mode.

Change-type: minor
Signed-off-by: Genadi Naydenov <[email protected]>
  • Loading branch information
gantonayde committed Oct 7, 2022
1 parent 6018b0c commit 8507157
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 12 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ When figuring out what size font to use, Inkyshot (invisibly) fills the screen w

If Inkyshot is living in a different house where things aren't necessarily always the same way up, use the `ROTATE` environment variable to rotate the output by 180 degrees.

### Dark mode

You can use the `DARK_MODE` environment variable if you want to eanble dark mode on the inkyshot.

### Weather

To enable the weather display, set the environment variable `MODE` to `weather`.

Next, use either `LATLONG` (e.g. 39.9199,32.8543) or `WEATHER_LOCATION` (e.g. Ankara, Turkey) environment variables to define the location for weather information. Entering only an empty `WEATHER_LOCATION` is also sufficient and in this case Inkyshot will lookup the latitude and longitude information from device's IP address.

Set `SCALE` environment variable to `F` to display the temperature values in Fahrenheit scale. The default is Celcius scale.
Set `SCALE` environment variable to `F` to display the temperature values in Fahrenheit scale. The default is Celsius scale.

Set `TEMP_THRESHOLD` environment variable to a desired temperature. All readings above this value will be displayed in colour on colour eInk screens. The default value is 25 Celsius (77 Fahrenheit).

Use the `WEATHER_FONT` variable to customize the font used in weather display mode.

Expand Down
50 changes: 39 additions & 11 deletions inkyshot/update-display.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ def create_mask(source):
mask_image.putpixel((x, y), 255)
return mask_image

def swap_two_colours(img, dark_mode=False):
"""Swap two colours.
"""
black = BLACK
if dark_mode:
target = BLACK - 1

else:
target = BLACK + 1
logging.info(f"Swapping colours {black} and {target}")
w, h = img.size
for x in range(w):
for y in range(h):
if img.getpixel((x, y)) == black:
img.putpixel((x, y), target)
elif img.getpixel((x, y)) == target:
img.putpixel((x, y), black)
return img

# Declare non pip fonts here ** Note: ttf files need to be in the /fonts dir of application repo
Grand9KPixel = "/usr/app/fonts/Grand9KPixel.ttf"

Expand All @@ -104,26 +123,31 @@ def draw_weather(weather, img, scale, fill):
# Load weather icon
icon_name = weather['symbol'].split('_')[0]
time_of_day = ''
swap_colours = False
# Couple of symbols have different icons for day and night. Check if this symbol is one of them.
if len(weather['symbol'].split('_')) > 1:
symbol_cycle = weather['symbol'].split('_')[1]
if symbol_cycle == 'day':
time_of_day = 'd'
elif symbol_cycle == 'night':
time_of_day = 'n'
swap_colours = True
icon_filename = f"{icon_map[icon_name]:02}{time_of_day}.png"
filepath = Path(__file__).parent / 'weather-icons' / icon_filename
icon_image = Image.open(filepath)
if swap_colours:
logging.info("Swapping night weather icon black and colour pixels")
icon_image = swap_two_colours(icon_image)
# Draw the weather icon
if WEATHER_INVERT and WAVESHARE:
icon_mask = create_mask(icon_image)
logging.info("Inverting Weather Icon")
icon = Image.new('1', (100, 100), 255)
icon.paste(icon_image, (0,0), icon_mask)
icon_inverted = ImageOps.invert(icon.convert('RGB'))
img.paste(icon_inverted, (120 + X_OFFSET, 3 + Y_OFFSET))
img.paste(icon_inverted, (119 + X_OFFSET, 3 + Y_OFFSET))
else:
img.paste(icon_image, (120 + X_OFFSET, 3 + Y_OFFSET))
img.paste(icon_image, (119 + X_OFFSET, 3 + Y_OFFSET))
return img

def get_current_display():
Expand Down Expand Up @@ -225,12 +249,12 @@ def set_current_display(val):
logging.error(f"Failed to set current display to {val}. Error is: {err}")

def temp_to_str(temp, scale):
"""Prepare the temperature to draw based on the defined scale: Celcius or Fahrenheit"""
"""Prepare the temperature to draw based on the defined scale: Celsius or Fahrenheit"""
if scale == 'F':
temp = celcius_to_fahrenheit(temp)
temp = celsius_to_fahrenheit(temp)
return f"{temp:.1f}"

def celcius_to_fahrenheit(temp):
def celsius_to_fahrenheit(temp):
"""Convert Celsius to Fahrenheit"""
return temp * 9/5 + 32

Expand Down Expand Up @@ -273,7 +297,7 @@ def celcius_to_fahrenheit(temp):
SCALE = 'F' if "SCALE" in os.environ and os.environ["SCALE"] == 'F' else 'C'

# Temperature threshold above which T is displayed in colour
TEMP_THRESHOLD = 25 if SCALE == 'C' else celcius_to_fahrenheit(25)
TEMP_THRESHOLD = 25 if SCALE == 'C' else celsius_to_fahrenheit(25)
if "TEMP_THRESHOLD" in os.environ:
TEMP_THRESHOLD = os.environ['TEMP_THRESHOLD']

Expand Down Expand Up @@ -315,15 +339,13 @@ def celcius_to_fahrenheit(temp):
HEIGHT = display.HEIGHT
BLACK = display.BLACK
WHITE = display.WHITE
if display.colour == "black":
COLOUR = BLACK
COLOUR = BLACK if display.colour == "black" else display.RED
if HEIGHT == 104:
# Display size: W 212 x H 104
X_OFFSET = 0
Y_OFFSET = 0
WEATHER_FONT_INCREASE = 0
else:
# Both display.RED and display.YELLOW = 2
COLOUR = display.RED
# Display size: W 250 x H 122
# text margin is 3 + 1/3*X_OFFSET = 10 pixels from left border
# weather icon is 250 - (120 + 21 + 100) = 9 pixels from right border
Expand Down Expand Up @@ -367,7 +389,7 @@ def celcius_to_fahrenheit(temp):
os.environ['LATLONG'] = f"{LAT},{LONG}"
# If weather is empty dictionary, fall back to drawing quote
if len(weather) > 0:
temperature = weather['temperature'] if SCALE == 'C' else celcius_to_fahrenheit(weather['temperature'])
temperature = weather['temperature'] if SCALE == 'C' else celsius_to_fahrenheit(weather['temperature'])
fill = COLOUR if temperature >= TEMP_THRESHOLD else BLACK
img = draw_weather(weather, img, SCALE, fill)
else:
Expand Down Expand Up @@ -444,6 +466,12 @@ def celcius_to_fahrenheit(temp):
if "ROTATE" in os.environ:
img = img.rotate(180)

# Enable dark mode
# #(it swaps the colour of the first two pixels in the palette)
if "DARK_MODE" in os.environ and target_display == 'weather':
logging.info("Switching to dark mode")
img = swap_two_colours(img, dark_mode=True)

if WAVESHARE:
# epd does not have a set_image method.
display.display(display.getbuffer(img))
Expand Down
Binary file modified inkyshot/weather-icons/02d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified inkyshot/weather-icons/02n.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8507157

Please sign in to comment.