Last Updated or created 2025-01-15
To display quotes, changing once per hour.
There is not much to be found for Waveshare 4.2 Epaper.
Except for an Arduino web example.
( see https://www.waveshare.com/wiki/E-Paper_ESP32_Driver_Board )
I reversed engineered the workings, and created a python upload script to push images.
Original workings are a mess.
Per 4 bit of color, high-low switched in a byte.
Black and red separated.
Using a till p encoding over curl commands.
My implementation uses a python script called as:
python3 epaper-pusher.py ~/Downloads/Untitled.png
http://10.1.0.99/EPDI_ 30 times something like http://10.1.0.99/ppppppppppppppppppppppppppppppppppppppppppppppppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppiodaLOAD_ http://10.1.0.99/NEXT_ 30 times something like http://10.1.0.99/pbcdefghijjjjjjffffffoooooooaaabbbbbbeeeedddppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppiodaLOAD_ http://10.1.0.99/SHOW_
NOTES: a = 0000 - - - p = 1111 = 15 30 lines with 1000 bytes ( ending with iodaLOAD_ ) black pixels first block 1 second block 0 red pixels first block 0 second block 1 white pixels first block 1 second block 1 PIXEL Example RBRB BWBW First block 1010 - letter K 0101 - Letter F - second nibble = white Second block 0101 - Letter F 1111 - Letter P - second nibble white
Code
from PIL import Image import numpy import requests url="http://10.1.0.99/" black_pixels = numpy.zeros((400,300)) red_pixels = numpy.zeros((400,300)) def classify_pixel_color(pixel): """ Classify a pixel as black, white, or red. """ r, g, b = pixel[:3] # Ignore alpha if present # Define thresholds for classification if r < 128 and g < 128 and b < 128: return 'black' elif r > 200 and g > 200 and b > 200: return 'white' elif r > 128 and g < 100 and b < 100: return 'red' else: return None def process_image(image_path): """ Process the image and classify its pixels into black, white, or red. """ image = Image.open(image_path) image = image.convert("RGB") # Ensure the image is in RGB mode width, height = image.size pixel_data = image.load() color_counts = {'black': 0, 'white': 0, 'red': 0} for y in range (0, 299): for x in range (0, 399): black_pixels[x][y] = 0 red_pixels[x][y] = 0 for y in range(299): for x in range(399): color = classify_pixel_color(pixel_data[x, y]) if color: color_counts[color] += 1 if color == 'black': black_pixels[x][y] = 1; if color == 'red': red_pixels[x][y] = 1; if color == 'white': black_pixels[x][y] = 1; red_pixels[x][y] = 1; return color_counts, black_pixels, red_pixels def number_to_letter(num): """ Translates a number from 0 to 15 into a corresponding letter (a-p). Args: num (int): The number to translate. Returns: str: The corresponding letter (a-p). """ if 0 <= num <= 15: return chr(ord('a') + num) else: raise ValueError("Number must be between 0 and 15, inclusive.") def print_array_in_chunks(array, chunk_size=1001): current_chunk = "" for item in array: # Convert item to string and add to the current chunk item_str = str(item) if len(current_chunk) + len(item_str) + 1 > chunk_size: # Print the current chunk and reset it current_chunk += "iodaLOAD_" try: requests.get(url + current_chunk, verify=False) if not response.content: # Equivalent to expecting an empty reply pass except requests.exceptions.RequestException as e: # Catch any request-related errors pass current_chunk = item_str else: # Append the item to the current chunk current_chunk += (item_str) current_chunk += "iodaLOAD_" # Print any remaining items in the chunk if current_chunk: try: requests.get(url + current_chunk, verify=False) if not response.content: # Equivalent to expecting an empty reply pass except requests.exceptions.RequestException as e: # Catch any request-related errors pass def switch_in_pairs(arr): # Loop through the array with a step of 2 for i in range(0, len(arr) - 1, 2): # Swap values at index i and i+1 arr[i], arr[i + 1] = arr[i + 1], arr[i] return arr if __name__ == "__main__": import sys if len(sys.argv) < 2: print("Usage: python3 script.py <image_path>") sys.exit(1) image_path = sys.argv[1] try: color_counts, black_pixels, red_pixels = process_image(image_path) try: requests.get(url + "EPDI_" , verify=False) if not response.content: # Equivalent to expecting an empty reply pass except requests.exceptions.RequestException as e: # Catch any request-related errors pass lines=[] for y in range(300): for x in range(0,399,4): first = red_pixels[x][y] second = red_pixels[x+1][y] thirth = red_pixels[x+2][y] fourth = red_pixels[x+3][y] nibble = 0 if (first == 1): nibble = nibble + 8 if (second == 1): nibble = nibble + 4 if (thirth == 1): nibble = nibble + 2 if (fourth == 1): nibble = nibble + 1 lines.append(number_to_letter(nibble)) switched_array = switch_in_pairs(lines) print_array_in_chunks(switched_array) try: requests.get(url + "NEXT_" , verify=False) if not response.content: # Equivalent to expecting an empty reply pass except requests.exceptions.RequestException as e: # Catch any request-related errors pass lines=[] for y in range(300): for x in range(0,399,4): first = black_pixels[x][y] second = black_pixels[x+1][y] thirth = black_pixels[x+2][y] fourth = black_pixels[x+3][y] nibble = 0 if (first == 1): nibble = nibble + 8 if (second == 1): nibble = nibble + 4 if (thirth == 1): nibble = nibble + 2 if (fourth == 1): nibble = nibble + 1 lines.append(number_to_letter(nibble)) switched_array = switch_in_pairs(lines) print_array_in_chunks(switched_array) try: requests.get(url + "SHOW_" , verify=False) if not response.content: # Equivalent to expecting an empty reply pass except requests.exceptions.RequestException as e: # Catch any request-related errors pass except Exception as e: pass