Learning how to use an E-Ink display, and GeoPy, Open-Meteo python libraries.
I’ve recently been using a Waveshare 2.3″ E-Ink display hat for various Raspberry Pi hardware. There are a number of projects out there that use this cute little display, and I would like the throw some of my code into the arena. To help learn python and the E-ink display, I’ve created a little weather app.
All the code is posted to my Github Repository. This code is a work in progress, and basically just a test piece, there really no error control.
I’m assuming that you have your Waveshare 2.13in E-Ink display correcly setup with your hardware. I’m using Waveshare 2.13in E-Ink display HAT V4 connected to a Raspberry Pi Zero 2W. If you haven’t set it up yet, visit https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_Manual and follow the directions for your hardware.
This next step is for use with Raspberry Pi hardware.
Install the necessary python libraries:
sudo apt update
sudo apt install python3-pip
sudo apt install python3-pil
sudo apt install python3-numpy
sudo apt install python3-gpiozero
sudo pip3 install spidevFor WeatherInk.py, GeoPy and Open-Meteo libraries are needed:
pip install openmeteo-requests
pip install requests-cache retry-requests numpy pandas
pip install geopyWeatherInk.py takes Latitude and Longitude coordinates and returns weather information, and displays it on an E-Ink display. I wrote this as an exercise to use an E-Ink display, and get weather info. The GPS function was a bonus. There are still issues with the code, throws an error when trying to convert GPS coordinates to a place without name, etc. Use at your own risk. Weather icons and font.ttc must be downloaded from my github
weatherink.py:
# /*****************************************************************************
# * | File : weatherink.py
# * | Author : Michael Bapst (lynxsilver@gmail.com)
# * | Function : Retrieves Weather from Open-Meteo and Displays it on a
# * | : Waveshare 2.13in E-Ink Display
# * | Info : I wrote this as an exercise to use an E-Ink display, and
# * | : get weather info. The GPS function was a bonus.
# * | : There are still issues with the code, throws an error when
# * | : trying to convert GPS coordinates to a place without name,
# * | : etc.
# *----------------
# * | This version: V1.0
# * | Date : 1/18/2025
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#*****************************************************************************
# The following libraries need to be installed:
# Install Open Meteo:
# pip install openmeteo-requests
# pip install requests-cache retry-requests numpy pandas
#
# Install geopy
# pip install geopy
import sys
import os
import logging
import epd2in13_V4
import time
from PIL import Image,ImageDraw,ImageFont
import traceback
import openmeteo_requests
from convertweather import convertUnixTime, RoundTemp, RoundWindSpeed, HeadingToCompass, DecodeWeatherCode, SecToHours, GetCity
import requests_cache
import pandas as pd
from retry_requests import retry
# Setup the Open-Meteo API client with cache and retry on error
cache_session = requests_cache.CachedSession('.cache', expire_after = 3600)
retry_session = retry(cache_session, retries = 5, backoff_factor = 0.2)
openmeteo = openmeteo_requests.Client(session = retry_session)
# For more information about Open-Meteo goto https://open-meteo.com/en/docs
# Make sure all required weather variables are listed here
# The order of variables in hourly or daily is important to assign them correctly below
# Change the Lat & Lon to the area you want weather info from. use https://open-meteo.com/en/docs to get your Lat & Lon
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": 64.1355,
"longitude": -21.8954,
"current": ["temperature_2m", "relative_humidity_2m", "weather_code", "wind_speed_10m", "wind_direction_10m", "wind_gusts_10m"],
"daily": ["weather_code", "temperature_2m_max", "temperature_2m_min", "sunrise", "sunset", "daylight_duration", "sunshine_duration", "uv_index_max"],
"temperature_unit": "fahrenheit",
"wind_speed_unit": "mph",
"precipitation_unit": "inch",
"timezone": "America/New_York",
"forecast_days": 1
}
responses = openmeteo.weather_api(url, params=params)
# Process first location. Add a for-loop for multiple locations or weather models
response = responses[0]
wAddress = GetCity(response.Latitude(), response.Longitude())
# Current values. The order of variables needs to be the same as requested.
current = response.Current()
wTemp = round(current.Variables(0).Value(), 1)
wHumid = current.Variables(1).Value()
wWeatherCode, wIcon = DecodeWeatherCode(current.Variables(2).Value())
wWindSpd = round(current.Variables(3).Value(), 2)
wWindDir = HeadingToCompass(current.Variables(4).Value())
wWindGust = round(current.Variables(5).Value(), 2)
wDateTime = convertUnixTime(current.Time())
# Process daily data. The order of variables needs to be the same as requested.
daily = response.Daily()
wTempHi = RoundTemp(daily.Variables(1).ValuesAsNumpy())
wTempLo = RoundTemp(daily.Variables(2).ValuesAsNumpy())
wUVIndex = daily.Variables(7).ValuesAsNumpy()
#Setup WaveShare 2.13 V4
epd = epd2in13_V4.EPD()
epd.init()
#epd.Clear(0xFF)
# Drawing on the image
fontObj = ImageFont.truetype('font.ttc', 10)
wImage = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(wImage)
draw.text((0, 0), wAddress, font = fontObj, fill = 0)
draw.line([(0,13),(250,13)], fill = 0,width = 1)
draw.text((250, 0), wDateTime, font = fontObj, fill = 0, anchor = "ra")
draw.text((0, 15), "Temp: " + str(wTemp) + " : HI/LO: " + str(wTempHi) + "/" + str(wTempLo), font = fontObj, fill = 0)
draw.text((0, 30), "Humidity: " + str(wHumid), font = fontObj, fill = 0)
draw.text((250, 30), "UVIndex: " + str(wUVIndex), font = fontObj, fill = 0, anchor = "ra")
draw.text((1, 45), "Weather: " + wWeatherCode, font = fontObj, fill = 0) #Setting the position to 2 keeps the W in weather from getting cut off
draw.text((1, 60), "Wind Speed: " + str(wWindSpd), font = fontObj, fill = 0)
draw.text((1, 75), "Wind Direction: " + str(wWindDir), font = fontObj, fill = 0)
draw.text((1, 90), "Wind Gusts: " + str(wWindGust), font = fontObj, fill = 0)
bmpIcon = Image.open(os.path.join(os.path.dirname(__file__), wIcon))
wImage.paste(bmpIcon,(185,57))
wImage = wImage.rotate(180) # rotate
epd.display(epd.getbuffer(wImage))
# Exit
epd.init()
epd.sleep()
epd2in13_V4.epdconfig.module_exit(cleanup=True)
exit()convertweather.py
# /*****************************************************************************
# * | File : convertweather.py
# * | Author : Michael Bapst (lynxsilver@gmail.com)
# * | Function : Various conversion functions used by Weather Ink python app
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 1/18/2025
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#*****************************************************************************
#
# Install geopy : pip install geopy
#
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderServiceError
from datetime import datetime
import numpy as np
def GetCity(Lat, Lon):
geolocator = Nominatim(user_agent="E-Ink_Weather_App")
try:
location = geolocator.reverse(str(Lat) + "," + str(Lon))
address = location.raw['address']
# Traverse the data
city = address.get('city', '')
state = address.get('state', '')
code = address.get('country_code')
addrss = city + ", " + state + ", " + code.upper()
return addrss
except GeocoderServiceError as e:
print("Error: ", e)
return "ERROR"
def convertUnixTime(UnixTime):
# Convert UNIX time to Modern
return datetime.utcfromtimestamp(UnixTime).strftime('%a, %b %-d, %Y %-I:%-M:%-S %p')
def RoundTemp(Temperature):
# Cleanup temperature
return np.round(Temperature, 1)
def RoundWindSpeed(WindSpeed):
# Cleanup Wind Speed
return np.round(WindSpeed, 2)
def HeadingToCompass(Heading):
# Convert Heading to Compass points (N-NE-E-SE-S-SW-W-NW)
# Converts a heading in degrees to a compass direction.
directions = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"]
index = round(Heading / 22.5) % 16
return directions[index]
def DecodeWeatherCode(WeatherCode):
match WeatherCode:
case 0:
return "Clear Sky", "icon/wmo_icon_00d.bmp"
case 1:
return "Mainly Clear", "icon/wmo_icon_01d.bmp"
case 2:
return "Partly Cloudy", "icon/wmo_icon_02d.bmp"
case 3:
return "Overcast", "icon/wmo_icon_03d.bmp"
case 45:
return "Fog", "icon/wmo_icon_45d.bmp"
case 48:
return "Freezing Fog", "icon/wmo_icon_45d.bmp"
case 51:
return "Light Drizzle", "icon/wmo_icon_53d.bmp"
case 53:
return "Moderate Drizzle", "icon/wmo_icon_53d.bmp"
case 55:
return "Heavy Drizzle", "icon/wmo_icon_53d.bmp"
case 56:
return "Light Freezing Drizzle", "icon/wmo_icon_57d.bmp"
case 57:
return "Heavy Freezing Drizzle", "icon/wmo_icon_57d.bmp"
case 61:
return "Light Rain", "icon/wmo_icon_61d.bmp"
case 63:
return "Moderate Rain", "icon/wmo_icon_61d.bmp"
case 65:
return "Heavy Rain", "icon/wmo_icon_65d.bmp"
case 66:
return "Light Freezing Rain", "icon/wmo_icon_66d.bmp"
case 67:
return "Heavy Freezing Rain", "icon/wmo_icon_67d.bmp"
case 71:
return "Light Snow", "icon/wmo_icon_71d.bmp"
case 73:
return "Moderate Snow", "icon/wmo_icon_73d.bmp"
case 75:
return "Heavy Snow", "icon/wmo_icon_75d.bmp"
case 77:
return "Snow Pellets", "icon/wmo_icon_75d.bmp"
case 80:
return "Light Rain Showers", "icon/wmo_icon_80d.bmp"
case 81:
return "Moderate Rain Showers", "icon/wmo_icon_81d.bmp"
case 82:
return "Heavy Rain Showers", "icon/wmo_icon_81d.bmp"
case 85:
return "Light Snow Showers", "icon/wmo_icon_85d.bmp"
case 86:
return "Heavy Snow Showers", "icon/wmo_icon_86d.bmp"
case 95:
return "Thunderstorms", "icon/wmo_icon_95d.bmp"
case 96:
return "Thunderstorms with Light Hail", "icon/wmo_icon_96d.bmp"
case 99:
return "Thunderstorms with Heavy Hail", "icon/wmo_icon_96d.bmp"
case _:
return "Invalid Weather Code", "icon/wmo_icon_err.bmp"
def SecToHours(seconds):
numHr = np.round(int(seconds/3600), 0)
numMin = np.round(int((seconds%3600)/60), 0)
numSec = np.round(int((seconds%3600)%60), 0)
#strHr = ["{:0f} hrs {:0f} mins {:0f} secs".format(float(numHr), float(numMin), float(numSec))]
strHr = ["{} hrs {} mins {} secs".format(numHr, numMin, numSec)]
return strHrepdconfig.py
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.2
# * | Date : 2022-10-29
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import os
import logging
import sys
import time
import subprocess
from ctypes import *
logger = logging.getLogger(__name__)
class RaspberryPi:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
MOSI_PIN = 10
SCLK_PIN = 11
def __init__(self):
import spidev
import gpiozero
self.SPI = spidev.SpiDev()
self.GPIO_RST_PIN = gpiozero.LED(self.RST_PIN)
self.GPIO_DC_PIN = gpiozero.LED(self.DC_PIN)
# self.GPIO_CS_PIN = gpiozero.LED(self.CS_PIN)
self.GPIO_PWR_PIN = gpiozero.LED(self.PWR_PIN)
self.GPIO_BUSY_PIN = gpiozero.Button(self.BUSY_PIN, pull_up = False)
def digital_write(self, pin, value):
if pin == self.RST_PIN:
if value:
self.GPIO_RST_PIN.on()
else:
self.GPIO_RST_PIN.off()
elif pin == self.DC_PIN:
if value:
self.GPIO_DC_PIN.on()
else:
self.GPIO_DC_PIN.off()
# elif pin == self.CS_PIN:
# if value:
# self.GPIO_CS_PIN.on()
# else:
# self.GPIO_CS_PIN.off()
elif pin == self.PWR_PIN:
if value:
self.GPIO_PWR_PIN.on()
else:
self.GPIO_PWR_PIN.off()
def digital_read(self, pin):
if pin == self.BUSY_PIN:
return self.GPIO_BUSY_PIN.value
elif pin == self.RST_PIN:
return self.RST_PIN.value
elif pin == self.DC_PIN:
return self.DC_PIN.value
# elif pin == self.CS_PIN:
# return self.CS_PIN.value
elif pin == self.PWR_PIN:
return self.PWR_PIN.value
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def spi_writebyte2(self, data):
self.SPI.writebytes2(data)
def DEV_SPI_write(self, data):
self.DEV_SPI.DEV_SPI_SendData(data)
def DEV_SPI_nwrite(self, data):
self.DEV_SPI.DEV_SPI_SendnData(data)
def DEV_SPI_read(self):
return self.DEV_SPI.DEV_SPI_ReadData()
def module_init(self, cleanup=False):
self.GPIO_PWR_PIN.on()
if cleanup:
find_dirs = [
os.path.dirname(os.path.realpath(__file__)),
'/usr/local/lib',
'/usr/lib',
]
self.DEV_SPI = None
for find_dir in find_dirs:
val = int(os.popen('getconf LONG_BIT').read())
logging.debug("System is %d bit"%val)
if val == 64:
so_filename = os.path.join(find_dir, 'DEV_Config_64.so')
else:
so_filename = os.path.join(find_dir, 'DEV_Config_32.so')
if os.path.exists(so_filename):
self.DEV_SPI = CDLL(so_filename)
break
if self.DEV_SPI is None:
RuntimeError('Cannot find DEV_Config.so')
self.DEV_SPI.DEV_Module_Init()
else:
# SPI device, bus = 0, device = 0
self.SPI.open(0, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self, cleanup=False):
logger.debug("spi end")
self.SPI.close()
self.GPIO_RST_PIN.off()
self.GPIO_DC_PIN.off()
self.GPIO_PWR_PIN.off()
logger.debug("close 5V, Module enters 0 power consumption ...")
if cleanup:
self.GPIO_RST_PIN.close()
self.GPIO_DC_PIN.close()
# self.GPIO_CS_PIN.close()
self.GPIO_PWR_PIN.close()
self.GPIO_BUSY_PIN.close()
class JetsonNano:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
def __init__(self):
import ctypes
find_dirs = [
os.path.dirname(os.path.realpath(__file__)),
'/usr/local/lib',
'/usr/lib',
]
self.SPI = None
for find_dir in find_dirs:
so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')
if os.path.exists(so_filename):
self.SPI = ctypes.cdll.LoadLibrary(so_filename)
break
if self.SPI is None:
raise RuntimeError('Cannot find sysfs_software_spi.so')
import Jetson.GPIO
self.GPIO = Jetson.GPIO
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(self.BUSY_PIN)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.SYSFS_software_spi_transfer(data[0])
def spi_writebyte2(self, data):
for i in range(len(data)):
self.SPI.SYSFS_software_spi_transfer(data[i])
def module_init(self):
self.GPIO.setmode(self.GPIO.BCM)
self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
self.SPI.SYSFS_software_spi_begin()
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.SYSFS_software_spi_end()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
class SunriseX3:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
Flag = 0
def __init__(self):
import spidev
import Hobot.GPIO
self.GPIO = Hobot.GPIO
self.SPI = spidev.SpiDev()
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(pin)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def spi_writebyte2(self, data):
# for i in range(len(data)):
# self.SPI.writebytes([data[i]])
self.SPI.xfer3(data)
def module_init(self):
if self.Flag == 0:
self.Flag = 1
self.GPIO.setmode(self.GPIO.BCM)
self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
# SPI device, bus = 0, device = 0
self.SPI.open(2, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
else:
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.close()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.Flag = 0
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN], self.PWR_PIN)
if sys.version_info[0] == 2:
process = subprocess.Popen("cat /proc/cpuinfo | grep Raspberry", shell=True, stdout=subprocess.PIPE)
else:
process = subprocess.Popen("cat /proc/cpuinfo | grep Raspberry", shell=True, stdout=subprocess.PIPE, text=True)
output, _ = process.communicate()
if sys.version_info[0] == 2:
output = output.decode(sys.stdout.encoding)
if "Raspberry" in output:
implementation = RaspberryPi()
elif os.path.exists('/sys/bus/platform/drivers/gpio-x3'):
implementation = SunriseX3()
else:
implementation = JetsonNano()
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###epd2in13_V4.py
# *****************************************************************************
# * | File : epd2in13_V4.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2023-06-25
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
# from . import epdconfig
import epdconfig
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
'''
function :send data
parameter:
data : Write data
'''
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
# send a lot of data
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte2(data)
epdconfig.digital_write(self.cs_pin, 1)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xf7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Fast
parameter:
'''
def TurnOnDisplay_Fast(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xff) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x01) #Driver output control
self.send_data(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
return 0
'''
function : Initialize the e-Paper fast register
parameter:
'''
def init_fast(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x18) # Read built-in temperature sensor
self.send_command(0x80)
self.send_command(0x11) # data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x22) # Load temperature value
self.send_data(0xB1)
self.send_command(0x20)
self.ReadBusy()
self.send_command(0x1A) # Write to temperature register
self.send_data(0x64)
self.send_data(0x00)
self.send_command(0x22) # Load temperature value
self.send_data(0x91)
self.send_command(0x20)
self.ReadBusy()
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(90, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
def display(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Sends the image buffer in RAM to e-Paper and fast displays
parameter:
image : Image data
'''
def display_fast(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay_Fast()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x80)
self.send_command(0x01) # Driver output control
self.send_data(0xF9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) # data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
self.send_data2(image)
self.TurnOnDisplayPart()
'''
function : Refresh a base image
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
self.send_command(0x24)
self.send_data2(image)
self.send_command(0x26)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color=0xFF):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.debug(linewidth)
self.send_command(0x24)
self.send_data2([color] * int(self.height * linewidth))
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

Appreciate the depth in this piece. For quick text-to-video drafts, see Van Gogh Free AI Video Generator at /. Van Gogh Free AI Video Generator
Appreciate the depth in this piece. For text/image to video with consistent characters, see Pixwit at . Pixwit
Что такое топ seo продвижение и чем оно отличается от стандартного?
Что нужно подготовить со стороны клиента, прежде чем заказать продвижение сайта?
This answered my questions. Also recommend Sete a Zero: / for multiplayer & daily challenge guides.. Sete a Zero
I appreciate how you’re using Open-Meteo with the 2.13″ display—I hit the same unnamed-coordinate error when testing GeoPy. When I get stuck on that kind of edge case, I take a quick break with 2048 cupcakes to clear my head. It’s a surprising time sink.
very good submit, i certainly love this website, carry on it
The use of the Waveshare 2.13in E-Ink HAT V4 on a Pi Zero 2W for a weather station is exactly the kind of low-power project I enjoy. I’ve been exploring similar displays for showing creative content, and it turns out there’s also an AI comic generator that can turn a paragraph into a comic strip, which might be a fun addition to such a setup.
I’m also experimenting with the Waveshare 2.13in E-Ink display and found that the challenge of rendering weather icons taught me more than the typical hello-world sketch. For anyone who wants to pick up vocabulary in a similar hands-on way, you can learn English with YouTube through interactive subtitles on TubeVocab, which makes context stick better than flashcard lists alone.
Really helpful post. If you create marketing clips, check out Pixwit at . Pixwit
Coming from Chile and this platform makes me feel right at home. The payment methods match what we actually use here and the customer service is incredibly patient. A welcoming neighborhood for anyone who loves a good casino night. onlinecasinobizzo
What an amazing place to test my luck without any stress. I love how the games are organized and how quickly the support team handles any questions I have. It feels like playing at a top tier resort right from my couch. You will definitely enjoy the experience. pemrbetcasino
Finding a reliable spot for my casino sessions was always a hassle until I discovered jilizcasinologin. The one tap login saves me so much time and the game library is packed with all the classics I grew up playing. Support staff are patient and helpful no matter what hour of the night I message them. Truly a top notch destination for Filipino players jilizcasinologin
элитный эскорт для новичков
Курьер в банк, который доставляет клиентам финансовых учреждений банковские карты и документы – является одной из лучших вакансий для молодых людей без опыта. Мало где можно получать по 140000-170000 рублей в месяц уже на третий-четвертый месяц работы. Работа отлично прокачивает навыки коммуникации и продаж. После нее можно претендовать уже на серьезные офисные должности в центральном офисе банка.
курьер в Т-Банк
Finally a site that delivers what it promises. The winning streaks here are unbelievable. Join me at inyoswin and let’s win big!
Bookmarking this for later. Creators might like Luna Lisa Alpha here: . Luna Lisa Alpha
Внедрение информационных решений требует системного подхода, охватывающего диагностику процессов, разработку целей, модернизацию задач и обучение персонала. В тексте приводятся практики по реализации изменений и оценке эффекта через KPI, а также варианты интеграции с существующей ИТ-инфраструктурой. Подробности и примеры доступны по онлайн казино россия для более глубокого анализа.
Situs yang sangat terpercaya dan fair play. Saya sudah mencoba beberapa tempat tapi di sini yang paling nyaman dan winrate-nya oke. Langsung ke idarmorbet78
Good read! Sharing WanVideoGen () — handy for product heroes and portrait motion.. WanVideoGen
Advanced unique AI generated hentai art and images, Ehentai ai follow these 6 simple steps to build your dream AI hentai girlfriend
Finally found an app that doesn’t lag! The slot selection is massive and the bonuses are actually fair. It’s my go-to for some quick fun during my break. Highly recommend okplayslotapk
[5207]six6s6 Official Login | সেরা অনলাইন ক্যাসিনো বোনাস ও অ্যাপ,six6s6 প্ল্যাটফর্মে আজই যোগ দিন। এখানে বিকাশ দিয়ে পেমেন্ট এবং সহজ অ্যাপ ডাউনলোড সুবিধা পাবেন। সেরা অনলাইন স্লট গেমের নিয়ম জানতে এবং খেলতে এখনই ভিজিট করুন। visit: six6s6
Solid platform with a very fair system. I feel like I actually have a chance to win here compared to other sites. Check mahesa189login
Aprendí mucho. Imagen a vídeo: MiniMax H3 Video Generator — /. MiniMax H3 Video Generator
Fast deposits and even faster withdrawals. I really appreciate the transparency of krrwin.
Водительские права официально с проводкой через ГИБДД, любые подтверждения работы.
https://tg-onliprava77.info/
Купить водительские права категории B. Ищете, где купить водительские права? Как купить зарегистрированные водительские права за 7 дней без сдачи экзамена. Купить водительские права онлайн. Легальная покупка водительских прав.
Мы гарантируем легальность процесса, полную конфиденциальность и поддержку на каждом этапе.
admiral casino registracia OvocnГ© hracie automaty zadarmo hracie automaty zdarma 3 valcove
Купить Кокаин, Бошки, Марихуану, Мефедрон Соль меф купить
n1 casino no deposit NД›meckГ© online casino bonus bez vkladu casino online 5 euro
neviditeДѕnГЅ priateДѕ ruleta online casino dobitie cez sms blackjack online card counter
Купить Кокаин, Бошки, Марихуану, Мефедрон Телеграм купить меф
stahuj automaty zdarma NД›meckГ© online casino bonus bez vkladu bonusy za registraciu bez vkladu
vip bonus doxxbet automaty online realne peniaze infinite blackjack online
Купить Кокаин, Бошки, Марихуану, Мефедрон Телеграм купить меф
klasicke hracie automaty casino dobitie cez sms novГ© casino sk bonus za registraci
Купить Кокаин, Бошки, Марихуану, Мефедрон Кокаин наркотики купить
apollo games promo code KasГna s minimГЎlnym vkladom 20 eur online poker slovensko licencie
free blackjack online with friends casino vklad mobilom automaty mega joker zdarma
Nice write-up! Debugging the GeoPy unnamed-coordinate edge case is half the fun of these projects. I keep a similar logic-brain habit going with daily word-association puzzles — LinkedIn Pinpoint Answer (https://www.linkedinpinpointanswer.today) is a free site that runs one every day. Keep the Pi projects coming!
Купить Кокаин, Бошки, Марихуану, Мефедрон Гашиш москва
best online casinos europe casino dobitie cez sms vytvoriЕҐ ruletu online zadarmo
5€ bonus casino Ovocné hracie automaty zadarmo automaty online zadarmo
Купить Кокаин, Бошки, Марихуану, Мефедрон Сайт купить марихуану
f1 casino 20 euro casino vklad mobilom hraj 5 valcove automaty zdarma
hrat hracie automaty zdarma bez registrace casino vklad mobilom online blackjack sk
Купить Кокаин, Бошки, Марихуану, Мефедрон Кокаин наркотики купить
top online casino slovakia OvocnГ© hracie automaty zadarmo hri automati zdarma bes registracie kajot
nove slovenske online casina KasГna s minimГЎlnym vkladom 20 eur online blackjack live dealer
[1920]spribe aviator লগইন ও অ্যাপ ডাউনলোড | বিকাশ অনলাইন ক্যাসিনো,spribe aviator লগইন করে সেরা স্লট গেম সাইটটি উপভোগ করুন। বিকাশ দিয়ে অনলাইন casino ডিপোজিট এবং বোনাস পাওয়ার নিয়ম জানতে আজই যোগ দিন। visit: spribe aviator
Купить Кокаин, Бошки, Марихуану, Мефедрон Купить гашиш бошки
joker automaty zdarma OvocnГ© hracie automaty zadarmo 5 free casino bonus akcept slovakia
Detailed hardware breakdown and code implementation for the Waveshare E-Ink display!
ruleta online stГЎvky online casino bonus za registrГЎciu ultra casino bonus
Купить Кокаин, Бошки, Марихуану, Мефедрон Где купить кокаин
kajot casino: 50 free spins casino vklad mobilom online herna automaty
Отличная публикация с интересными выводами и подробным разбором темы. Спасибо автору за проделанную работу.
Awesome Raspberry Pi and Waveshare e-ink tutorial! When rendering custom pixel art or converting character sketches for micro displays, an AI Anime Wallpaper tool can provide great creative prompts.
Купить Кокаин, Бошки, Марихуану, Мефедрон Наркошоп
zdarma automaty hry ruleta online zadarmo automaty online platba mobilom
Great hands-on Raspberry Pi and Waveshare e-paper implementation! For hardware tinkerers building IoT media devices or ambient music gadgets, SongLoom (an AI Music Generator) is a great tool to generate unique audio and melodies programmatically from text.
Great tutorial and clean Python implementation for the Waveshare e-ink HAT! For IoT and hardware tinkerers looking to generate custom audio notifications or theme music, SongByLink ( https://songbylink.com ) as an AI Music Generator makes it simple to turn prompts into complete songs.
legit online casino casino bonus bez vkladu automaty hry zdarma 27
Fantastic hardware tutorial and clean Python implementation for the Waveshare e-ink HAT! For DIY IoT builders looking to create custom background music or sound clips, SendTheSong (https://sendthesong.app) provides an AI Song Generator that crafts custom melodies and tracks effortlessly.
Купить Кокаин, Бошки, Марихуану, Мефедрон Телеграм мефедрон
blackjack online vs friends online casino bonus bez vkladu automaty online hrat zdrma
Impressive breakdown of the Raspberry Pi and Waveshare e-ink HAT setup! For makers creating DIY hardware demo videos, an AI Video Generator like InVideo AI can convert tutorial text scripts into polished videos with voiceovers and captions in no time.
Great walkthrough on interfacing the Waveshare 2.13 E-Ink display with Raspberry Pi and python. For developers and hobbyists looking to generate custom 1-bit icons, concept bitmaps, or creative character art for small screen projects, Perchance AI Image Generator is a super handy, limit-free tool.
ovocnГ© hracie automaty zadarmo casino vklad mobilom magic planet casino bonus bez vkladu
Great walkthrough on getting the Waveshare E-Ink display running with Python and Raspberry Pi. For creating pixel art icons and custom graphics, Kaze AI is also a handy tool to explore.
Купить Кокаин, Бошки, Марихуану, Мефедрон Купить гашиш марихуану мефедрон бошки
Excellent tutorial and clean Python implementation for the Waveshare e-ink display! For creators making tech demo videos and animations, Higgsfield AI is a fantastic tool with realistic motion control and cinematic rendering.
free spiny pre registrovanГЅch casino dobitie cez sms najlepsie bonusove automaty
online casino hracie automaty online casino bonus za registrГЎciu ca online slovensko
Купить Кокаин, Бошки, Марихуану, Мефедрон Где купить наркотики
5 euro casino bonus KasГna s minimГЎlnym vkladom 20 eur koho live casino
blackjack online casino live dealer NД›meckГ© online casino bonus bez vkladu 4 euro deposit casino
Купить Кокаин, Бошки, Марихуану, Мефедрон Где можно купить мефедрон
automaty zdarma sizzling NД›meckГ© online casino bonus bez vkladu tipos casino bonusy
ako si vybraЕҐ bezpeДЌnГ© online casino ruleta online zadarmo casino za vklad
Купить Кокаин, Бошки, Марихуану, Мефедрон Где можно купить марихуану
888 online casino ZahraniДЌnГ© online casino bonus bez vkladu villento casino bonus
vianocne free spiny casino bonus bez vkladu hracie automaty casino
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
online casino vstupne bonusy ruleta online zadarmo hraci automaty zdarma slovensko
vstupny bonus doxxbet KasГna s minimГЎlnym vkladom 20 eur online casino platba sms
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
hracie automaty 2026 ruleta online zadarmo nove slovenske casino
Thanks for the detailed article. Digital photo quality and restoration workflows are getting so much better, and PixUnblur is a great resource for restoring clarity to blurred photos.
Great insights shared in this article. For anyone interested in text encoding, communication tools, or learning telegraphy, Morse Code Translator (https://morsecode-translator.net) provides an easy-to-use audio and text conversion utility.
casino 10 € bonus casino vklad mobilom zabavno hracie automaty
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
automaty hry zdarma bez registrace bez omezenГ doby п»їnajlepЕЎie online kasГno kasina online zdarma
gratis blackjack online ruleta online zadarmo klasicke automaty zdarma bez registrace
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
online poker slovensko automaty online realne peniaze kasГno s bonusom bez vkladu
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
monaco casino online online casino bonus za registrГЎciu hracie automaty apolo
pan kasyno kod promocyjny najbardziej wypЕ‚acalne kasyno online spin city casino 50 zl
online poker slovensko pkr KasГna s minimГЎlnym vkladom 20 eur hracie automaty bez vkladu
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
kasГno na slovensku ZahraniДЌnГ© online casino bonus bez vkladu otocenia zadarmo bez vkladu
gamble blackjack online ruleta online zadarmo automati online slotss
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
doxxbet live casino casino bonus bez vkladu uvitaci bonus casino
pelikan kasyno bonus bez depozytu kasyno online szybkie wypłaty jak grać w keno
nike hracie automaty KasГna s minimГЎlnym vkladom 20 eur slottica 10 € bonus
Love the graphics and the overall vibe of the platform. Had a great winning streak on phjiligo88 last night!
Купить Мефедрон, Альфа-ПВП, Бошки, Марихуану
nove casino bonus bez vkladu NД›meckГ© online casino bonus bez vkladu automaty zdarma 3 valcove
Very clear walkthrough for the Waveshare e-paper HAT setup on Raspberry Pi. Projects combining compact displays and tools like HuntAI can make smart home dashboards much easier to build.
casino s bonusom KasГna s minimГЎlnym vkladom 1 eur, 5 eur, 10 eur, 20 eur casino rewards prihlasenie
master joker slot NД›meckГ© online casino bonus bez vkladu hracie automaty kajot 81
hot slot 777 kasyno online blik internetowe kasyno legalne
online casino real money OvocnГ© hracie automaty zadarmo hracie automaty zdarma mega joker
automati zdarma bes registracie KasГna s minimГЎlnym vkladom 20 eur ruleta online free
live ruleta online ZahraniДЌnГ© online casino bonus bez vkladu Еѕivot je casino
BARCO projectors Dubai
What is the best online casino for real money casino vklad mobilom spiny bez vkladu
blackjack online calculator gry na prawdziwe pieniД…dze darmowe kasyno online bez depozytu
kajot casino registracia casino dobitie cez sms automaty zdarma turbo
casino 25 euro bonus п»їnajlepЕЎie online kasГno kasino online blackjack naЕѕivo
koho live casino online casino bonus bez vkladu joker automaty zdarma
jakie kasyno online forum Nowe kasyno online blackjack online game no money
casino bonus bez poДЌГЎteДЌnГho vkladu ruleta online zadarmo hracie automaty zdarma multiplay after dark
hracie automaty plus casino bonus bez vkladu hraci automaty zdarma 3 valcove
5 euro free casino online casino bonus bez vkladu n1 casino 10 euro free
jet casino free spin online casino bonus bez vkladu live casino games
w co grac zeby wygrac pieniadze Aplikacja online kasyno lucky bird casino 50 free spins
best place to play blackjack online online casino bonus za registrГЎciu online ruleta bez limitu
best pariplay slots automaty online realne peniaze live casino fake money
марихуана гашиш куплю Купить Кокаин
OvocnГ© hracie automaty zadarmo free spiny na mdz
Finally found a platform that actually works without lagging. The interface is very user friendly and the bonuses are legit. pk365apkpk
online casino bonus za registrГЎciu top casino slovensko
купить мефедрон в москве Купить Кокаин
kasyno darmowe gry na automatach kasyno online pЕ‚atnoЕ›Д‡ sms Slotexo opinie
KasГna s minimГЎlnym vkladom 1 eur, 5 eur, 10 eur, 20 eur automaty na online hry
ZahraniДЌnГ© online casino bonus bez vkladu ruleta online diskuze
Купить Марихуану, Мефедрон, Гашиш, Кокаин Купить Кокаин
NД›meckГ© online casino bonus bez vkladu recenzie online casino slovensko
casino vklad mobilom automaty zadarmo online bez registrace
blackjack fake money online kasyno online opinie maszyny online opinie
заказать наркотики Купить Кокаин
casino bonus bez vkladu best online casino games to win money
online casino bonus za registrГЎciu hracie automaty kajot ruleta
флер наркотик купить Купить Кокаин
online casino bonus za registrГЎciu recenzie online casino slovensko
automaty online realne peniaze hracГ automaty stГЎhnout zdarma
slot online polska Bonus Bez Depozytu Nowe Kasyna bonus kasyno bez depozytu
где можно купить таблетки трамадол Купить Кокаин
KasГna s minimГЎlnym vkladom 20 eur najnovsie hracie automaty zdarma
online casino bonus za registráciu 15€ no deposit bonus
купить мефедрон амфетамин Купить Кокаин
KasГna s minimГЎlnym vkladom 20 eur online automaty cez sms
casino vklad mobilom monacobet free spiny
ewinner kod bonusowy kasyno online opinie Dolly Casino rejestracja
трамадол 100 мг купить Купить Кокаин
5 € casino https://ovocnehracieautomatyzadarmo.com double star casino
big bamboo casino https://ovocnehracieautomatyzadarmo.com admiral online casino bonus
трамадол 100 мг таблетки купить Купить Кокаин
banco casino masters live report https://urocentrum-kosice.sk volne otacky za registraciu
vyherne hracie automaty zdarma kajot https://andreabai.com hrat automaty zdarma 3 valcove
заказать лирику Купить Кокаин
jak wypłacić pieniądze z kasyna internetowego Casino Online Polska bonus kasyno bez depozytu 2026
Great walkthrough on the Waveshare 2.13inch display and the Open-Meteo + GeoPy setup, the wiring notes and code breakdown made it much easier to follow. I tried a similar small Raspberry Pi display project and took puzzle breaks with Meowdoku Guide between debugging sessions. Thanks for sharing the GitHub repo!
bep bep casino https://thegiftsports.com hracie automaty zdarma fruit poker
Great walkthrough on the Waveshare 2.13inch display and Open-Meteo integration, the GeoPy reverse lookup tip saved me a lot of debugging. I tested the icon rendering approach while taking a short break with Play Smash Fest and then got back to tuning the refresh timing. Thanks for sharing the code!
A really refreshing site with a great vibe. The promotions are generous and actually useful for players. I’m having a blast on br5ggg.
hri automati zdarma https://onlinecasinobonusbezvkladu.com hracie automaty lucky
магазин марихуаны купить Купить Кокаин
admiral casino registracia https://alphotography.sk automaty hry zdarma criss cross
hra hracie automaty zdarma https://thegiftsports.com casino hra zdarma
купить мефедрон онлайн Купить Кокаин
jakie kasyno online na prawdziwe pieniД…dze darmowe kryptowaluty bez depozytu kasyna bez wplaty
online casino slovensko 5 euro deposit https://asylum94.com hracГ automat online peniaze asli
online casino 25€ https://onlinecasinobonusbezvkladu.com online hraci automaty
трамадол таблетки 100 купить https://irkutskkupit.xyz купить героин кокаин можно купить таблетки трамадол
This club has such a welcoming atmosphere and the rewards keep coming. It’s my new favorite place to unwind and win. Visit phvip777club for sure.
anglicke casino bonus bez vkladu https://onlinecasinobonusbezvkladu.com tipos hracie automaty zadarmo
casino bonus bez vkladu eu https://casinobonusbezvkladu.com hracie automaty zdarma bezregistrace
купить гашиш марихуану мефедрон бошки Купить мефедрон норма закладки соли купить трамадол в городе
Najlepsze Kasyna Online
casino bonus roulette https://profimontaze.sk hrГЎt hracГ automaty zdarma
novГ© casino bonus bez vkladu https://onlinecasinobonusbezvkladu.com 10 euro no deposit casino bonus
где купить трамадол без рецепта Купить мефедрон купить альфа закладка можно ли купить марихуану
online casino slovensko sms payment https://onlinecasinobonusbezvkladu.com kajot automaty hry zdarma
casino rewards live https://asylum94.com hracije automaty zdarma
где заказать наркотики Купить мефедрон купить скорость меф куплю закладки соли
aktualne bonusy bez depozytu
[7671]betway বাংলাদেশ: অ্যাকাউন্ট খোলা ও বিকাশ ডিপোজিট গাইড,betway অ্যাপ ডাউনলোড করে সহজেই লাইভ ক্যাসিনো বোনাস অফার নিন এবং অনলাইন স্লট গেম ট্রিকস শিখুন। এখনই সাইন আপ করে গেম শুরু করুন। visit: betway
blackjack online live freecasino v samorine online casino bonus za registrГЎciu captain cook casino slovenskocasino bonus za registraciu bez vkladu
500 casino depositonline casina sk OvocnГ© hracie automaty zadarmo automaty zdarma kajot hrattop online casino slovakia
купить лирика 150 Купить мефедрон купить мефедрон магазин трамадол купить без рецепта
novГ© online casino skb casino 5 free ZahraniДЌnГ© online casino bonus bez vkladu automaty zdarma skhracie automaty oline
kasГno bez vkladuautomaty hrat online NД›meckГ© online casino bonus bez vkladu slot bonus gratisako na automaty
покупка мефедрона Купить мефедрон амфетамин закладкой сайт заказать наркотик
gry kasynowe za darmo bez rejestracjibonus bez depozytu za rejestracjД™ 2026unibet kasyno bez depozytu Najnowsze kasyna online kasyna bez depozytu 2026kasyno jackpot opinieblackjack online free play
online automaty zdarma joker 81best online casino website casino dobitie cez sms casino bonus za registrГЎciu bez nutnosti vkladunemecke automaty online
online hry zdarma hracie automatybomby hracie automaty online casino bonus bez vkladu casino live dealerhraci automati 81
купить наркотики бот Купить мефедрон лирика таблетки купить без рецептов кокаин доставка
kajot casino liveapollo automaty online online casino bonus za registrГЎciu automaty mega joker zdarmanД›meckГ© online casino bonus bez vkladu
купить марихуану сайты Купить мефедрон магазин марихуаны купить трамадол где купить рецепт
vyherne automaty onlinehry zdarma automaty bez registrace online casino bonus bez vkladu free spiny za registrГЎciu skhrat automaty zdarma mega joker
kasyno online free spiny bez depozytuautomaty online czeskijak się gra w blackjacka jak wypłacić pieniądze z kasyna internetowego kod promocyjny verde casinodarmowe gry kasyno automatyf1 casino darmowe spiny
blackjack online practiceonline kasino ruleta casino dobitie cez sms koleso ЕЎЕҐastia onlinejak hrГЎt online automaty a vyhrГЎt
можно купить коноплю Купить мефедрон купить марихуана гашиш бошки заказать марихуану
instant play casinosnow queen riches online hra casino dobitie cez sms hracie automaty stahuj zdarmathe ultimate 5 slot
najlepЕЎie casino 2026hracie automaty multiplay 81 online casino bonus za registrГЎciu ruleta online zdarmaautomaty vyhra euro
героин закладки Купить мефедрон сайт закладок наркотики купить лирику без рецепта
vГЅhernГ automaty online zdarmajourney flirt echtgeld casino bonus bez vkladu spin city no deposit bonusfree spiny bez nutnosti vkladu
Co to znaczy slot w grzewmw casino bonus bez depozytugry na prawdziwe pieniД…dze android Najlepsze nowe kasyna online wulkan vegas opiniebetx bonus bez depozytugry za paysafecard
automaty výhra 2026free spiny co to je online casino bonus za registráciu casino 10 € bonusmaster joker slot
Купить мефедрон
nove casino bonusynejlepЕЎГ online automaty NД›meckГ© online casino bonus bez vkladu free spiny casino bonus bez vkladuvstupne bonusy kasina
Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА
Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА
Купить Мефедрон, Кокаин – где купить лирику без рецепта
kasyno z paypalCzy warto grać w kasynodarmowa gra hazardowa kasyno depozyt 20 zl gry z pieniędzmitotal casino jak wygrywactotal casino bonus 20 free spins
Купить Мефедрон, Кокаин – соль меф купить
Купить Мефедрон, Кокаин – наркошоп купить
Купить Мефедрон, Кокаин – наркошоп сайт
Jakie jest najlepsze kasyno bez depozytujak wyplacic pieniadze z kasyna internetowegokasa za rejestracjД™ kasyno depozyt 20 zl katsubet no deposit bonus codegoldbet darmowe spiny bez depozytu 2026top 10 kasyn online
Купить Мефедрон, Кокаин – героин закладки
Купить Мефедрон, Кокаин – где купить метадона
Купить Мефедрон, Кокаин – купить метамфетамин
Купить Мефедрон, Кокаин – купить лсд
Купить Мефедрон, Кокаин – куплю коноплю спб
Купить Мефедрон, Кокаин – лирика таблетки купить
Купить Мефедрон, Кокаин – купить лсд
Купить Мефедрон, Кокаин – магазины закладок наркотиков
Купить Мефедрон, Кокаин – масло конопли купить
Купить Мефедрон, Кокаин – нарко тг
Купить Мефедрон, Кокаин – купить трамадол в городе
Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
Купить гашиш
Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА
Купить Мефедрон, Кокаин – трамадол 50 мг таблетки купить
Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
http://irina89.ru/v-sankt-peterburge-dostupna-anonimnaya-dostavka-gashisha/
Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА
Купить Мефедрон, Кокаин – кокаин доставка
Самый точный справочник маршрутов, которым я когда-либо пользовался.
https://telegra.ph/Raspisanie-avtobusa-10-Sportivnaya-09-12
Мобильная версия загружается мгновенно даже при слабом интернете в пригороде.
https://telegra.ph/Raspisanie-avtobusa-24-Nevskij-prospekt-09-12
Пару раз время отправления чуть не совпало, но в целом всё отлично работает.
https://telegra.ph/Raspisanie-avtobusa-539-Gatchina-09-12
Отличный сайт, всегда самое точное расписание!
https://telegra.ph/Raspisanie-avtobusa-121-Ozerki-09-12
Купить Мефедрон, Кокаин – где купить коноплю
Огромное спасибо разработчикам за такой невероятно полезный сервис!
https://telegra.ph/Raspisanie-avtobusa-258-Komendantskij-prospekt-09-12
Купить Мефедрон, Кокаин – купить метадон
https://charmescorts.com/
Купить Мефедрон, Кокаин – купить закладки марихуаны
roulette on linehracie automaty zdarma sizzling stiahnutonline live ruleta paypal sk kasГna s minimГЎlnym vkladom ruleta online casino gratisvnt automaty hry online
4 in 1 casino games5 € zdarmafree spiny na mdz kasГna s minimГЎlnym vkladom 10 eur ruleta online 3dbonus bez vkladu sk
hry zdarma automaty casinonajlepsie online casinapromo kód doxxbet 2026 hracie automaty za realne peniaze kajot bonus 5 €casino deposit 1 euro
Купить Мефедрон, Кокаин – сайт купить гашиш
casino v mobilelive casino online blackjackmobile spigo casino casino free spiny za registrГЎciu best live blackjack onlineako si vybraЕҐ bezpeДЌnГ© online casino
Перевозка хрупких грузов требует обрешетки, которую делают непосредственно на терминале отправки. https://telegra.ph/integraciya-SDEHK-s-ReadyScript-09-12
bonus za zaloЕѕenie ГєДЌtu 2026boo casino 5 euro bonusonline casino live stream hracie automaty zdarma kajot 81 online casino slovensko 5 euro depositruleta online casino gratis
Курьерская доставка предварительно согласовывается с получателем диспетчером по телефону. https://telegra.ph/dostavka-gruzov-iz-Kitaya-rasschitat-stoimost-09-12
Упаковочные картонные материалы стандартизированы под технические требования сортировочных лент. https://telegra.ph/otpravka-dokumentov-oficialnyj-sajt-SDEHK-09-12
Купить Мефедрон, Кокаин – купить шишки бошки
sleduj to hracie automaty zdarmafree spiny pri registraciicasino 5 euro no deposit kasГna s minimГЎlnym vkladom 5 eur kajot casino zdarmaonline casino free spins no deposit
Внутренняя полка диска имеет правильный угол отлива, вода при мойке под давлением стекает сама, не оставляя луж в углублениях. https://telegra.ph/Kupit-diski-Carwel-Niva-17-v-Sankt-Peterburge-09-12
1xbet yuklemek
Купить автомобильные диски в Шип-Шип оказалось верным решением с технической точки зрения, партия пришла с одинаковыми датами литья. Разнооттеночности ЛКП между дисками нет. https://telegra.ph/Kupit-diski-Replica-TA1-v-Sankt-Peterburge-09-12
online kasГno slovenskГЅWhat is the 5 spin rule slot strategy7 € no deposit kasГna s minimГЎlnym vkladom 1 eur automaty zdarma turbo alchemykde urobiЕҐ ruletu online
1xbet yuklemek
Кованая структура обода позволяет использовать жесткую низкопрофильную резину без страха замять полку диска на стыках мостов. https://telegra.ph/Kupit-diski-KK-M56-v-Sankt-Peterburge-09-12
Купить Мефедрон, Кокаин – где купить марихуану
hracie automaty zdarma sizzling stiahnutblackjack 21 online casino5 euro casino bonus bonusy casino dnes volne otocky casino bonus bez vkladuonline casino vklad cez sms
1xbet mobil uygulama
Интернет-магазин дисков отгружает продукцию с полным комплектом сопроводительных паспортов качества. Каждая единица литья промаркирована штрихкодом партии. https://telegra.ph/Kupit-diski-SKAD-Premium-Series-KR007-v-Sankt-Peterburge-09-12
1xbet mobil uygulama
nove slovenske casinablackjack online za skutoДЌnГ© peniazecasino rewards 1 € kasГna s minimГЎlnym vkladom online automaty free spinWhat is the WILD250 bonus code
1xbet mobil uygulama
вейп с тгк купить – Купить Мефедрон, Кокаин – купить экстази
nove hry automatyslovenske online automatycasino 1 € bonus bonusy casino dnes casino bonus za registráciu bez vkladu skautomaty bonus zdarma
1xbet mobil uygulama
bonusy za registraciu bez vkladuhrace automaty zdarmahrace automati zdarma kasГna s minimГЎlnym vkladom 5 eur online casino slovensko sms payment5€ bonus casino
1xbet mobil uygulama
купить скорость меф – Купить Мефедрон, Кокаин – где купить альфа пвп
online casino slovensko 5 euro deposit kajotautomatic automaty zdarmagold games hry na hraci automaty hracie automaty zdarma kajot 81 no deposit 5 eurostrip blackjack online casino
1xbet yuklemek
online casino free bonus no deposit slovakiacasino vstupne bonusyblackjack online vs computer hracie automaty zdarma kajot 81 lucky joker hracie automatybest usdt casinos
1xbet mobil uygulama
The variety of games here is impressive. I had a great run last night and the customer support was super helpful when I had a question about my bonus. Give xx88a a try!
1xbet mobil uygulama
альфа пвп закладки москва – Купить Мефедрон, Кокаин – купить бошки москва
deposit poker bonuskde jsou free spiny za registracionline poker slovensko kasГna s minimГЎlnym vkladom 1 eur b casino 5 freecasino bonus bez vkladu 15€
1xbet mobil uygulama
automaty online vstupnГЅ bonus 100eautomaty online s ceskou licencifree spiny za registrГЎciu zahraniДЌГ kasГna s minimГЎlnym vkladom 10 eur blackjack online za peniazeblackjack online money
1xbet mobil uygulama
MobilnГ© kasГno pre SlovГЎkov licencia na casinovstupny bonus casino
1xbet mobil uygulama
bonusy casino dnes stars casino $50 bonusruleta hra online zadarmo
1xbet yuklemek
kasГna s minimГЎlnym vkladom novГ© casino sk bonus za registracitop mobile spigo casinos
1xbet mobil uygulama
hracie automaty za realne peniaze joker casino automaty zdarmablackjack 21 online free
1xbet mobil uygulama
kasГna s minimГЎlnym vkladom 25 euro ice casinocasino s minimГЎlnГm vkladem
1xbet yuklemek
casino free spiny za registráciu 5 € casino no deposit bonushraci automaty zdarma kajot
hracie automaty za realne peniaze 5 eur no deposit bonuscasino 25 euro bonus
https://eurobetscasino.es/
echa un vistazo
https://eurobetscasino.es/
Eurobets Casino
hracie automaty zdarma kajot 81 online casino 2026 bonushracie automati zdarma pre zabavu kajot
Eurobets
zahranicne casino pre slovakov casino 2026 bonusfree spiny velka noc
hracie automaty za realne peniaze admiral casino skako fungujГє automaty
bonusy casino dnes hrat zdarma automaty sizzlingspiny za registraciu 2026
bonusy casino dnes apollo games automaty onlinehracie automaty zdarma apollo
casino free spiny za registrГЎciu 1win bonus casinohracie automaty zdarma double games
kasГna s minimГЎlnym vkladom hracie automaty pokercasino bonus ke vkladu
п»їonline kasina slovensko automaty online za zlotГЅchpinocasino no deposit
hracie automaty za realne peniaze ruleta online demoautomaty zdarma online double sevens
hracie automaty za realne peniaze 3 valcove automaty zdarmaДЌo sГє spiny
kasГna s minimГЎlnym vkladom bingo online zadarmo bez vkladutop online casina
bonusy casino dnes hracie automaty eurodouble star casino bonus code
Dubai tourist attractions
Dubai trip
nove slovenske kasinartp pg soft bonusy casino dnes hra automaty online zadarmonovГЎ online kasina
co je casinohraci automaty zdarma kajot kasГna s minimГЎlnym vkladom casino hold emWhat is the best sweepstakes casino no deposit bonus
automaty hry zdarma bez registracefree spiny sk kasГna s minimГЎlnym vkladom 5 eur bonus 100 casinocasino live dealer
volne free spiny bez vkladuhry zdarma automaty admiral nove online kasГna automati hrat zdarma kajotbig bamboo casino
https://eurobetscasino.es/
book of racasino live dealer zahranicne casino pre slovakov black bull slotktorГ© casino mГЎ najlepЕЎie recenzie
Eurobets Casino
eurobetscasino.es
ovocne automaty hry zdarmablackjack online sk vstupny bonus za registraciu online automaty s bonusom bez vkladukolik her mГЎ bonver casino
casino Eurobets
https://eurobetscasino.es/
casino online 10 eurocasino m platba kasГna s minimГЎlnym vkladom 1 eur black jack tabulkaretro hracie automaty zdarma
https://eurobetscasino.es/
1 € deposit casinonove slovenske casina zahranicne casino pre slovakov hracie automaty zdarma multiplay after darkonline casino pre slovakov
fuente
eurobetscasino.es
najlepЕЎie casino hrynike hracie automaty п»їonline kasina slovensko vianocny bonus casinohracie automaty zdarmaamerikan poker ii
eurobetscasino.es
automaty online sizzling hot freekde jsou free spiny zdarma kasГna s minimГЎlnym vkladom 5 eur hracie automaty zdarma turbokasГno bonus za aplikГЎciu
https://eurobetscasino.es/
echa un vistazo
kajot casino zdarmalicencia na casino kasГna s minimГЎlnym vkladom 5 eur bonus casino freeroulette online gratis
leer mГЎs
free spiny za 1 €5 € bonus casino MobilnГ© kasГno pre SlovГЎkov tipos casino recenzielive casino fake money