Elektronisches Preisschild Sammelbestellung - Ansteuerung
Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese
- Marsupilami72
- Beiträge: 2879
- Registriert: Mo 4. Nov 2013, 23:48
- Wohnort: mittendrin
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Wir werden das in absehbarer Zeit in einem größeren Gebäude im Harz ausgiebig testen
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Den CC2531 gibt es auch bereits fertig mit SMA-Konnektor. Das Routing der Masseführung zum SMA-Konnektor ist mies, aber denoch ist die Reichweite mit externer 2,4 GHz Antenne deutlich höher (grob 1-2 Räume weiter, Stahlbetondecken machen ohne weitere Router kein Spaß). Wenn das Teil in einem ZigBee 3.0 Netzwerk mit Routern funktionieren würde, wäre dies wohl ein großer Mehrwert.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Arrrr, der Meister wird zufrieden sein!
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
BTW: Was bedeuten die Barcodes am Rand?
- Marsupilami72
- Beiträge: 2879
- Registriert: Mo 4. Nov 2013, 23:48
- Wohnort: mittendrin
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das sind die MAC-Adressen der Schilder
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Wir brauchen jetzt noch eine ordentliche Antenne für den Stick.
Einen 50Ohm Dipol, oder gibbet da was feineres?
Einen 50Ohm Dipol, oder gibbet da was feineres?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Gewöhnliche Wlan-Antennen sollten es tun. Es reichen die für "nur" 2,4 GHz.
MfG. Andreas
MfG. Andreas
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Bisschen Gewinn an der Antenne wäre ja gut.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Je länger die Antenne wird, desto flacher wird die Abstrahlcharakteristik. Der Stummel ist ungefähr kugelförmig, mit einer längeren Antenne wird es dann mehr zu einer flachen Scheibe.
An meinem normalen Zigbee2Mqtt-Stick habe ich eine 5dB-Antenne von einem alten WLAN-Router, da sind allerdings noch 2 Birnen als Repeater dabei.
An meinem normalen Zigbee2Mqtt-Stick habe ich eine 5dB-Antenne von einem alten WLAN-Router, da sind allerdings noch 2 Birnen als Repeater dabei.
- Mechatronk
- Beiträge: 450
- Registriert: So 28. Feb 2021, 23:47
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Was, außer der Bundesnetzagentur, spricht gegen einen Verstärker vor der Antenne?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Achtung: Gewinn gegenüber Kugelstrahler. Davon sollte es nicht zuviel sein (2-5 dBi).
Wenn, dann in Sende- und Empfangsrichtung. 20 dBm EIRP sind bei uns "erlaubt" (EIRP_dBm = Ausgangsleistung_Verstärker_dBm + Antennengewinn_dBi).Mechatronk hat geschrieben: ↑Fr 14. Okt 2022, 13:22 Was, außer der Bundesnetzagentur, spricht gegen einen Verstärker vor der Antenne?
- Mechatronk
- Beiträge: 450
- Registriert: So 28. Feb 2021, 23:47
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Mal fabulieren: Hmm, also ein einem Ende stöpselt man den CC2531 mit möglichst kurzem Verbindungskabel an, am anderen Ende eine Antenne. Der CC2531 sendet und das Ding verstärkt es. Soweit klar, aber was ist mit eingehenden Signalen von den Schildern? Oder fängt der einfach ALLES im 2,4GHz auf und drückt es nachgebrannt in Richtung CC2531 der sich dann aussuchen soll was er braucht?Mechatronk hat geschrieben: ↑Fr 14. Okt 2022, 14:39 https://www.ebay.de/itm/114337978055 sollte es tun, oder ?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Ich hab an der aktuellen Station.py geschraubt und einen "Discovery-Modus" eingebaut:
führt man die station.py --d aus, läuft sie im Discovery-mode
dann erzeugt sie für jedes Schild was sich an der Station anmeldet eine mac.png Datei mit einem Musterinhalt und eingebettet einen Text zuzüglich des Aktualisierungs- Datum und Zeit.
Dafür braucht man eine muster.png im richtigen Format und die FreeMonoItaly.ttf
Wenn ich herraus gefunden habe wie das mit git geht mach ich einen branch oder wie das heisst.
Bis dahin schicke ich die Dateien per PN raus.
führt man die station.py --d aus, läuft sie im Discovery-mode
dann erzeugt sie für jedes Schild was sich an der Station anmeldet eine mac.png Datei mit einem Musterinhalt und eingebettet einen Text zuzüglich des Aktualisierungs- Datum und Zeit.
Dafür braucht man eine muster.png im richtigen Format und die FreeMonoItaly.ttf
Wenn ich herraus gefunden habe wie das mit git geht mach ich einen branch oder wie das heisst.
Bis dahin schicke ich die Dateien per PN raus.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Schick es doch dem Originalautor. Vielleicht nimmt er es gleich in den Master Branch.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Bei der neuen Firmware ist ein Firmware OTA möglich, also per Funk.
Dazu legt man einfach die entsprechende bin Datei in den Ordner der station.py
Die Software muss natürlich neuer sein als die Installierte.
Dann zieht sich das Display die neue Firmware.
Dazu legt man einfach die entsprechende bin Datei in den Ordner der station.py
Die Software muss natürlich neuer sein als die Installierte.
Dann zieht sich das Display die neue Firmware.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das ist ein nettes Feature. Aber erst mal muss ich verstehen, was ich da machen muss.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Also diese Grafikzeugs ist ja ätzend.
Ich will doch einfach nur Text mit Python Pillow so generieren, das es als harte Pixelschrift heraus kommt.
So sieht die Schriftart aus:
So sieht die dann in der png Datei nach der Ausgabe aus:
Total verwaschen und das Display rechnet dass dann wieder in 1-Bit BMP um
Wie macht man es so, das es nachher richtig heraus kommt?
So:
und nicht so:
Ich will doch einfach nur Text mit Python Pillow so generieren, das es als harte Pixelschrift heraus kommt.
So sieht die Schriftart aus:
So sieht die dann in der png Datei nach der Ausgabe aus:
Total verwaschen und das Display rechnet dass dann wieder in 1-Bit BMP um
Wie macht man es so, das es nachher richtig heraus kommt?
So:
und nicht so:
- Marsupilami72
- Beiträge: 2879
- Registriert: Mo 4. Nov 2013, 23:48
- Wohnort: mittendrin
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Da ist offensichtlich Antialiasing aktiviert - hast Du mal den Quelltext?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das ist mit Python Pillow erstellt.
Zuerst eine RGB 128x296 Fläche in weiß und dann der Text drauf.
Das passiert aber auch bei gimp.
Zuerst eine RGB 128x296 Fläche in weiß und dann der Text drauf.
Das passiert aber auch bei gimp.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das hat geklappt
Nun muss das noch bei python Pillow klappen.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das Thema Schrift und Antialiasing.
Wenn man das Bild zum Upload komplett im Gimp oder Windows Malprogramm erstellt müsste es ohne Probleme klappen, wenn man keine Graustufen/Helligkeitsstufen im Bild hat die gedithert werden müssen.
Verwendet man aber TrueType Fonts in Python wird es hässlich.
Es klappt, wenn man die ttf in bfd und dann in .pil umwandelt.
Man muss sich zuerst eine Schriftart herauspicken und dann in bdf wandeln mit der Ziel-Schriftgröße
otf2bdf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraSe.ttf -p 15 -o test15.bfd
diese wird dann in das Python Format gewandelt und steht dann für Python Pillow als Bitmap Schriftart zur Verfügung
./converts.py test15.bfd
Mit diesem Script hab ich das Schild geschrieben, es muss eine Grafik erstellt werden mit 296x128 Pixeln,
in die schreibt man dann den Text.
Zum Schluss dann noch in die Vertikale drehen.
muster.py
converts.py
Wenn man das Bild zum Upload komplett im Gimp oder Windows Malprogramm erstellt müsste es ohne Probleme klappen, wenn man keine Graustufen/Helligkeitsstufen im Bild hat die gedithert werden müssen.
Verwendet man aber TrueType Fonts in Python wird es hässlich.
Es klappt, wenn man die ttf in bfd und dann in .pil umwandelt.
Man muss sich zuerst eine Schriftart herauspicken und dann in bdf wandeln mit der Ziel-Schriftgröße
otf2bdf /usr/share/fonts/truetype/ttf-bitstream-vera/VeraSe.ttf -p 15 -o test15.bfd
diese wird dann in das Python Format gewandelt und steht dann für Python Pillow als Bitmap Schriftart zur Verfügung
./converts.py test15.bfd
Mit diesem Script hab ich das Schild geschrieben, es muss eine Grafik erstellt werden mit 296x128 Pixeln,
in die schreibt man dann den Text.
Zum Schluss dann noch in die Vertikale drehen.
muster.py
Code: Alles auswählen
#!/usr/bin/python3
import os
from PIL import Image, ImageDraw, ImageFont
import time
if 1>=1:
muster=Image.new("RGB",(296,128),color=(255,255,255))
named_tuple = time.localtime() # get struct_time
time_string = time.strftime("%m/%d/%Y, %H:%M:%S", named_tuple)
im = ImageDraw.Draw(muster)
font = ImageFont.load("./fonts/test24.pil")
im.text((10,20),"Christian Finger" ,fill=(0, 0, 0),font=font)
font = ImageFont.load("./fonts/test.pil")
im.text((25,60),"Weltherrschaft" ,fill=(255, 0, 0),font=font)
im.rectangle((22,94,250,120),fill=(255,0,0))
im.rectangle((24,95,251,121),outline=(0,0,0,),width=2)
font = ImageFont.load("./fonts/test15.pil")
im.text((30,95),"spätestens bis 2025" ,fill=(255,255,255),font=font)
muster=muster.rotate(angle=90,expand="true")
#muster.show()
muster.save('00000282ddc83b15.png'
converts.py
Code: Alles auswählen
#!/usr/bin/python3
#
# The Python Imaging Library
# $Id$
#
# PIL raster font compiler
#
# history:
# 1997-08-25 fl created
# 2002-03-10 fl use "from PIL import"
#
from __future__ import print_function
import glob
import sys
# drivers
from PIL import BdfFontFile
from PIL import PcfFontFile
VERSION = "0.4"
if len(sys.argv) <= 1:
print("PILFONT", VERSION, "-- PIL font compiler.")
print()
print("Usage: pilfont fontfiles...")
print()
print("Convert given font files to the PIL raster font format.")
print("This version of pilfont supports X BDF and PCF fonts.")
sys.exit(1)
files = []
for f in sys.argv[1:]:
files = files + glob.glob(f)
for f in files:
print(f + "...", end=' ')
try:
fp = open(f, "rb")
try:
p = PcfFontFile.PcfFontFile(fp)
except SyntaxError:
fp.seek(0)
p = BdfFontFile.BdfFontFile(fp)
p.save(f)
except (SyntaxError, IOError):
print("failed")
else:
print("OK")
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Ich hab mal einen Schildgenerator gebastelt.
Der benötigt allerdings die .pil Schriftarten.
Müsste auch mit ttf gehen, dann muss man umstricken zb:
font = ImageFont.truetype("arial.ttf", 15)
Und sieht nicht so hübsch aus.
https://pillow.readthedocs.io/en/stable ... eFont.html
https://youtu.be/IxK-QpQpxgw
https://youtu.be/LDGm2OOVngA
Der benötigt allerdings die .pil Schriftarten.
Müsste auch mit ttf gehen, dann muss man umstricken zb:
font = ImageFont.truetype("arial.ttf", 15)
Und sieht nicht so hübsch aus.
https://pillow.readthedocs.io/en/stable ... eFont.html
https://youtu.be/IxK-QpQpxgw
https://youtu.be/LDGm2OOVngA
Code: Alles auswählen
#!/usr/bin/python3
import os
from PIL import Image, ImageDraw, ImageFont
import time
Display_Size_x=296
Display_Size_y=128
Name=""
Titel=""
unter=""
while 1:
print("-------------Eingabe Schild-------------------")
mac=""
while ( ((len(mac) <12)) or ((len(mac)>12)) ):
mac=input (" MAC :")
mac=mac.lower()
Name=input (" Name : ")
Titel=input(" Titel: ")
unter=input(" Unterschrift: ")
fileIn="0000"+mac+".png"
print(" MAC: "+fileIn)
print(" Name : "+Name)
print(" Titel: "+Titel)
print(" Unterschrift: "+unter)
muster=Image.new("RGB",(296,128),color=(255,255,255))
named_tuple = time.localtime() # get struct_time
time_string = time.strftime("%m/%d/%Y, %H:%M:%S", named_tuple)
im = ImageDraw.Draw(muster)
font = ImageFont.load("./fonts/test24.pil")
length_name=font.getbbox(Name)
im.text((((Display_Size_x/2)-length_name[2]/2),5),Name ,fill=(0, 0, 0),font=font)
font = ImageFont.load("./fonts/test.pil")
length_name=font.getbbox(Titel)
im.text((((Display_Size_x/2)-length_name[2]/2),45),Titel ,fill=(0, 0, 0),font=font)
font = ImageFont.load("./fonts/test15.pil")
box=font.getbbox(unter)
tboy1=90
tboy2=box[3]+tboy1
tbox1=((Display_Size_x-box[2])/2)
tbox2=((Display_Size_x-box[2])/2)+box[2]
im.rectangle((tbox1-6,tboy1-2,tbox2+6,tboy2+2),fill=(255,0,0),outline=(0,0,0),width=2)
im.text((tbox1,tboy1),unter,fill=(255,255,255),font=font)
muster.show()
ready=input(" OK? y/n :")
if ready=="y":
print(" Excellent")
muster=muster.rotate(angle=90,expand="true")
muster.save(fileIn)
else:
print( " Schade")
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Hier noch die station.py mit Discovery-modus.
Aufrufen mit discovery.py --d
Im Discovery Modus Legt die Station eine MAC-ID.png an, wenn noch keine Datei vorhanden ist, die man dann nach belieben bearbeiten kann.
Auf dem Display wird bei Erfolg dann Discovery und die MAC id angezeigt.
Aufrufen mit discovery.py --d
Im Discovery Modus Legt die Station eine MAC-ID.png an, wenn noch keine Datei vorhanden ist, die man dann nach belieben bearbeiten kann.
Auf dem Display wird bei Erfolg dann Discovery und die MAC id angezeigt.
Code: Alles auswählen
#!/usr/bin/python3
import timaccop
import bmp2grays
from Cryptodome.Cipher import AES
from collections import namedtuple
import struct
import os
import sys
import shutil
import logging
from PIL import Image, ImageDraw, ImageFont
import binascii
import time
from io import BytesIO
parameter=sys.argv
discover=False
if "--d" in parameter:
discover=True
print ("DISCOVER-MODE")
masterkey = bytearray.fromhex("D306D9348E29E5E358BF2934812002C1")
PORT = "/dev/ttyACM0"
EXTENDED_ADDRESS = [ 0x00, 0x12, 0x4B, 0x00, 0x14, 0xD9, 0x49, 0x35 ]
PANID = [ 0x47, 0x44 ]
CHANNEL = 11
IMAGE_WORKDIR = "/tmp/"
PKT_ASSOC_REQ = (0xF0)
PKT_ASSOC_RESP = (0xF1)
PKT_CHECKIN = (0xF2)
PKT_CHECKOUT = (0xF3)
PKT_CHUNK_REQ = (0xF4)
PKT_CHUNK_RESP = (0xF5)
VERSION_SIGNIFICANT_MASK = (0x0000ffffffffffff)
HW_TYPE_42_INCH_SAMSUNG = (1)
HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST = (0xEFF8)
HW_TYPE_74_INCH_DISPDATA = (2)
HW_TYPE_74_INCH_DISPDATA_FRAME_MODE = (3)
HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST = (0x008b)
HW_TYPE_ZBD_EPOP50 = (4)
HW_TYPE_ZBD_EPOP50_ROM_VER_OFST = (0x008b)
HW_TYPE_ZBD_EPOP900 = (5)
HW_TYPE_ZBD_EPOP900_ROM_VER_OFST = (0x008b)
HW_TYPE_29_INCH_DISPDATA = (6)
HW_TYPE_29_INCH_DISPDATA_FRAME_MODE = (7)
HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST = (0x008b)
HW_TYPE_29_INCH_ZBS_026 = (8)
HW_TYPE_29_INCH_ZBS_026_FRAME_MODE = (9)
HW_TYPE_29_INCH_ZBS_025 = (10)
HW_TYPE_29_INCH_ZBS_025_FRAME_MODE = (11)
HW_TYPE_29_INCH_ZBS_ROM_VER_OFST = (0x008b)
TagInfo = namedtuple('TagInfo', """
protoVer,
swVer,
hwType,
batteryMv,
rfu1,
screenPixWidth,
screenPixHeight,
screenMmWidth,
screenMmHeight,
compressionsSupported,
maxWaitMsec,
screenType,
rfu
""")
AssocInfo = namedtuple('AssocInfo', """
checkinDelay,
retryDelay,
failedCheckinsTillBlank,
failedCheckinsTillDissoc,
newKey,
rfu
""")
CheckinInfo = namedtuple('CheckinInfo', """
swVer,
hwType,
batteryMv,
lastPacketLQI,
lastPacketRSSI,
temperature,
rfu,
""")
PendingInfo = namedtuple('PendingInfo', """
imgUpdateVer,
imgUpdateSize,
osUpdateVer,
osUpdateSize,
nextCheckinDelay,
rfu
""")
ChunkReqInfo = namedtuple('ChunkReqInfo', """
versionRequested,
offset,
len,
osUpdatePlz,
rfu,
""")
ChunkInfo = namedtuple('ChunkInfo', """
offset,
osUpdatePlz,
rfu,
""")
logging.basicConfig(format='%(asctime)s %(message)s')
logger = logging.getLogger(__name__)
dsn = 0
def print(*args):
msg = ""
for arg in args:
msg += str(arg) + " "
logger.warning(msg)
def decrypt(hdr, enc, tag, nonce):
cipher = AES.new(masterkey, AES.MODE_CCM, nonce, mac_len=4)
cipher.update(hdr)
plaintext = cipher.decrypt(enc)
#print("rcvd_packet:", plaintext.hex())
#print("rcvhdr:", hdr.hex())
try:
cipher.verify(tag)
return plaintext
except:
return None
def send_data(dst, data):
global dsn
dsn += 1
if dsn > 255:
dsn = 0
hdr = bytearray.fromhex("41cc")
hdr.append(dsn)
hdr.extend(PANID)
hdr.extend(reversed(dst))
hdr.extend(EXTENDED_ADDRESS)
#print("hdr:", hdr.hex())
cntr = int(time.time())
cntrb = struct.pack('<L', cntr)
nonce = bytearray(cntrb)
nonce.extend(EXTENDED_ADDRESS)
nonce.append(0)
#print("nonce:", nonce.hex())
cipher = AES.new(masterkey, AES.MODE_CCM, nonce, mac_len=4)
cipher.update(hdr)
ciphertext, tag = cipher.encrypt_and_digest(data)
out = ciphertext+tag+cntrb
timaccop.mac_data_req(dst, PANID, 12, dsn, out)
def process_assoc(pkt, data):
ti = TagInfo._make(struct.unpack('<BQHHBHHHHHHB11s',data))
print(ti)
ai = AssocInfo(
checkinDelay=900000, #check each 900sec
retryDelay=1000, #retry delay 1000ms
failedCheckinsTillBlank=2,
failedCheckinsTillDissoc=2,# Better enable this by default
newKey=masterkey,
rfu=bytearray(8*[0])
)
print(ai)
ai_pkt = bytearray([ PKT_ASSOC_RESP ]) + bytearray(struct.pack('<LLHH16s8s', *ai))
send_data(pkt['src_add'], ai_pkt)
def prepare_image(client):
is_bmp = 0
filename = bytes(client).hex() + ".png"
#print("Reading image file:" + bytes(client).hex() + ".bmp/.png")
if os.path.isfile(filename):
print("Using .png file ",filename)
elif os.path.isfile(bytes(client).hex() + ".bmp"):
is_bmp = 1
filename = bytes(client).hex() + ".bmp"
print("Using .bmp file ",filename)
else:
if discover==True:
print("DISCOVER "+filename)
generate_discover_image(filename)
src=r'discover.png'
dst=filename
shutil.copyfile(src, dst)
else:
print ("No Image found "+filename)
return 0,0
modification_time = os.path.getmtime(filename)
creation_time = os.path.getctime(filename)
imgVer = int(modification_time)<<32|int(creation_time) # This uses the mofidication time of the image to look for the newest one
file_conv = IMAGE_WORKDIR + bytes(client).hex().upper() + "_" + str(imgVer) + ".bmp" # also use the MAC in case 1 images are created within 1 second
if not os.path.isfile(file_conv):
if is_bmp == 0:
Image.open(bytes(client).hex() + ".png").convert("RGB").save(IMAGE_WORKDIR + "tempConvert.bmp")
bmp2grays.convertImage(1, "1bppR", IMAGE_WORKDIR + "tempConvert.bmp", file_conv)
else:
bmp2grays.convertImage(1, "1bppR", bytes(client).hex() + ".bmp", file_conv)
imgLen = os.path.getsize(file_conv)
return (imgVer, imgLen)
def get_firmware_offset(hwType):
if hwType == HW_TYPE_42_INCH_SAMSUNG:
return HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST
if hwType == HW_TYPE_74_INCH_DISPDATA:
return HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST
if hwType == HW_TYPE_74_INCH_DISPDATA_FRAME_MODE:
return HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST
if hwType == HW_TYPE_29_INCH_DISPDATA:
return HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST
if hwType == HW_TYPE_29_INCH_DISPDATA_FRAME_MODE:
return HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST
if hwType == HW_TYPE_ZBD_EPOP50:
return HW_TYPE_ZBD_EPOP50_ROM_VER_OFST
if hwType == HW_TYPE_ZBD_EPOP900:
return HW_TYPE_ZBD_EPOP900_ROM_VER_OFST
if hwType == HW_TYPE_29_INCH_ZBS_026 or hwType == HW_TYPE_29_INCH_ZBS_026_FRAME_MODE or hwType == HW_TYPE_29_INCH_ZBS_025 or hwType == HW_TYPE_29_INCH_ZBS_025_FRAME_MODE:
return HW_TYPE_29_INCH_ZBS_ROM_VER_OFST
def prepare_firmware(hwType):
filename = 'UPDT{0:0{1}X}.BIN'.format(hwType,4)
#print("Reading firmware file:", filename)
if not os.path.isfile(filename):
#print("No Firmware file available")
return (0,0)
f = open(filename,mode='rb')
f.seek(get_firmware_offset(hwType))
firmwareVersionData = f.read(8)
f.close()
osVer = int.from_bytes(firmwareVersionData, "little") & VERSION_SIGNIFICANT_MASK | hwType << 48
osLen = os.path.getsize(filename)
return (osVer, osLen)
def get_image_data(imgVer, offset, length):
filename = IMAGE_WORKDIR + imgVer + ".bmp"
#print("Reading image file:", filename)
f = open(filename,mode='rb')
f.seek(offset)
image_data = f.read(length)
f.close()
return image_data
def get_fw_data(hwType, offset, length):
filename = 'UPDT{0:0{1}X}.BIN'.format(hwType,4)
print("Reading firmware file:", filename)
f = open(filename,mode='rb')
f.seek(offset)
fw_data = f.read(length)
f.close()
return fw_data
def process_checkin(pkt, data):
ci = CheckinInfo._make(struct.unpack('<QHHBBB6s',data))
print(ci)
imgVer = 0
imgLen = 0
try:
imgVer, imgLen = prepare_image(pkt['src_add'])
except Exception as e :
print("Unable to prepare image data for client", pkt['src_add'])
print(e)
osVer = 0
osLen = 0
try:
osVer, osLen = prepare_firmware(ci.hwType)
except Exception as e :
print("Unable to prepare firmware data for client", pkt['src_add'])
print(e)
pi = PendingInfo(
imgUpdateVer = imgVer,
imgUpdateSize = imgLen,
osUpdateVer = osVer,
osUpdateSize = osLen,
nextCheckinDelay = 0,
rfu=bytearray(4*[0])
)
print(pi)
pi_pkt = bytearray([ PKT_CHECKOUT ]) + bytearray(struct.pack('<QLQLL4s', *pi))
send_data(pkt['src_add'], pi_pkt)
def process_download(pkt, data):
cri = ChunkReqInfo._make(struct.unpack('<QLBB6s',data))
#print(cri)
ci = ChunkInfo(
offset = cri.offset,
osUpdatePlz = cri.osUpdatePlz,
rfu = 0,
)
#print(ci)
try:
if ci.osUpdatePlz:
fdata = get_fw_data(cri.versionRequested>>48, cri.offset, cri.len)
else:
fdata = get_image_data(bytes(pkt['src_add']).hex().upper() + "_" + str(cri.versionRequested), cri.offset, cri.len)
except Exception as e :
print("Unable to get data for version", cri.versionRequested)
print(e)
return
outpkt = bytearray([ PKT_CHUNK_RESP ]) + bytearray(struct.pack('<LBB', *ci)) + bytearray(fdata)
#print("sending chunk", len(outpkt), outpkt[:10].hex() ,"...")
send_data(pkt['src_add'], outpkt)
def generate_pkt_header(pkt): #hacky- timaccop cannot provide header data
bcast = True
if pkt['dst_add'] == b'\xff\xff': #broadcast assoc
hdr = bytearray.fromhex("01c8")
else:
hdr = bytearray.fromhex("41cc")
bcast = False
hdr.append(pkt['dsn'])
hdr.extend(pkt['dst_pan_id'])
hdr.extend(pkt['dst_add'])
if bcast:
hdr.extend(pkt['src_pan_id'])
hdr.extend(reversed(pkt['src_add']))
return hdr
def generate_discover_image(filename):
named_tuple = time.localtime() # get struct_time
time_string = time.strftime("%m/%d/%Y, %H:%M:%S", named_tuple)
muster=Image.new("RGB",(296,128),color=(255,255,255))
im = ImageDraw.Draw(muster)
font = ImageFont.load_default()
output="DISCOVER"
im.text((80, 0),output ,align='center',index=1,fill=(255, 0, 0),font=font)
output=filename
im.text((80, 40),output ,align='center',index=1,fill=(255, 0, 0),font=font)
muster=muster.rotate(-90,expand=True)
font = ImageFont.load_default()
im.text((1, 1),time_string,index=1,fill=(0, 0, 0),font=font)
muster.save('discover.png')
def process_pkt(pkt):
hdr = generate_pkt_header(pkt)
if len(pkt['data']) < 10:
print("Received a too short paket")
print("data", pkt['data'].hex())
return
nonce = bytearray(pkt['data'][-4:])
nonce.extend(reversed(pkt['src_add']))
nonce.extend(b'\x00')
tag = pkt['data'][-8:-4]
ciphertext = pkt['data'][:-8]
plaintext = decrypt(hdr, ciphertext, tag, nonce)
if not plaintext:
print("data", pkt['data'].hex())
print("hdr", hdr.hex())
print("ciph", ciphertext.hex())
print("nonce", nonce.hex())
print("tag", tag.hex())
print("packet is NOT authentic")
return
typ = plaintext[0]
if typ == PKT_ASSOC_REQ:
print("Got assoc request")
process_assoc(pkt, plaintext[1:])
elif typ == PKT_CHECKIN:
print("Got checkin request")
process_checkin(pkt, plaintext[1:])
elif typ == PKT_CHUNK_REQ:
#print("Got chunk request")
process_download(pkt, plaintext[1:])
else:
print("Unknown request", typ)
timaccop.init(PORT, PANID, CHANNEL, EXTENDED_ADDRESS, process_pkt)
print("Station started")
timaccop.run()
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Genialer cliffhanger
Er legte die Batterie ein und was dann geschah!
Er legte die Batterie ein und was dann geschah!
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Fontrendering für low- oder medium-DPI geräte ohne graustufen ist die pest
also heute
früher was das Standarddisziplin. Heute fehlen teils die Funktionen dafür in den Libraries bzw die Renderer sind eigentlich nur noch auf high-DPI und Subpixel-AA getrimmt (oder aber man muss dann lowlevel mit freetype rumzicken um die drölf schichten der Grafikbibliotheken zu umgehen). Deswegen sieht Text heute auch immer blurry aus wenn man nicht viel zeit ins feintuning steckt. Dazu kommt dass die meisten Rederer auch kaum noch ordentlich ohne ebenjenes Subpixelgemurkse arbeiten und so dann zB Stämme von klein-m oder groß-T mal einen, mal zwei pixel breit werden.
IMHO ist der aktuell am wenigsten ekelhafte Weg, gleich Bitmapfonts zu nutzen. Ist zwar auch eklig aber besser als das meiste andere.
also heute
früher was das Standarddisziplin. Heute fehlen teils die Funktionen dafür in den Libraries bzw die Renderer sind eigentlich nur noch auf high-DPI und Subpixel-AA getrimmt (oder aber man muss dann lowlevel mit freetype rumzicken um die drölf schichten der Grafikbibliotheken zu umgehen). Deswegen sieht Text heute auch immer blurry aus wenn man nicht viel zeit ins feintuning steckt. Dazu kommt dass die meisten Rederer auch kaum noch ordentlich ohne ebenjenes Subpixelgemurkse arbeiten und so dann zB Stämme von klein-m oder groß-T mal einen, mal zwei pixel breit werden.
IMHO ist der aktuell am wenigsten ekelhafte Weg, gleich Bitmapfonts zu nutzen. Ist zwar auch eklig aber besser als das meiste andere.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Man sieht hier eignetlich sehr gut die Artefakte die ich meinte:
Oben im Namenstext geht es noch
Weltherrschaft ist auch fett genug.
Der Text in der roten Box: alles; die null in2025, das i in bis, die klötzchen an den kleinen e, das n, mal ein, mal zwei pixel stammbreite
Bitmapfonts nutzen und glücklich sein oder mit viel Hass tief ins Fontrendering eingreifen und feststellen dass die meisten aktuellel (open source) fonts sowieso keine hinting-infos mehr haben bzw die ggf vorhandenen geflissentlich ignoriert werden
(sorry fürs Genöle, aber das ist mein alltäglich Leid, das sieht auf Labeldruckern dann nämlich ähnlich grubbelig aus, aber ich schweife ab)
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Naja, bei einem Klebelabel aus dem Epson/Zebra/Brother wäre mir das völlig egal.
Bei einer dauerhaften Beschriftung vielleicht weniger und ansonsten kann unsere
Druckerei auch Seriendrucke für Topqualität (Werbebeschriftung mit Individualisierung zb) oder Spezialkleber.
Aber generell stimme ich dir zu. Gerade einfaches Text2$bildformat in guter Qualität ist erstaunlich schwierig.
Ich hatte ähnlichen Spaß mit den Kartendruckern (Mitgliedsausweise, Thermotransfer) und gdlib/ImageMagick usw.
Ich würde ja gerne mitbasteln, aber ich warte noch auf mein Paket
Bei einer dauerhaften Beschriftung vielleicht weniger und ansonsten kann unsere
Druckerei auch Seriendrucke für Topqualität (Werbebeschriftung mit Individualisierung zb) oder Spezialkleber.
Aber generell stimme ich dir zu. Gerade einfaches Text2$bildformat in guter Qualität ist erstaunlich schwierig.
Ich hatte ähnlichen Spaß mit den Kartendruckern (Mitgliedsausweise, Thermotransfer) und gdlib/ImageMagick usw.
Ich würde ja gerne mitbasteln, aber ich warte noch auf mein Paket
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Für so Kram wie Versandlabel und co: Ja.
Aber Typenschilder per Thermotransfer...
In 600DPI drucken löst das Problem. Aber eigentlich gibt es halt keinen Grund warum 300DPI mit entsprechend günstigerer Druckhardware nicht reichen würden, wären da nicht jene Probleme
Und naja $alles wenn man was auf LCD oder OLED ausgeben will bei embedded
es sieht dann halt einfach immer gruselig aus
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Kann mir mal jemand bitte die Funktion des $-Zeichen vor manchen Wörtern erklären.
In letzter Zeit habe ich das hier schon einige male gesehen, verstehe es aber nicht
In letzter Zeit habe ich das hier schon einige male gesehen, verstehe es aber nicht
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
In manchen Programmiersprachen wird mit dem Zeichen eine Variable gekennzeichnet. Es drückt also aus, dass man einen beliebigen Vertreter der Spezies meint. Z. B.:
$AUTO = irgendein Auto im Gegensatz zu mein Auto.
$AUTO = irgendein Auto im Gegensatz zu mein Auto.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Ah! Danke für die Info, war mir bisher tatsächlich nicht bekannt.Wieder was gelernt
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Zur station.py:
Oben im Programm ist ein masterkey drin, sollte man den ändern oder es tunlichst unterlassen da dran rumzufummeln?
Edit:
Juchu! Meine sind heute angekommen, vielen vielen Dank dafür!
Nun habe ich mir einen CC2531 geflasht, diese 3V-Brücke habe ich nicht gebraucht, im Gegenteil, wenn die aktiviert war hagelte es verify-Errors beim Flashen mit Brücke. Jetzt ist es anscheinend sauber geflasht.
Aber, es passiert nichts.
Ich habs an einem Raspberry angestöpselt, es wurde auch als /dev/ttyACM0 eingebunden.
discovery.py --d
gestartet. "Station started" meldet es mir. Also ein Schild genommen, Deckel ab, Batterien raus, Batterien rein und es ganz dicht an die Antenne gelegt. Aber es passiert so nüscht. Gar nüscht. Weder auf dem Schild noch in der Konsole.
Dann habe ich im discovery.py mal alle auskommentierten print-Befehle einkommentiert in der Hoffnung das irgendwas kommt. Aber nichts kommt. Nächstes Schild, gleicher Effekt. Nichts.
Jetzt weiß ich nicht weiter an welchem Ende ich suchen könnte.
Kann man dem timaccop.run() noch irgendeine Debug-Option mitgeben, im Moment weiß ich eben nicht ob der CC2531 irgendwas macht.
Edit2:
Jetzt habe ich den Stick an einen PC (war vorher Raspberry) angeschlossen und es geht.
Am Raspberry hatte ich den Kanal auf 20 umgestellt, kann es daran gelegen haben?
Edit3:
Jaaaa, wenn man sich nur einmal mit dem Zeug beschäftigen würde was man so macht!
Im ZBS-Flasher liegt ein "firmware_ch11_low_power" Ordner. Naaa, was der wohl macht Herr Phettsack??
Kanal 11 ist also hardverdrahtet in der Firmware.
Oben im Programm ist ein masterkey drin, sollte man den ändern oder es tunlichst unterlassen da dran rumzufummeln?
Edit:
Juchu! Meine sind heute angekommen, vielen vielen Dank dafür!
Nun habe ich mir einen CC2531 geflasht, diese 3V-Brücke habe ich nicht gebraucht, im Gegenteil, wenn die aktiviert war hagelte es verify-Errors beim Flashen mit Brücke. Jetzt ist es anscheinend sauber geflasht.
Aber, es passiert nichts.
Ich habs an einem Raspberry angestöpselt, es wurde auch als /dev/ttyACM0 eingebunden.
discovery.py --d
gestartet. "Station started" meldet es mir. Also ein Schild genommen, Deckel ab, Batterien raus, Batterien rein und es ganz dicht an die Antenne gelegt. Aber es passiert so nüscht. Gar nüscht. Weder auf dem Schild noch in der Konsole.
Dann habe ich im discovery.py mal alle auskommentierten print-Befehle einkommentiert in der Hoffnung das irgendwas kommt. Aber nichts kommt. Nächstes Schild, gleicher Effekt. Nichts.
Jetzt weiß ich nicht weiter an welchem Ende ich suchen könnte.
Kann man dem timaccop.run() noch irgendeine Debug-Option mitgeben, im Moment weiß ich eben nicht ob der CC2531 irgendwas macht.
Edit2:
Jetzt habe ich den Stick an einen PC (war vorher Raspberry) angeschlossen und es geht.
Am Raspberry hatte ich den Kanal auf 20 umgestellt, kann es daran gelegen haben?
Edit3:
Jaaaa, wenn man sich nur einmal mit dem Zeug beschäftigen würde was man so macht!
Im ZBS-Flasher liegt ein "firmware_ch11_low_power" Ordner. Naaa, was der wohl macht Herr Phettsack??
Kanal 11 ist also hardverdrahtet in der Firmware.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Meine sind auch angekommen. Vielen Dank Hightech.
Mein CC2531 habe ich geflasht, station.py meldet auch Station started aber die Displays pairen sich nicht. Weis Jemand, wie man sehen kann, was der CC2531 Stick macht? Und was hat es mit der LED auf sich? Beim Einstecken leuchtet die grün und geht dann aus, sobald die Station gestartet ist.
Mein CC2531 habe ich geflasht, station.py meldet auch Station started aber die Displays pairen sich nicht. Weis Jemand, wie man sehen kann, was der CC2531 Stick macht? Und was hat es mit der LED auf sich? Beim Einstecken leuchtet die grün und geht dann aus, sobald die Station gestartet ist.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Die "Pairen" sich nur, wenn eine passende macID.png Datei vorliegt, einfach mal die Ausgabe der Station.py beobachten.
Man kann auch das Display debuggen, wenn man an dem Pin UartTx des Display mitschneidet.
Man kann auch das Display debuggen, wenn man an dem Pin UartTx des Display mitschneidet.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Mhm. Ich steige schon im Discovery-Script in Zeile 2 aus
Also sag ich
und bekomm gesagt
Also googel ich, finde das hier (die Antwort mit den 22 Punkten, die genau meinen Fall beschreibt), und dort steht, dass das Modul, wenn man's laden will, oft anders heisst als wenn man's benutzen will (warum zur Hölle). Also im Beispiel bei denen z.B. hiesse es python-aalib und nicht aalib. Man soll also...
Pypi kennt das Modul aber nicht.
Irgendwie geht es mir bei Python immer so. Ich wunder mich im Rückblick immer wieder, wie ich die zwei, drei Programme zusammengekriegt hab, die bei mir laufen.
Kann mich jemand auf den rechten Weg bringen, bitte?
(System ist MacOS 12.6 mit Python 3.9.6.)
Code: Alles auswählen
ModuleNotFoundError: No module named 'timaccop'
Code: Alles auswählen
python3 -m pip3 install timaccop
Code: Alles auswählen
Defaulting to user installation because normal site-packages is not writeable
ERROR: Could not find a version that satisfies the requirement timaccop (from versions: none)
ERROR: No matching distribution found for timaccop
Code: Alles auswählen
But it actually wrong package name, ... search on pypi site to get the accurate package name
Irgendwie geht es mir bei Python immer so. Ich wunder mich im Rückblick immer wieder, wie ich die zwei, drei Programme zusammengekriegt hab, die bei mir laufen.
Kann mich jemand auf den rechten Weg bringen, bitte?
(System ist MacOS 12.6 mit Python 3.9.6.)
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Du musst schon alle Dateien aus dem git Repository herunter laden. Das Station.Py ist nur die Steuerzentrale.
https://github.com/danielkucera/epaper-station
https://github.com/danielkucera/epaper-station
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Sehr geil! Danke schön. Bis auf eins habe ich jetzt bei allen das discovery.png zu sehen bekommen. Das ist für heute genug Erfolg morgen muss da ein Katzenbild drauf.
Und vielen Dank für Deine Arbeit! Ich hätte mich nie an so etwas herangetraut.
Und vielen Dank für Deine Arbeit! Ich hätte mich nie an so etwas herangetraut.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Die Teile wollen schon minimum 2,9V sehen. Drunter ist die Reichweite =0.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Eine weitere Möglichkeit die Displays mit Inhalt zu bespaßen:
Man nimmt einen ESP32 und kann da ein Display als Station dran laufen lassen.
Die Frage hier ist nur, braucht man noch einen extra Server oder reicht der esp, das hab ich noch nicht raus gefunden
Man nimmt einen ESP32 und kann da ein Display als Station dran laufen lassen.
Die Frage hier ist nur, braucht man noch einen extra Server oder reicht der esp, das hab ich noch nicht raus gefunden
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Ich dachte das macht das station.py Skript von dir im Discovery Modus automatisch?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Ja, im Discovery Modus müsste es so gehen.
Poste mal die Ausgabe der Station.
Hast du die Adresse des Stick korrekt in der Station eingetragen?
Poste mal die Ausgabe der Station.
Hast du die Adresse des Stick korrekt in der Station eingetragen?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Das Projekt kenne ich noch gar nicht, hört sich interessant an. Hast du einen Link dazu?Hightech hat geschrieben: ↑Fr 21. Okt 2022, 23:08 Eine weitere Möglichkeit die Displays mit Inhalt zu bespaßen:
Man nimmt einen ESP32 und kann da ein Display als Station dran laufen lassen.
Die Frage hier ist nur, braucht man noch einen extra Server oder reicht der esp, das hab ich noch nicht raus gefunden
Wäre interessant wenn der ESP ähnlich deinem discovery auch gleich Schilder generieren könnte. Power müsste der doch genug haben.
Wenn man dann auch noch die Texte direkt auf dem ESP ablegen könnte und on demand aussendet.
Ein Schild als repeater an neuralgischen Punkten wäre auch noch was.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
https://github.com/jjwbruijn/ESP32-epaper-station
phettsack hat geschrieben: ↑Sa 22. Okt 2022, 08:22Das Projekt kenne ich noch gar nicht, hört sich interessant an. Hast du einen Link dazu?Hightech hat geschrieben: ↑Fr 21. Okt 2022, 23:08 Eine weitere Möglichkeit die Displays mit Inhalt zu bespaßen:
Man nimmt einen ESP32 und kann da ein Display als Station dran laufen lassen.
Die Frage hier ist nur, braucht man noch einen extra Server oder reicht der esp, das hab ich noch nicht raus gefunden
Wäre interessant wenn der ESP ähnlich deinem discovery auch gleich Schilder generieren könnte. Power müsste der doch genug haben.
Wenn man dann auch noch die Texte direkt auf dem ESP ablegen könnte und on demand aussendet.
Ein Schild als repeater an neuralgischen Punkten wäre auch noch was.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Wenn ich die station.py imDiscovery Mode starte sieht das so aus:
Dann Batterien raus, Batterien rein, Display macht seinen Bootvorgang aber es passiert nichts weiter.
Wenn ich den Stick abstecke kommen diverse Meldungen. Also scheint die station.py mit dem Stick zu kommunizieren. Was habt Ihr für eine Baudrate für den seriellen Port eingestellt?
Code: Alles auswählen
python station.py --d
DISCOVER-MODE
2022-10-22 08:36:50,649 Station started
Wenn ich den Stick abstecke kommen diverse Meldungen. Also scheint die station.py mit dem Stick zu kommunizieren. Was habt Ihr für eine Baudrate für den seriellen Port eingestellt?
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Danke!
Ja, da bräuchte man noch einen Webserver . Könnte wohl sogar bei einem hoster liegen. Der ESP müsste eben nur dran kommen.
Im Moment macht das nur Sinn für Leute die keinen CC2531 haben finde ich.
Ja, da bräuchte man noch einen Webserver . Könnte wohl sogar bei einem hoster liegen. Der ESP müsste eben nur dran kommen.
Im Moment macht das nur Sinn für Leute die keinen CC2531 haben finde ich.
Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung
Mal ne Viertelstunde warten.Kerko hat geschrieben: ↑Sa 22. Okt 2022, 08:41 Wenn ich die station.py imDiscovery Mode starte sieht das so aus:
Dann Batterien raus, Batterien rein, Display macht seinen Bootvorgang aber es passiert nichts weiter.Code: Alles auswählen
python station.py --d DISCOVER-MODE 2022-10-22 08:36:50,649 Station started
Vielleicht sind auch die Batterien vom Schild runter?