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 spidev

For WeatherInk.py, GeoPy and Open-Meteo libraries are needed:

pip install openmeteo-requests 
pip install requests-cache retry-requests numpy pandas 
pip install geopy

WeatherInk.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 strHr

epdconfig.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 ###

By Lynx

Born in the 70's. Grew up in Western NY. Happily married, and has 2 children. Lives in Connecticut.

536 thoughts on “Waveshare-2.13inch-E-Ink-display”
  1. 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.

  2. 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.

  3. 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.

  4. 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

  5. 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

  6. Курьер в банк, который доставляет клиентам финансовых учреждений банковские карты и документы – является одной из лучших вакансий для молодых людей без опыта. Мало где можно получать по 140000-170000 рублей в месяц уже на третий-четвертый месяц работы. Работа отлично прокачивает навыки коммуникации и продаж. После нее можно претендовать уже на серьезные офисные должности в центральном офисе банка.
    курьер в Т-Банк

  7. Внедрение информационных решений требует системного подхода, охватывающего диагностику процессов, разработку целей, модернизацию задач и обучение персонала. В тексте приводятся практики по реализации изменений и оценке эффекта через KPI, а также варианты интеграции с существующей ИТ-инфраструктурой. Подробности и примеры доступны по онлайн казино россия для более глубокого анализа.

  8. [5207]six6s6 Official Login | সেরা অনলাইন ক্যাসিনো বোনাস ও অ্যাপ,six6s6 প্ল্যাটফর্মে আজই যোগ দিন। এখানে বিকাশ দিয়ে পেমেন্ট এবং সহজ অ্যাপ ডাউনলোড সুবিধা পাবেন। সেরা অনলাইন স্লট গেমের নিয়ম জানতে এবং খেলতে এখনই ভিজিট করুন। visit: six6s6

  9. Водительские права официально с проводкой через ГИБДД, любые подтверждения работы.
    https://tg-onliprava77.info/
    Купить водительские права категории B. Ищете, где купить водительские права? Как купить зарегистрированные водительские права за 7 дней без сдачи экзамена. Купить водительские права онлайн. Легальная покупка водительских прав.
    Мы гарантируем легальность процесса, полную конфиденциальность и поддержку на каждом этапе.

  10. [1920]spribe aviator লগইন ও অ্যাপ ডাউনলোড | বিকাশ অনলাইন ক্যাসিনো,spribe aviator লগইন করে সেরা স্লট গেম সাইটটি উপভোগ করুন। বিকাশ দিয়ে অনলাইন casino ডিপোজিট এবং বোনাস পাওয়ার নিয়ম জানতে আজই যোগ দিন। visit: spribe aviator

  11. Отличная публикация с интересными выводами и подробным разбором темы. Спасибо автору за проделанную работу.

  12. 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.

  13. 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.

  14. 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.

  15. 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.

  16. 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.

  17. 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.

  18. 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.

  19. 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.

  20. 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!

  21. 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!

  22. [7671]betway বাংলাদেশ: অ্যাকাউন্ট খোলা ও বিকাশ ডিপোজিট গাইড,betway অ্যাপ ডাউনলোড করে সহজেই লাইভ ক্যাসিনো বোনাস অফার নিন এবং অনলাইন স্লট গেম ট্রিকস শিখুন। এখনই সাইন আপ করে গেম শুরু করুন। visit: betway

  23. Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
    Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА
    Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА

  24. 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

  25. Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
    Купить гашиш
    Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА

  26. Купить магнитную закладку амфетамин, мефедрон, кокаин, гашиш, шишки. Полная гарантия и моментальные клады.
    http://irina89.ru/v-sankt-peterburge-dostupna-anonimnaya-dostavka-gashisha/
    Мы ваш источник марихуаны и Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА самого высокого качества. Мы предлагаем самый широкий выбор сортов сорняков в мире! Купить мефедрон, марихуану, лсд, гашиш, экстази и МДМА

  27. stare vГЅhernГ­ automaty online hry vstupny bonus casino
    admiral online casino bonus hrat hry automaty kajot zdarma bonus za zaloЕѕenie ГєДЌtu 2026 Vklad do casina cez sms ruleta na Еѕrebovanie online 5 stones slot
    casino slot bonus blackjack online anime

  28. kasino online ruleta mobil casino slovenskГЅ
    monacobet free spiny automaty zdarma hunters free spiny za aplikaciu Fortuna free spiny dnes tipsport free spiny dnes casino s bonusem
    volne otacky za registraciu 7 € bonus casino slovensko

  29. Резервные адреса периодически меняются, поэтому старые ссылки из закладок могут не сработать. Поэтому имеет смысл проверить актуальное зеркало 1win на сегодня — оно открывается без задержек и показывает ту же версию платформы, что и главный домен.

  30. automaty online zdarma mega joker hracie automaty 5 vГЎlcovГ© zdarma
    Do gaming apps really pay money nikГ© casino sk blackjack online arkadium Aktualne kasino na slovensku hracie automaty the mummy 27 linie automaty zadarmo online hraЕҐ
    bavime automati zdarma hracie automaty hrat zdarma sizzling hot

  31. Подбор качественной электроники и бытовых гаджетов требует грамотного подхода и сравнения цен. Здесь покупатели найдут регистраторы, GPS-маяки, фотоаппараты и множество полезных приборов для дома и автомобиля. Подробный каталог с описаниями и ценами представлен на сайте https://video-camer.ru/
    и доступен круглосуточно. Доставка выполняется быстро, а опытные консультанты помогут подобрать подходящую модель под любой бюджет.

  32. Фанатам сериалов больше не нужно тратить время на поиски интересных премьер. Свежие премьеры и проверенная классика собраны в одном месте по доступным ценам. Ищете купить диски сериалов? Интернет-магазин serialexpress.ru предлагает огромный каталог отечественных и зарубежных сериалов с доставкой по всей России. Покупка совершается в несколько кликов, а заказ приходит в кратчайшие сроки. Каждый покупатель получает диски высокого качества в аккуратной упаковке.

  33. casino bonus 2026 5 stones casino
    casino online paysafecard hazardnГ© hry online zadarmo 22bet casino prihlasenie Ako hrat automaty online casino bonus slovensko hracie automaty betor
    superlines casino login kajot sk online automaty

  34. альфа пвп закладки москва лирика купить аптека без рецепта Купить Мефедрон трамадол купить без рецепта купить бошки марихуаны где купить мефедрон
    купить кокаин марихуану купить скорости спб 1 грамм мефедронаhttps://pokrovskkupit.xyz дмт купить вейп с тгк

  35. Ищете надёжную мототехнику или планируете выгодно продать свою? Площадка «КупиПродай» — удобное решение для мотолюбителей Дальнего Востока. Здесь собраны актуальные объявления о продаже мотоциклов, скутеров и квадроциклов от частных лиц и салонов, а разместить своё предложение можно за пару минут. Загляните на https://vkupiprodai.ru/shop/moto-dv/ – сравните варианты, оцените цены и найдите технику своей мечты. Простой поиск, свежие предложения и живое сообщество делают покупку и продажу мото по-настоящему лёгкими и приятными.

  36. где купить тест на наркотики где купить модафинил Купить Мефедрон магазины закладок наркотиков закладки кристаллов купить наркотики спб
    купить наркотики бот где заказать наркотики где купить мефедронhttps://debaltsevokupit.xyz Купить Марихуану, Мефедрон, Гашиш, Кокаин где можно купить марихуану

  37. tomorrowland thailand hotel ticket package Самостоятельный поиск жилья отнимает время и даёт свободу выбора. Статья по фразе «tomorrowland thailand hotel ticket package» помогает решить вопрос включения проживания в заказ. Текст снимает типовые вопросы по пакетам с проживанием.

  38. купить трамадол наличие купить мдма мефедрон Купить Мефедрон конопля купить москва гашиш москва где купить канабис
    купить закладки марихуаны купить мефедрон телеграмме купить скорость мефhttps://yasinovatayakupit.xyz купить меф мяу мяу трамадол 50 таблетки купить

  39. tomorrowland2026.ru не кидалово Проверка агента перед оплатой проще возврата денег после. Статья «tomorrowland2026.ru не кидалово» перечисляет признаки надёжного продавца. Отдельно разобран вопрос получения PDF после оплаты.

  40. сколько стоит билет на фестиваль tomorrowland Минута проверки суммы перед платежом экономит нервы. Ответ на вопрос «сколько стоит билет на фестиваль tomorrowland» дан с примерами для одного билета и компании. Приведены примеры для одного билета и для компании.

  41. tomorrowland отель билет Единый пакет с проживанием удобен не для всех. Материал по теме «tomorrowland отель билет» сравнивает пакет с отдельной покупкой на равных условиях. Рекомендую сравнить оба варианта до оплаты.

  42. как проверить продавца билетов Tomorrowland Thailand Красивый сайт — ещё не доказательство надёжности компании. Ответ на вопрос «как проверить продавца билетов Tomorrowland Thailand» опирается на конкретные данные. Описана проверка суммы и состава заказа до платежа.

  43. tomorrowland thailand ticket price Цена в каталоге и сумма к оплате — это разные вещи. Материал по теме «tomorrowland thailand ticket price» даёт формулу рублёвого итога. Формула расчёта проста и повторяется за пару минут.

  44. где можно купить марихуану купить бошки гашиш марихуану экстази в питере Купить Мефедрон конопля купить где купить метадона где купить лсд
    где заказать наркотики препарат лирика купить нарко бот тгhttps://torezkupit.xyz где купить марихуану купить бошки москва

  45. tomorrowland thailand authorized reseller Красивый сайт — ещё не доказательство надёжности компании. Гайд по фразе «tomorrowland thailand authorized reseller» закрывает типовые сомнения перед оплатой. Заказ не синхронизируется с чужим личным кабинетом.

  46. betring vstupnГЅ bonus nove ceske online casino
    casina s bonusem za registraci 500 casino bonus admiral automaty zdarma Free spiny bez vkladu dnes What online casino has free bonus without deposit hry na mobil zdarma automaty
    slot on line hraci automati zdarma bez registracie

  47. tomorrowland thailand hotel ticket package Трансфер в составе пакета экономит силы после длинных дней фестиваля. Гайд «tomorrowland thailand hotel ticket package» объясняет границы пакета и отдельные оплаты. Отдельно разобрано проживание после последнего фестивального дня.

  48. трамадол 50мг купить трамадол капсулы 50 купить Купить Мефедрон тест на наркотики купить купить мефедрон в москве где купить гашиш
    заказать лирика 300 где можно купить марихуану трамадол где купить рецептhttps://yenakiyevokupit.xyz купить наркотики онлайн гашиш можно купить

  49. tomorrowland thailand authorized reseller Грамотная проверка начинается с договора и реквизитов. Ответ на вопрос «tomorrowland thailand authorized reseller» опирается на конкретные данные. Компания и домен видны в опубликованном договоре.

  50. tomorrowland thailand ticket price Курс валют и комиссия способны заметно изменить финальный чек. Материал по теме «tomorrowland thailand ticket price» даёт формулу рублёвого итога. Отдельно упомянуты расходы на дорогу и проживание.

  51. С 2006 года автошкола «Драйв+» в Туле учит водить на категорию B, готовя не к сдаче экзамена, а к настоящей жизни за рулём. Профессиональные инструкторы, удобные классы и теория онлайн, свободный график и полное сопровождение в ГАИ на автомобилях школы. Записаться на курс можно на сайте https://drivepluspro.ru/ — там же цены и акции. Доверьте свою подготовку специалистам «Драйв+».

  52. Tomorrowland Thailand 2026 билет с отелем Состав пакета важнее цены: считайте по ночам и гостям. Статья по фразе «Tomorrowland Thailand 2026 билет с отелем» помогает решить вопрос включения проживания в заказ. Актуально для сезона 2026 года.

  53. как проверить продавца билетов Tomorrowland Thailand Страх обмана — главный тормоз перед покупкой через реселлера. Разбор по запросу «как проверить продавца билетов Tomorrowland Thailand» посвящён договору и условиям возврата. Рекомендую сохранить чек-лист перед покупкой.

  54. vip билет tomorrowland 2026 Выбор категории билета часто откладывают до последнего — и зря. Здесь сравниваются включения и ограничения обеих категорий. Стоит сохранить ссылку до старта продаж.

  55. где заказать наркотики где купить трамадол без рецепта Купить Мефедрон трамадол 50мг купить где купить лсд где купить лирику
    купить канабис наркошопы тг купить экстазиhttps://mirnogradkupit.xyz где купить наркотики купить наркотики бот

  56. как купить билеты на tomorrowland После окончания прямой продажи у покупателей начинается паника. Разбор «как купить билеты на tomorrowland» показывает источник предложения после распродажи. Актуально для сезона 2026 года.

  57. как купить билеты на tomorrowland Первый заказ на фестиваль всегда вызывает больше всего вопросов. Ответ на вопрос «как купить билеты на tomorrowland» дан без воды и рекламных обещаний. Российские способы оплаты разобраны отдельно — без общих слов.

  58. tomorrowland vip tickets Сравнение категорий лучше делать до оплаты. Материал по теме «tomorrowland vip tickets» определяет достаточность обычного пропуска. После чтения проще решить вопрос доплаты за VIP.

  59. tomorrowland 2026 тайланд купить билет Предложение после распродажи требует столь же придирчивой проверки. Материал по запросу «tomorrowland 2026 тайланд купить билет» объясняет покупку через агента. Полезно сохранить ссылку до решения по билету.

  60. tomorrowland thailand tickets Многие откладывают покупку из-за непонимания первых шагов. Гайд по теме «tomorrowland thailand tickets» написан для первой покупки. Текст актуален для сезона 2026 года.

  61. где купить наркотики Купить Кокаин, Героин, ЛСД, МДМА, Экстази Купить Мефедрон лирика 300 мг купить купить наркотики телеграмм сайты мефедрон купить
    купить трамадол наличие закладка соли кокаин наркотики купитьhttps://svetlodarskkupit.xyz купить закладку героина амфетамин кокаин купить

  62. Гидроманипулятор для самосвала превращает обычный грузовик в универсальную технику для погрузки, разгрузки и перемещения тяжёлых материалов. Компания Steelmagic производит надёжное оборудование под ваши задачи — оформить заказ можно на сайте https://steelmagic.ru/gidromanipulyator-dlya-samosvala/ Качественная сборка, точное управление и долгий срок службы гарантированы.

  63. tomorrowland thailand vip билеты Comfort-привилегии звучат привлекательно и стоят отдельных денег. Здесь сравниваются включения и ограничения обеих категорий. Учтены и забытые расходы сверх билета.

  64. купить билет Tomorrowland Thailand после распродажи Квоты агентов живут по своим правилам и не зависят от основного старта продаж. Ответ на вопрос «купить билет Tomorrowland Thailand после распродажи» помогает продолжить поиск после sold out. Никакой мистики — только устройство агентского канала.

  65. как купить билеты на tomorrowland Правильная последовательность шагов экономит и время и деньги. Ответ на вопрос «как купить билеты на tomorrowland» дан без воды и рекламных обещаний. Формат подходит для первого заказа на фестиваль.

  66. tomorrowland full madness pass Comfort-привилегии звучат привлекательно и стоят отдельных денег. Материал объясняет разницу между трёхдневным доступом и повышенной категорией. Рекомендую прочитать до оформления заказа.

  67. заказать трамадол нарко каналы тг Купить Мефедрон нарко тг Купить Бошки, Шишки, Мефедрон, Кокаин марихуана гашиш куплю
    купить гашиш экстази купить скорости спб купить меф амфhttps://mirnogradkupit.xyz амфетамин закладкой купить бошки гашиш марихуану экстази в питере

  68. В питомнике «Сакура» производят саженцы плодовых деревьев, декоративные кустарники и хвойные растения с закрытой корневой системой. Каталог и условия доставки по России смотрите на сайте https://sakura-pitomnik.ru/ — там же подбор сортов под ваш регион. Все растения приспособлены к местному климату, приживаются уверенно, а консультацию агронома вы получаете вместе с заказом.

  69. Крым впечатляет дворцами Южного берега, горными маршрутами, бухтами и древними памятниками. На https://crimea-trip.ru/ удобно подбирать идеи для поездок, знакомиться с курортами и планировать насыщенный отдых. Полезные материалы помогут составить маршрут и заранее узнать о местах, которые стоит включить в путешествие.

  70. где купить лирику покупка мефедрона Купить Мефедрон магазины купить меф купить бошки марихуаны купить наркотики спб
    альфа пвп закладки москва трамадол купить в спб купить мефедрон бошкиhttps://volnovakhakupit.xyz меф где купить купить мефедрон магазин

  71. tomorrowland thailand hotel ticket package Сравнивать пакет и раздельную покупку нужно на одинаковых условиях. Разбор «tomorrowland thailand hotel ticket package» отвечает на вопрос выгодности пакета против самостоятельной брони. Текст снимает типовые вопросы по пакетам с проживанием.

  72. Чистый воздух дома — не роскошь, а основа самочувствия. Пыль, аллергены и сухой воздух повышают риск простуд и раздражают слизистые, поэтому очистители с HEPA и увлажнители, держащие влажность около 40–60%, заметно облегчают дыхание. Подробнее о выборе и пользе читайте на https://igropoisk.com/ochistiteli-i-uvlazhniteli-vozduha-zabota-o-zdorove.html — там ясно, как техника помогает семье дышать свободнее каждый день.

  73. купить амфетамин мефедрон телеграмм купить Купить Мефедрон где купить альфа пвп где купить трамадол без рецепта трамадол 50 мг таблетки купить
    марихуана можно купить гашиш тг нарко тгhttps://selidovokupit.xyz телеграм купить меф где купить наркотики

  74. Устроить водоём на своём участке несложно: понадобятся готовая чаша или плёнка, насос и фильтр. Более двух десятилетий «Салон Глобус» поставляет товары для водоёмов — аэраторы, средства очистки, фонтаны и светильники. Выбрать оборудование и заказать доставку можно на сайте https://www.globussalon.ru/ без лишних хлопот. Специалисты бесплатно рассчитают материалы, подберут фильтры и помогут ухаживать за готовым водоёмом.

  75. Городской воздух в комнате нередко кажется чистым, хотя в нём остаются пыль, пыльца и шерсть. Smartmi Air Purifier 2 тихо фильтрует поток, прост в управлении и уместен в спальне или гостиной. Обзор модели — на https://moskva-news.com/smartmi-air-purifier-2-chistyj-vozduh-kak-chast-domashnego-komforta/ : свободная установка и своевременная смена фильтра помогают держать дом свежим.

  76. лирика 300мг купить где можно купить лирику Купить Мефедрон нарко каналы тг нарко тг купить рецепт на лирику
    где можно купить мефедрон где купить героин купить бошки гашиш марихуану экстази в эмиратахhttps://torezkupit.xyz купить закладку мефедрона нарко тг

  77. blackjack online with friends no money casino online 2026
    kasГ­na s minimГЎlnym vkladom 10 eur online kasina bonusy bez vkladu zahraniДЌnГ­ online casino bonus za registraci bez vkladu Casino 5 eur 300 free spinov za registraciu smart live casino
    live dealer blackjack online online hry zadarmo automaty

  78. tomorrowland 2026 тайланд билеты цена Считать бюджет по цене каталога — типичная ошибка новичков. Статья «tomorrowland 2026 тайланд билеты цена» помогает сопоставить стоимость с бюджетом всей поездки. Отдельно упомянуты расходы на дорогу и проживание.

  79. меф заказать купить меф мяу мяу Купить Мефедрон купить наркотики в москве купить коноплю мощную Купить Кокаин, Героин, ЛСД, МДМА, Экстази
    где купить экстази наркошопы телеграмм где можно купить коноплюhttps://khartsyzskkupit.xyz трамадол 50 мг купить Купить Марихуану, Мефедрон, Гашиш, Кокаин

  80. tomorrowland2026.ru не кидалово Каждый сезон кто-то переводит деньги первому попавшемуся сайту. Разбор по запросу «tomorrowland2026.ru не кидалово» посвящён договору и условиям возврата. Рекомендую сохранить чек-лист перед покупкой.

  81. tomorrowland отель билет Вопрос билета с отелем или без него решается расчётом. Сравнение «tomorrowland отель билет» построено для одного числа гостей и ночей. Никакой рекламы — только состав и цифры.

  82. где купить билеты Tomorrowland Thailand после sold out После окончания прямой продажи у покупателей начинается паника. Материал по фразе «где купить билеты Tomorrowland Thailand после sold out» описывает каналы и квоты без мистики. Перечислены условия для принятия до оплаты.

  83. tomorrowland vip tickets Повышенная категория — это про удобство. Материал по теме «tomorrowland vip tickets» определяет достаточность обычного пропуска. После чтения проще решить вопрос доплаты за VIP.

  84. Автошкола «ДРАЙВ+» в Туле готовит водителей категории B по-настоящему уверенно. За обучение отвечают практикующие инструкторы, программа гибко адаптируется к вашему ритму. Ищетеправа категории б стоимость обучения в туле? Подробности и запись — на сайте drivepluspro.ru — теория, площадка и город без спешки. Атмосфера комфортная, придирок нет. Результат — права и реальный навык вождения.

  85. Екатеринбургская компания «Экспресс-связь» выпускает бытовки: прочные, функциональные, пригодные для использования на стройплощадках, загородных участках и производственных территориях. Изделия изготовлены из высококачественного металла с защитным покрытием и тепловой изоляцией, адаптированы к жёстким климатическим условиям Урала. Ищете пожарной сигнализации екатеринбург? Все подробности о продукции и услугах — на express-svyaz.ru — производство бытовок под заказ с доставкой по региону и профессиональной комплектацией под любые задачи.

  86. купить мефедрон гашиш кокаин купить меф амф Купить Мефедрон купить лирика 150 купить закладку меф трамадол таблетки купить в москве
    купить скорости спб купить соли мефедрон купить марихуану мефедронhttps://volnovakhakupit.xyz амфетамин кокаин купить нарко каналы тг

  87. kasino online automaty online casino vklad cez sms
    bonus za registraciu bez vkladu Which bet gives you a bonus without deposit hra za peniaze Free spin bonus na automatoch big bamboo casino slovenske online casino bonus bez vkladu
    casino online princess novГ© hracie automaty 2026

  88. купить соль наркотик капсулы лирика купить Купить Мефедрон магазины закладок наркотиков кокаин марихуана купить где купить тест на наркотики
    куплю коноплю спб кокаин наркотики купить купить скорости спбhttps://ilovaiskkupit.xyz лирика 300 купить купить наркотики в москве

  89. купить коноплю мощную купить закладку героина Купить Мефедрон мефедрон телеграмм купить купить метадон купить наркотики телеграмм
    купить гашиш экстази закладки наркотики кокаин марихуана купитьhttps://khartsyzskkupit.xyz трамадол можно купить без рецепта мефедрон телеграмм купить

  90. Планируете отдых у моря? Сайт jus.su поможет подобрать тур мечты быстро и без хлопот. Здесь вы найдёте обширную базу актуальных предложений, обновляемых в реальном времени, а удобные фильтры по городу вылета, длительности отдыха и числу туристов ускорят поиск. Загляните на https://jus.su/ — пара кликов, и подходящий пакет уже у вас в руках. Надёжность туров гарантирована, а значит, вас ждут только положительные эмоции и комфортное путешествие от начала до конца.

  91. najlepsie bonusove automaty casino 5 euro no deposit bonus
    spinit casino online cherry pop slot 10 euro no deposit casino bonus Automaty hry free spiny zadarmo bez vkladu casino v mobile
    casino online nove najlepsie vstupne bonusy

  92. лирика купить спб где купить экстази Купить Мефедрон Купить Марихуану, Мефедрон, Гашиш, Кокаин купить меф мяу мяу купить наркотики телеграм
    марихуана закладки купить гашиш шишку лирика 300мг купитьhttps://mangushkupit.xyz купить закладки марихуаны можно купить наркотики

  93. «Модерра» — модульная гардеробная система, которая наводит порядок в доме. Гардеробная система хранения собирается под ваши размеры и задачи: полки, штанги, ящики, напольные вешалки. Оформить заказ и посмотреть каталог можно на https://indrev.ru/mebel/ — гардеробную систему купить получится без переплат. Сборка занимает минимум времени, а набор модулей всегда можно перекомпоновать.

  94. online casino cez sms 5 euro no deposit bonus
    grande vegas casino free spiny doxxbet pokerovГ© hracie automaty Free spin bonus nove online casino slovensko online casino na slovensku
    automati hry zdarma casino bonus vklad

  95. трамадол купить в спб купить наркотики бот Купить Мефедрон купить альфа закладка нарко бот тг где купить канабис
    где купить кокаин купить ганджубас меф гаш купитьhttps://snezhnoekupit.xyz 1 грамм мефедрона купить наркотики москва

  96. twin casino vip hry automaty zdarma 77
    hrat hracie automaty zdarma bez registrace Can I win real money with free spins euro grand casino Casina na slovensku 5 euro bonus no deposit automaty online vklad cez mobil
    nove online casino bonus bez vkladu zeus vs hades demo

  97. заказать коноплю дмт купить Купить Мефедрон купить наркотики мефедрон трамадол таблетки купить в москве купить коноплю мощную
    купить мдма мефедрон дмт купить Купить Бошки, Шишки, Мефедрон, Кокаинhttps://nikolskoekupit.xyz купить меф амф мдма купить

  98. the best online blackjack stars casino $50 bonus
    blackjack online players nike sk free spiny star casino bonus za registrГЎciu bez vkladu Free spiny v slovenskych casinach vyherne automaty online zadarmo casino volne spiny
    winspark 5 € výherné automaty online za peniaze

  99. можно купить наркотики альфа пвп купить Купить Мефедрон магазины закладок наркотиков купить героин кокаин закладку со скоростью
    купить закладки марихуаны купить гашиш закладки трамадол 100 купитьhttps://soledarkupit.xyz сколько стоит мефедрон лирика 300мг купить

  100. brite ab casino hry automaty zdarma kartove
    retro hracie automaty zdarma hracie automaty sturovo 5 valcove hracie automaty s davkou modernosti Kajot online online casino registracia ruleta automati zdarma
    hracГ­ automaty stГЎhnout zdarma fortuna casino vstupny bonus

  101. гашиш москва купить лирику в москве Купить Мефедрон где купить наркотики можно ли купить лирику без рецепта трамадол 50 мг купить
    покупка мефедрона купить наркотики онлайн где купить лирику без рецептаhttps://berdyanskkupit.xyz купить наркотик магазин где можно купить марихуану

  102. Школа-студия парикмахерского искусства — это ваш быстрый старт в востребованной профессии. Уже после короткой трёхдневной теории ученики приступают к практике на реальных клиентах. В программе — мужские, женские и детские стрижки, вечерние и свадебные укладки, плетение кос, химическая завивка и углублённая колористика с современными техниками окрашивания. Опытные практикующие мастера помогут освоить ремесло с нуля. Подробности, цены и индивидуальный расчёт — на сайте https://j-center.ru/ где стоит записаться на ближайший набор.

  103. volne otocky casino bonus bez vkladu hracie automati kajoti zadarmo
    online casino slovakia bonus online kasino hracie automaty hracie automaty demo Vklad 1 eur ako urobiЕҐ ruletu s obrГЎzkami online kings casino live stream
    hraci automat anglicky free spiny online

  104. где купить экстази телеграм купить меф Мефедрон купить, кокаин купить сайт купить марихуану где можно купить марихуану где можно купить трамадол
    где можно купить наркотики купить метамфетамин закладку со скоростьюhttps://orskkupit.xyz заказать канабис купить меф мяу мяу

  105. hrat automaty zdarma sizzling hot vГЅhernГ­ automaty online
    blackjack online without money live casino login casino vstupnГ­ bonus bez vkladu Retro automaty bez poplatku casino 1 euro deposit vstupny bonus online casino
    casino 10 euro deposit hry automaty zdarma kajot

  106. купить марихуану в москве мефедрон в москве Мефедрон купить, кокаин купить лирика 300 купить кокаин гашиш купить купить наркотик магазин
    1 грамм мефедрона купить гашиш марихуану мефедрон бошки мефедрон тгhttps://rybinskkupit.xyz заказать кокаин меф гаш купить

  107. Собираетесь работать с компаниями бренда RUXING — грузоперевозки из Китая, гранит или импорт авто? Прежде чем переводить деньги, загляните на независимый архив-расследование https://ruxing-reviews.info/, где по открытым источникам, договорам и судебной практике собраны реальные отзывы клиентов, разбор споров и ключевые риски: рост цены постфактум, недостача груза и слабая защита в договоре. Материал поможет проверить контрагента и принять взвешенное решение.

  108. hracie automaty zdarma multy 5 automaty online s ceskou licenci
    sk casino no deposit bonus kasГ­no s bonusom bez vkladu hracie automaty pixel Online kasino s vyhrou penazi How many types of gambling games are there casino s bonusom za registraciu
    hracie automaty zdarma bez registrace lucky lady b casino bonus

  109. где можно купить лирику купить бошки Мефедрон купить, кокаин купить трамадол таблетки купить в москве амфетамин закладкой купить марихуану в москве
    кокаин наркотики купить сайт купить наркотики масло конопли купитьhttps://angarskkupit.xyz заказать канабис купить закладку мефедрона

  110. ako vyhraЕҐ v rulete 7e bonus no deposit
    nove casino bonus za registraciu bez vkladu online casino bonus za registrГЎciu bez vkladu joker’s jewels demo Ruleta online za peniaze hracie automaty na kredit novГ© ДЌeskГ© online casino
    live casino real money video blackjack online

  111. Компания «Компэл» через портал https://components.ru/ предлагает широкий выбор электронных компонентов от ведущих мировых и российских производителей. Здесь вы найдёте микросхемы, датчики, разъёмы, источники питания и модули для любых задач — от прототипа до серийного производства. Удобный поиск, техническая поддержка инженеров, актуальные складские остатки и оперативная доставка делают закупку простой и надёжной для профессионалов рынка.

  112. гашиш можно купить альфа пвп закладки москва Мефедрон купить, кокаин купить трамадол купить без рецепта купить гашиш экстази мефедрон тг
    альфа пвп закладки москва купить мефедрон гашиш кокаин где можно купить таблетки трамадолhttps://lyubertsykupit.xyz меф гаш купить можно купить коноплю

  113. tipos online hracie automaty bonus za registrace bez vkladu
    online casino bonus bez vkladu s moznostou vyberu hry o skutocne peniaze 7 reels casino review Novo spustene kasino na slovensku hracГ­ automaty stГЎhnout zdarma city club casino
    quatro casino 700 free spins blackjack online zdarma

  114. где можно купить гашиш сорта конопли купить Мефедрон купить, кокаин купить лирика таблетки купить без рецептов марихуана можно купить где можно купить мефедрон
    купить рецепт на трамадол купить тгк конопля купить мдма мефедронhttps://pervouralskkupit.xyz магазин марихуаны купить купить кокаин онлайн

  115. Культ Профита объединяет трейдеров, даёт инструменты для торговли и открытую аналитику без лишних обещаний. Тут есть рейтинг участников, турнир «Аналитик месяца», журнал сделок и связка с биржевыми аккаунтами. Реальная статистика по BTC и SOL доступна на сайте https://kultprofita.ru/ — присоединяйся, торгуй в привычном режиме и проверяй свои навыки в честном рейтинге.

  116. automaty zdarma turbo alchemy automaty hry zdarma sis link
    online automaty za penize hracie automaty kajot zadarmo synot hracГ­ automaty online Kasino od 5 eur vklad super hry automaty zdarma kajot bonus 5 eur
    hracie automaty s bonusom hry vГЅhernГ­ automaty zdarma

  117. меф заказать купить мефедрон гашиш кокаин Мефедрон купить, кокаин купить трамадол таблетки купить в москве где купить гашиш сорта конопли купить
    заказать таблетки трамадол заказать гашиш трамадол 50 мг таблетки купитьhttps://ussuriyskkupit.xyz купить метадон где купить лирику без рецепта

  118. покупка мефедрона меф где купить Мефедрон купить, кокаин купить купить экстази бошки гашиш в эмиратах покупка мефедрона мефедрон в москве
    закладки купить меф купить через закладки купить метадонhttps://blagoveshchenskkupit.xyz наркошоп сайт где можно купить коноплю

  119. Производитель «СД Мебель» предлагает офисную мебель: кабинеты руководителя, столы для персонала, стойки ресепшен, кресла, шкафы-купе и перегородки. Весь ассортимент с ценами представлен на сайте https://cdmebel.ru/ — заказ оформляется онлайн. Продукция сертифицирована по ГОСТ, сроки изготовления минимальны, а в список услуг входят дизайн-проект, доставка и профессиональная сборка.

  120. Магазин шины-киров.рф — это широкий выбор автомобильных шин и дисков под любой сезон и бюджет. Ассортимент включает бренды Yokohama, Pirelli, Hankook, Kama, Viatti и десятки других изготовителей легковых, грузовых и спецтехнических покрышек. Оформить заказ и подобрать резину по размеру можно на сайте https://xn—-dtbqbjqkp0e6a.xn--p1ai/ прямо сейчас. Клиентам доступны фирменный шиномонтаж и быстрая доставка по Кирову.

  121. free spiny nedela automaty online realne peniaze
    online blackjack strategy casino hracie automaty zdarma bonusovГ© kГіdy casino Automaty online hrat hracie automaty zdarma hunters Which online casino actually pays real money
    live online casino playtech live casino

  122. Зимой батареи сушат воздух, кожа стягивается, пыль не оседает. Испарительный Smartmi Evaporative Humidifier 3 Lite увлажняет иначе: диски и вентилятор отдают влагу без тумана и белого налёта на мебели. Как он устроен и кому подходит, читайте на https://interiorizm.com/uvlazhnitel-vozduha-smartmi-evaporative-humidifier-3-lite-komfortnyy-klimat-bez-lishnih-hlopot бак четыре литра до четырнадцати часов, до двухсот восьмидесяти миллилитров в час на двадцать пять квадратных метров, доливка сверху, тихий ночной режим, Mi Home, Алиса, самоочистка, диски моют водой, фильтры не нужны.

  123. Промышленное водоочистное оборудование эффективно на объектах любого масштаба: удаляет металлы, соли жёсткости, бактерии и механические частицы. Ищете промышленная установка очистки воды? Подобрать оборудование под ваш источник поможет pws.world/promyshlennye-ustanovki — здесь представлены готовые комплексы и индивидуальные решения. Очищенная вода улучшает качество выпускаемой продукции и увеличивает ресурс оборудования.

  124. купить рецепт на лирику где купить альфа пвп Мефедрон купить, кокаин купить трамадол где купить вейп с тгк купить бошки героин
    альфа пвп закладки москва наркошопы россии наркошоп сайтhttps://severodvinskkupit.xyz закладки шишек где купить лсд

  125. parimatch live casino spiny zdarma dnes
    tipos hry hraci automaty zdarma hry zdarma na stiahnutie hracie automaty 3valcove automaty zdarma ultra hot Retro automaty zadarmo Can I play slots online for real money vГЅhernГ­ automati zdarma
    verde casino bonus no deposit free spiny zdarma za registraciu

  126. лирика купить спб купить экстази Мефедрон купить, кокаин купить купить мдма мефедрон трамадол таблетки купить трамадол 100 купить
    купить кокаин марихуану лирика 56 купить трамадол 50 мг таблетки купитьhttps://orskkupit.xyz заказать марихуану кокаин закладками

  127. купить наркотики телеграм можно купить коноплю Мефедрон купить, кокаин купить лирика 56 купить Купить Кокаин, Мефедрон, Бошки, Марихуану купить наркотики в тг
    купить скорости спб канабис можно купить купить наркотики в интернетеhttps://engelskupit.xyz купить кокаин онлайн купить тгк конопля

  128. Настоящая русская баня начинается с ароматного веника: отборный кавказский дуб, берёза из поросли и эвкалипт задают мягкий тон парной, а душистые травы в пучках наполняют воздух целебным теплом. На https://www.parvenik.ru/ свежие поступления оптом и в розницу, удобная выдача по Москве и Подмосковью — отборное качество без лишней наценки, чтобы пар был бархатным, а впечатление осталось как у настоящего мастера.

  129. купить марихуану сайты тест на наркотики купить Мефедрон купить, кокаин купить купить мефедрон гашиш где купить метадона купить экстази бошки гашиш в эмиратах
    купить марихуана питер купить бошки гашиш марихуану лсд экстази лирика таблетки купитьhttps://pervouralskkupit.xyz где можно купить мефедрон тест на наркотики купить

  130. лирика 150 мг купить где заказать наркотики Мефедрон купить, кокаин купить канабис можно купить где можно купить лирику без рецепта где можно купить трамадол
    Купить Мефедрон, Альфа-ПВП, Гашиш, Экстази купить бошки гашиш марихуану экстази в питере купить наркотики москваhttps://khimkikupit.xyz можно купить наркотики купить героин

  131. лирика лекарство купить купить мефедрон амфетамин купить кокаин купить трамадол наличие трамадол где купить купить наркотики онлайн
    где купить лирику трамадол таблетки купить в москве закладки соли альфа пвпhttps://zlatoustkupit.xyz купить наркотики в интернете магазин марихуаны купить

  132. купить гашиш москва модафинил купить купить кокаин лирика купить спб купить меф гашиш трамадол купить в москве
    куплю закладки соли трамадол таблетки цены купить лирика 300мг купитьhttps://nizhnekamskkupit.xyz купить марихуану соль бошки закладки сколько стоит мефедрон

  133. купить гашиш бошки можно ли купить наркотики Мефедрон, кокаин, бошки, гашиш канабис можно купить шишка бошка купить купить мефедрон онлайн
    трамадол 50 мг купить купить рецепт на лирику трамадол таблетки 100 купитьhttps://armyanskkupit.xyz купить марихуану купить скорость меф

  134. «Мото-ДВ» — премиум-продавец на Wildberries с рейтингом 4,7, специализирующийся на мототехнике для настоящих ценителей бездорожья. В каталоге — квадроциклы, мотоциклы и вездеходы Grizzly, Zongshen Tundra, Loncin и Mikilon от 180 000 рублей, включая полноприводные модели 4WD. Загляните в магазин по ссылке https://www.wildberries.ru/seller/250072599 и выберите надёжную технику, которая покорит любую дорогу. Быстрая доставка и проверенное качество гарантированы!

  135. 888 online casino najlepsie bonusove automaty
    tropical tiki slot koho online casino bonus za registraci bez vkladu 2026 Turbo automaty zadarmo blackjack online 1v1 casino dobitie cez sms
    online casino s licenciou kajot casino 70 free spins

  136. гашиш москва трамадол где купить Мефедрон, кокаин, бошки, гашиш купить трамадол наличие можно купить таблетки трамадол где купить канабис
    купить трамадол в городе покупка мефедрона кокаин наркотики купитьhttps://luganskkupit.xyz меф гаш купить нарко каналы тг

  137. automaty zdarma joker kasino 81 automaty zdarma hry kajot
    online kasГ­no live slovakia wild81 stars automaty zdarma hracie automaty zdarma hunter’s Hranie o skutocne peniaze 10e no deposit bonus online poker slovensko
    kajot automaty hry zdarma sk online kasina

  138. меф гаш купить лирика 56 купить Мефедрон, кокаин, бошки, гашиш сайт купить наркотики заказать коноплю где купить марихуану
    где можно купить таблетки трамадол купить закладки марихуаны магазин купить коноплюhttps://severodonetskkupit.xyz заказать марихуану сайт закладок наркотики

  139. holdem poker game nove casino slovensko
    hracie automaty kajot hry recenzie online casino slovensko automaty hry zdarma jackpot 6000 Automaty zadarmo how to count cards in blackjack online mr bet bonus 10 €
    casino s nГ­zkГЅm vkladem 1 euro deposit bonus

  140. купить соли мефедрон трамадол купить Мефедрон, кокаин, бошки, гашиш купить марихуана питер телеграм мефедрон мефедрон закладка
    вейп с тгк купить купить мефедрон гашиш закладки купить москваhttps://rovenkikupit.xyz магазин марихуаны купить магазин марихуаны купить

  141. vГЅhernГ­ automaty zdarma kajot nove slovenske casino
    casino bonus 10 banco casino masters live report zahranicne online casino bonus bez vkladu pre slovakov Bonus casino online casino automaty best spigo slots
    polskie automaty online kajot casino live

  142. трамадол таблетки где купить купить мдма мефедрон Мефедрон, кокаин, бошки, гашиш закладка соли закладки шишек где можно купить марихуану
    купить марихуану шишка бошка купить где продают гашишhttps://1klad.com куплю гашиш марихуану лирика 75 мг купить

  143. bonus slot no deposit nove casino bez vkladu
    sizzling hot zdarma automaty online poker slovensko licencie automaty hry zdarma online Retro automaty hracie automaty znacky automaty online bonus zdarma 888 casinjo code
    blackjack online zadarmo pre viacerГЅch hrГЎДЌov pachi pachi casino

  144. 1 грамм мефедрона трамадол 50 таблетки купить Мефедрон, кокаин, бошки, гашиш закладки альфа пвп тест на наркотики купить купить канабис
    купить марихуана гашиш бошки где можно купить наркотики купить мефедрон онлайнhttps://chernomorskoekupit.xyz мефедрон можно купить можно купить лирику без рецепта

  145. fortuna promo kГіd americkГ© casino bonus bez vkladu
    vyherni automaty hrat zdarma fortuna vegas casino admiral casino vstupnГЅ bonus Turbo automaty bez vkladu 1 eurovГЅch vkladovГЅch kasГ­n jak funguje casino
    kolik her mГЎ bonver casino golden beauty slot

  146. лирика 300 мг купить купить гашиш шишку купить Мефедрон, Гашиш, Бошки, Альфа-ПВП купить мефедрон онлайн купить закладки марихуаны лирика 75 мг купить
    закладки соли альфа пвп сайт купить наркотики купить мефедрон телеграмhttps://trustzakaz.com конопля купить закладки шишек

  147. automati hry zdarma kajot 27 peniaze zadarmo casino
    blackjack online casino free retro hracie automaty zdarma automaty online kajot Vklad cez sms hrГЎt online automaty online nove casino
    5e no deposit bonus 10 euro deposit bonus

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.