Jingcai/Sunton ESP32-3248S035C – 3.5 inch TFT Display 320*480 pixels with Capacitive Touchscreen – ESP32
An even cheaper solution than post below.
Printed a nice case, let the designing begin.
Going with my friend Vincent to the Whisky Festival, with some of his friends.
Missing the train, buying whisky coins every half hours, some beers afterwards. Fun times.
Bought some cigars accompanying the whiskies.
Seen Wullie Macmorland walking around.
I’ve played pipes in his restaurant several times in the 90’s
Last time I’ve seen him is 10+ years ago, with a great story.
When I walked into his restaurant, he remembered me. And my love for whisky.
Before I could sit down, he called me to his bar.
“I have a whisky you have to try!” He said.
Sneaky with the bottle below the counter, he poured me a “whisky”.
It was disgusting !
I said, “THAT’s not whisky!”
“Yes it is!” he smiled. Safari whisky!
He was laughing at my disgusted face.
“Someone gave it to me, it’s everything but whisky.”
It’s even bad for lamp oil! LOL









Jup, I am a fan of smoky whiskies.
UPDATE:
20250312 – Liquid BBQ smoke whisky delivered ..
Made a cap for a mushroom button, with editable text.


It’s on makersworld:
https://makerworld.com/en/models/1093945
Also made some chair thingies. We have wooden floors and her new chair has pointy feet.


Made using Openscad
difference(){
union(){
cylinder(h=5,d=30);
translate([0,0,1.5]){
difference(){
rotate([20,0,0])
cylinder(h=30,d=25);
rotate([20,0,0])
cylinder(h=30,d=17);
}
}
}
translate([0,0,-5])
cylinder(h=5,d=30);
}
I’ve got a little SDR stick a while ago with some antenna’s.

I’ve got some extra antenna’s
So I was playing around with P2000 and Airplane Radio (tracking overhead planes)

For debugging I used SigDigger
dump1090-mutability --aggressive --interactive --net --net-http-port 8080 --net-sbs-port 30003 git clone https://github.com/Zanoroy/multimon-ng.git cd multimon-ng/ mkdir build cd build cmake .. make rtl_fm -f 169.65M -M fm -s 22050 -p 83 -g 30 | ./multimon-ng -a FLEX -t raw /dev/stdin dump1090-fa --interactive

I bought a cheap esp32 display (4 inch 480×480) from China.
It also has three relays to control lights.
Below is a gallery with default screens.










Flashing OpenHasp was a breeze.
Configure the thing for HA was not so easy.


Install OpenHasp via Hacs on HA.
There is a webinterface on the display, here you have to configure wifi, mqtt and the pages.






Config files used for this first test:
{"page":1,"id":34,"obj":"img","src":"L:/pcb480x480.png","auto_size":0,"w":480}
{"page":1,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":50,"text":"IOTDesigns","value_font":22,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}
{"page":1,"id":2,"obj":"btn","x":10,"y":60,"w":105,"h":90,"toggle":true,"text":"\uE335","text_font":32,"mode":"break","align":1}
{"page":1,"id":3,"obj":"dropdown","x":10,"y":160,"w":170,"h":60,"options":"Option 1\nOption 2\nOption 3\nOption 4"}
{"page":0,"id":1,"obj":"label","x":375,"y":45,"h":40,"w":100,"text":"00.0°C","align":2,"bg_color":"#2C3E50","text_color":"#FFFFFF"}
{"page":1,"id":6,"obj":"slider","x":20,"y":300,"w":440,"h":40,"min":15,"max":85}
Designer at : https://haspdesigner.qrisonline.nl/
4inchdisplay2:
objects:
- obj: "p0b1" # temperature label on all pages
properties:
"text": '{{ states("sensor.livingtemperature") }}°C'
- obj: "p1b2" # light-switch toggle button
properties:
"val": '{{ 1 if states("switch.livingshelly") == "on" else 0 }}'
"text": '{{ "\uE6E8" if is_state("switch.livingshelly", "on") else "\uE335" | e }}'
event:
"up":
- service: homeassistant.toggle
entity_id: "switch.livingshelly"
- obj: "p1b3" # dropdown
event:
"changed":
- service: persistent_notification.create
data:
message: I like {{ text }}
- obj: "p1b6" # Light brightness
properties:
"val": "{{ state_attr('number.dinnertable_brightness_0', 'brightness') if state_attr('number.dinnertable_brightness_0', 'brightness') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: number.dinnertable_brightness_0
brightness: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: number.dinnertable_brightness_0
brightness: "{{ val }}"
NOTE: Dimmer is not working via HA (yet), but mqtt messages are working.

| obj | Type | Description | Extra Parts |
|---|---|---|---|
| btn | Binary | Button | |
| switch | Toggle | Switch | indicator, knob |
| checkbox | Toggle | Checkbox | indicator |
| label | Visual | Label | |
| led | Visual | LED | |
| spinner | Visual | Spinner | indicator |
| obj | Visual | Base Object | |
| line | Visual | Line | |
| img | Visual | Image | |
| cpicker | Selector | Color picker | knob |
| roller | Selector | Roller | selected |
| dropdown | Selector | Dropdown List | selected, items, scrollbar |
| btnmatrix | Selector | Button Matrix | items |
| msgbox | Selector | Messagebox | items, items_bg |
| tabview | Selector | Tabview | items, items_bg, indicator, selected |
| tab | Selector | Tab | |
| bar | Range | Progress Bar | indicator |
| slider | Range | Slider | indicator, knob |
| arc | Range | Arc | indicator, knob |
| linemeter | Range | Line Meter | |
| gauge | Range | Gauge | indicator, ticks |
| qrcode | Visual | Qrcode |
We’ve gone too far.
IA is generating news articles and complete YT video’s.
Also, forums and news articles are made using AI.
Reviews are being generated by vote farms.
Unchecked and being re-ingested by other IA scrapers.
It’s being fed again into other new AI generators.
Content generators are not interested in if the generated content is true.
Just generate traffic and income.
I hate watching a long YT video, voice being generated, story content from ChatGPT and not fact checked.
No new information, just generic information stretched into more time you have to watch.
If there is a disaster, people generate false footage to generate traffic.
I’ll resume this rant in time .. i’m not done
I’ve got a flipper zero at last.
https://flipperzero.one/
I know, it’s more an useful toy than a serious tool.
It’s too limited. But useful for me.
Learning about tools and sub gigahertz monitoring.
I hoped to get a BFFB for it, that will be a big plus.
https://www.justcallmekokollc.com/product/flipper-zero-bffb/31
One of the first things was reflashing the device with Momentum firmware.
I’ve ordered a Wi-Fi Dev Board, so I can use Marauder.
Here are some qFlipper screenshots.





Will add pictures and info about the Wifi dev board.
Some information:
The Flipper Zero is a versatile multi-tool for geeks, hackers, and hardware enthusiasts. It is designed as a portable, open-source device with numerous capabilities for interacting with digital systems and hardware. Here’s an overview of what the Flipper Zero can do:
The Flipper Zero is a powerful tool, but its legality depends on how it is used. Be sure to respect laws and ethical guidelines when exploring its capabilities.
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
A while ago, I bought a small Dehumidifier for my wine cellar.
I liked it a lot, so I bought another for our bedroom.
I saw some posts about people asking which Dehumidifier is supported by Home Assistant.
This one is. The “Eeese Otto Dehumidifier”
This works with the LocalTuya integration.
There are many examples how to integrate LocalTuya in HA which can be found easily using a search on the net. So, I’m not going to explain that.
I could not find a configuration example, that’s why I’ll post that part here.
Pre config:
Gallery of config steps










Developer website information, where to find your credentials.
(And a list of entities)




