Seite 4 von 5

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Di 1. Nov 2022, 15:50
von omega
Hat denn schon jemand was gebastelt um die Teile per ZigBee2MQTT anzusprechen?

Einen CC2531 habe ich (noch) nicht da, aber einen CC1352 inkl. ZigBee Firmware. Das muss doch auch irgendwie gehen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mi 2. Nov 2022, 11:53
von phettsack
Probier doch einfach mal das Zigbee2Mqtt auf Anlernen zu schalten und das Schild (Batterien raus, Batterien rein) dann ganz ganz dicht neben die Antenne zu packen und das Logfile zu beobachten ob da irgendwas kommt.
Ich bin mir aber nicht sicher ob zigbee2mqtt überhaupt eine Funktion hat um Nutzdaten (das Bild) zu übertragen. Das war ursprünglich gedacht um Sensordaten zu empfangen.

Bei ganz wenigen wird auch was gesendet: https://www.zigbee2mqtt.io/devices/mTouch_One.html
Da gäbe es dann display_text , dafür müsste das Schild dann vermutlich eine andere Firmware haben die aus zugesandtem Text ein Bild rendert.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mi 2. Nov 2022, 18:57
von omega
Tja, wenn das so einfach wäre...

Also Pairing passiert nicht, selbst im Debug Modus passiert nichts. Ich sehe aber, dass ein Paket (eigentlich zwei) vom Display gesendet wird, dann aber bereits vom Zigbee Stack verworfen wird, weil es kein gültiges ZigBee Paket sei. Das heißt das Paket geht gar nichts bis zum Rechner und ZigBee2MQTT.

Wenn ich mir die station.py anschauen, sieht mir das aber so aus, als ob die ganze Kommunikation verschlüsselt ist, auch das Pairing?! Hier steige ich aber noch nicht durch wie ich das ZigBee2MQTT klar machen soll. Ein

Code: Alles auswählen

network_key: [ 0xD3,0x06,0xD9,0x34,0x8E, 0x29, 0xE5, 0xE3, 0x58, 0xBF, 0x29, 0x34, 0x81, 0x20, 0x02, 0xC1 ]
führt auch nicht zu Funktion.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mi 2. Nov 2022, 19:12
von Hightech
Das Preisschild läuft definitiv nur mit dem Stick auf dem die TiMac Firmware drauf ist.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mi 2. Nov 2022, 19:36
von omega
Also kein ZigBee, sondern nur sowas ähnliches auf 802.15.4 basierend? Schade...

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 4. Nov 2022, 19:33
von michabe
Andreas_P hat geschrieben: Do 27. Okt 2022, 19:42 Zum Flashen der Preisschilder möchte ich mir einen Stecker drucken den ich auf die Kontakteinflächen der Preisschilder drauf halte,
dazu fehlt mir die Info in welchen Abstand die einzelnen Kontaktflächen zu einander haben. Hat dazu jemand Informationen ?
Ich hab da mal was messen lassen:
Bild

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 4. Nov 2022, 20:48
von omega
Das lässt mir ja doch keine Ruhe... Ich habe jetzt einen 802.15.4 Stack am laufen und bekomme auch Daten, jetzt möchte ich aber nicht den ganzen TIMAC reverse engineeren. Kann mir jemand die Ausgabe die beim ersten pairen von station.py --l --d ausgegeben wird senden?
Idealerweise noch print("pkt", pkt.hex()) am Anfang der def process_pkt(pkt): Funktion einfügen.

Sollte dann so irgendwie aussehen:

Code: Alles auswählen

python3 station.py  --l --d
DISCOVER-MODE
Labermodus
2022-11-04 19:41:59,818 pkt 1f3b10c36c0200000300ffff0000000000000200fe54a90035004744ffff7000c500000000000000ff00000000000000000000000000000000000000585600202f000000ffffffff975f0100e4550020dfdf000080350020e12f01000000 
2022-11-04 19:41:59,821 data 00000000000000000000000000585600202f000000ffffffff975f0100e4550020dfdf000080350020e12f01000000 
2022-11-04 19:41:59,821 hdr 41cc00ff7000000000000200fe6c0200000300ffff 
2022-11-04 19:41:59,821 ciph 00000000000000000000000000585600202f000000ffffffff975f0100e4550020dfdf00008035 
2022-11-04 19:41:59,821 nonce 010000006c0200000300ffff00 
2022-11-04 19:41:59,822 tag 0020e12f 
2022-11-04 19:41:59,822 packet is NOT authentic 
Hintergrund: TIMAC sendet irgendwie wohl keinen Header, ich habe aber einen, daher würde ich gerne die Unterschiede sehen. Irgendwie dürfte ein CC1352 mit ordentlicher Antenne auch etwas besser sein.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 4. Nov 2022, 22:29
von ProgBernie
Ich habe station.py wie folgt abgeändert:

Code: Alles auswählen

def process_pkt(pkt):
    if laber:
        print("pkt", pkt)
        print("pkt['data']", pkt['data'].hex())
Damit erhalte ich bei einem reset des Schildes:

Code: Alles auswählen

pi@TEApi:~/estation $ python station.py --l --d
DISCOVER-MODE
Labermodus
2022-11-04 21:20:54,113 Station started
2022-11-04 21:23:43,993 pkt {'type': 'parse_mac_data_ind', 'src_add_mode': 3, 'src_add': [0, 0, 2, 109, 108, 153, 59, 26], 'dst_add_mode': 2, 'dst_add': b'\xff\xff', 'timestamp': b';\x1a\x08\x00', 'timestamp2': b'\xb2\x04', 'src_pan_id': b'GD', 'dst_pan_id': b'\xff\xff', 'link_quality': 89, 'correlation': 107, 'rssi': 203, 'dsn': 0, 'key_source': b'\x00\x00\x00\x00\x00\x00\x00\x00', 'security_level': 0, 'key_id_mode': 0, 'key_index': 0, 'length': 47, 'data': b'\xcd\xd6\x94\t\x1c+9\x14\xb1h\xa1O^\xa9?\x02U\xfd)\xcd\xc0\x08\x03PC\xafR\xc0*E\x19\x08\xfcV\xaf\xd1\xffHBp\xc2\xc8T\x00\x00\x00\x00'}
2022-11-04 21:23:43,995 pkt['data'] cdd694091c2b3914b168a14f5ea93f0255fd29cdc008035043af52c02a451908fc56afd1ff484270c2c85400000000
2022-11-04 21:23:44,028 rcvd_packet: f00000000000130100000800280a00800028011d0043000200c800100000000000000000000000
2022-11-04 21:23:44,029 rcvhdr: 01c800ffffffff47441a3b996c6d020000
2022-11-04 21:23:44,036 Got assoc request
2022-11-04 21:23:44,037 TagInfo(protoVer=0, swVer=1181116006400, hwType=8, batteryMv=2600, rfu1=0, screenPixWidth=128, screenPixHeight=296, screenMmWidth=29, screenMmHeight=67, compressionsSupported=2, maxWaitMsec=200, screenType=16, rfu=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
2022-11-04 21:23:44,038 AssocInfo(checkinDelay=900000, retryDelay=1000, failedCheckinsTillBlank=2, failedCheckinsTillDissoc=2, newKey=bytearray(b'\xd3\x06\xd94\x8e)\xe5\xe3X\xbf)4\x81 \x02\xc1'), rfu=bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00'))
2022-11-04 21:23:44,038 hdr: 41cc0147441a3b996c6d0200003549d914004b1200
2022-11-04 21:23:44,039 nonce: d07465633549d914004b120000
2022-11-04 21:24:10,325 pkt {'type': 'parse_mac_data_ind', 'src_add_mode': 3, 'src_add': [0, 0, 2, 109, 108, 153, 59, 26], 'dst_add_mode': 3, 'dst_add': b'5I\xd9\x14\x00K\x12\x00', 'timestamp': b'\xa9[\t\x00', 'timestamp2': b'\x01%', 'src_pan_id': b'GD', 'dst_pan_id': b'GD', 'link_quality': 89, 'correlation': 107, 'rssi': 203, 'dsn': 0, 'key_source': b"\x08\x00'\x1e\x00\x1a;\x99", 'security_level': 0, 'key_id_mode': 63, 'key_index': 0, 'length': 30, 'data': b'\xcf\xd6\x94\t\x1c8+\x15\xb1`\xa9\xb9\x7f\xa3?\x1aU\xd5(\xd0\xc0K\xfeK\x16E\x00\x00\x00\x00'}
2022-11-04 21:24:10,326 pkt['data'] cfd694091c382b15b160a9b97fa33f1a55d528d0c04bfe4b164500000000
2022-11-04 21:24:10,329 rcvd_packet: f200000000130100000800f609000098000000000000
2022-11-04 21:24:10,329 rcvhdr: 41cc0047443549d914004b12001a3b996c6d020000
2022-11-04 21:24:10,331 Got checkin request
2022-11-04 21:24:10,332 CheckinInfo(swVer=1181116006400, hwType=8, batteryMv=2550, lastPacketLQI=0, lastPacketRSSI=0, temperature=152, rfu=b'\x00\x00\x00\x00\x00\x00')
2022-11-04 21:24:10,333 Reading image file:./0000026d6c993b1a.bmp/.png
2022-11-04 21:24:10,334 Using ./0000026d6c993b1a.png file
2022-11-04 21:24:10,335 Reading firmware file: UPDT0008.BIN
2022-11-04 21:24:10,336 No Firmware file available
2022-11-04 21:24:10,337 PendingInfo(imgUpdateVer=7161838112113685969, imgUpdateSize=9542, osUpdateVer=0, osUpdateSize=0, nextCheckinDelay=0, rfu=bytearray(b'\x00\x00\x00\x00'))
2022-11-04 21:24:10,338 hdr: 41cc0247441a3b996c6d0200003549d914004b1200
2022-11-04 21:24:10,338 nonce: ea7465633549d914004b120000
2022-11-04 21:24:10,554 pkt {'type': 'parse_mac_data_ind', 'src_add_mode': 3, 'src_add': [0, 0, 2, 109, 108, 153, 59, 26], 'dst_add_mode': 3, 'dst_add': b'5I\xd9\x14\x00K\x12\x00', 'timestamp': b'u^\t\x00', 'timestamp2': b'\xb4\x16', 'src_pan_id': b'GD', 'dst_pan_id': b'GD', 'link_quality': 89, 'correlation': 107, 'rssi': 203, 'dsn': 1, 'key_source': b'\t\x00j\x06\x00\x00K\x12', 'security_level': 0, 'key_id_mode': 59, 'key_index': 0, 'length': 29, 'data': b'd4T\x0eGD\x8e\xab\x16P5\x07q\x8e$\xcf\xee\x83\xab\x9ex\x1c\xd0\xf9v\x01\x00\x00\x00'}
2022-11-04 21:24:10,555 pkt['data'] 6434540e47448eab16503507718e24cfee83ab9e781cd0f97601000000
2022-11-04 21:24:10,558 rcvd_packet: f4d1f56363d1f56363000000005800000000000000
2022-11-04 21:24:10,559 rcvhdr: 41cc0147443549d914004b12001a3b996c6d020000
2022-11-04 21:24:10,560 Got chunk request
2022-11-04 21:24:10,561 ChunkReqInfo(versionRequested=7161838112113685969, offset=0, len=88, osUpdatePlz=0, rfu=b'\x00\x00\x00\x00\x00\x00')
2022-11-04 21:24:10,562 ChunkInfo(offset=0, osUpdatePlz=0, rfu=0)
2022-11-04 21:24:10,563 Reading image file: /tmp/0000026D6C993B1A_7161838112113685969.bmp
2022-11-04 21:24:10,567 sending chunk 95 f5000000000000424d46 ...
2022-11-04 21:24:10,568 hdr: 41cc0347441a3b996c6d0200003549d914004b1200
2022-11-04 21:24:10,569 nonce: ea7465633549d914004b120000
2022-11-04 21:24:10,659 pkt {'type': 'parse_mac_data_ind', 'src_add_mode': 3, 'src_add': [0, 0, 2, 109, 108, 153, 59, 26], 'dst_add_mode': 3, 'dst_add': b'5I\xd9\x14\x00K\x12\x00', 'timestamp': b'\xc1_\t\x00', 'timestamp2': b'\x9f%', 'src_pan_id': b'GD', 'dst_pan_id': b'GD', 'link_quality': 89, 'correlation': 107, 'rssi': 203, 'dsn': 2, 'key_source': b'\t\x00?\x1d\x00\x9e;\xcd', 'security_level': 0, 'key_id_mode': 121, 'key_index': 0, 'length': 29, 'data': b'z\xb2\xeb\xdd`\x1b.\xfco\xcd\x00\xbfM\xd1\xa5|\xc67\x837\xc1\rI\xbf\x81\x02\x00\x00\x00'}
2022-11-04 21:24:10,660 pkt['data'] 7ab2ebdd601b2efc6fcd00bf4dd1a57cc6378337c10d49bf8102000000
2022-11-04 21:24:10,662 rcvd_packet: f4d1f56363d1f56363580000005800000000000000
2022-11-04 21:24:10,663 rcvhdr: 41cc0247443549d914004b12001a3b996c6d020000
2022-11-04 21:24:10,665 Got chunk request
2022-11-04 21:24:10,665 ChunkReqInfo(versionRequested=7161838112113685969, offset=88, len=88, osUpdatePlz=0, rfu=b'\x00\x00\x00\x00\x00\x00')
2022-11-04 21:24:10,666 ChunkInfo(offset=88, osUpdatePlz=0, rfu=0)
2022-11-04 21:24:10,666 Reading image file: /tmp/0000026D6C993B1A_7161838112113685969.bmp
2022-11-04 21:24:10,667 sending chunk 95 f5580000000000555555 ...
2022-11-04 21:24:10,668 hdr: 41cc0447441a3b996c6d0200003549d914004b1200
2022-11-04 21:24:10,668 nonce: ea7465633549d914004b120000
2022-11-04 21:24:10,760 pkt {'type': 'parse_mac_data_ind', 'src_add_mode': 3, 'src_add': [0, 0, 2, 109, 108, 153, 59, 26], 'dst_add_mode': 3, 'dst_add': b'5I\xd9\x14\x00K\x12\x00', 'timestamp': b'\xf9`\t\x00', 'timestamp2': b"\xea'", 'src_pan_id': b'GD', 'dst_pan_id': b'GD', 'link_quality': 86, 'correlation': 107, 'rssi': 202, 'dsn': 3, 'key_source': b'\t\x00?\x07\x00\x9e;\xcd', 'security_level': 0, 'key_id_mode': 121, 'key_index': 0, 'length': 29, 'data': b'z\x11\x17"\xb8\xfeN#j\xcc"\xc41\xf0[\x95\x15\x8a!\x16~\x9b\xcc\xd2\xfc\x03\x00\x00\x00'}
2022-11-04 21:24:10,761 pkt['data'] 7a111722b8fe4e236acc22c431f05b95158a21167e9bccd2fc03000000
2022-11-04 21:24:10,763 rcvd_packet: f4d1f56363d1f56363b00000005800000000000000
2022-11-04 21:24:10,764 rcvhdr: 41cc0347443549d914004b12001a3b996c6d020000
2022-11-04 21:24:10,765 Got chunk request
2022-11-04 21:24:10,766 ChunkReqInfo(versionRequested=7161838112113685969, offset=176, len=88, osUpdatePlz=0, rfu=b'\x00\x00\x00\x00\x00\x00')
2022-11-04 21:24:10,767 ChunkInfo(offset=176, osUpdatePlz=0, rfu=0)
2022-11-04 21:24:10,767 Reading image file: /tmp/0000026D6C993B1A_7161838112113685969.bmp
2022-11-04 21:24:10,768 sending chunk 95 f5b00000000000555555 ...
2022-11-04 21:24:10,769 hdr: 41cc0547441a3b996c6d0200003549d914004b1200
2022-11-04 21:24:10,770 nonce: ea7465633549d914004b120000
...

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 4. Nov 2022, 23:07
von omega
Danke, das muss ich in Ruhe verdauen. Da sind Ähnlichkeiten und Unterschiede...

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 16:22
von omega
Die Info hat geholfen, dass die Pakete vom PC nun richtig empfangen werden. Das Beantworten passt noch nicht so ganz, da muss ich mir einen zweiten CC1352 besorgen, um mit zuschneiden was wirklich gesendet wird. Bisher ignoriert das Display leider die Antwort vom PC.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 18:57
von ProgBernie
Wenn es Dir hilft kann ich einen gesamten Upload und die hochgeladene Bilddatei zur Verfügung stellen.

Ach ja: Unter 2.5V meldet sich das Display noch mit einem Assoc Request, aber bleibt dann stehen. Ob es die Antwort nicht mehr liest oder was da schief läuft weiß ich nicht, es bleibt jedenfalls mit ASSOCIATE READY im Display stehen. Batterien raus/rein lässt das ganze wieder erneut starten.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 20:52
von omega
Der Ausschnitt reicht erstmal, danke. Der Hinweis mit den 2,5 V ist gut, das Display bekommt hier aber externe 3.3 V, daher schließe ich das momentan noch aus,

Laut UART Ausgabe wird nach dem Senden schlafen gegangen.

Code: Alles auswählen

booted at 0x1aec Reset reason: 00
Booting FW ver 0x0000011300000000
 -> FW v1.19.0.0
MAC 00:00:02:6C:C3:10:3B:1F
temp: 20
eeprom has 59 image slots
Erz IMAGES
Erz UPD
Erz SETTINGS
MESSAGE 'BOOTING'
booted at 0x1aec Reset reason: 01
Booting FW ver 0x0000011300000000
 -> FW v1.19.0.0
MAC 00:00:02:6C:C3:10:3B:1F
temp: 20
eeprom has 59 image slots
Associate is displayed
MESSAGE 'ASSOCIATE READY'
booted at 0x1aec Reset reason: 01
Booting FW ver 0x0000011300000000
 -> FW v1.19.0.0
MAC 00:00:02:6C:C3:10:3B:1F
temp: 21
eeprom has 59 image slots
Associate is not displayed
try ch 11
sleep: 791015
Vielleicht sollte ich einfach auf den bestellten passenden CC Stick warten, dann lässt sich das einfacher umbauen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 21:30
von sukram
Der Sourcecode der Displaysoftware hilft da wohl nicht weiter? Da müsste doch grob drinstehen, was das Funkmodul hören will. Übersehe ich etwas?

https://github.com/atc1441/E-Paper_Pricetags

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 21:56
von omega
Ja doch schon. Wenn ich das richtig verstanden haben sollte das so ablaufen:

Code: Alles auswählen

- ...
- ASSOCIATE READY anzeigen
- 4x Kommunikationsversuch
  - Nachricht senden
  - Delay
  - Empfang auswerten
    - Wenn was sinnvolles, pairing fortsetzen, ...
    - Ansonsten zumindest irgendwelche Meldungen
  - nochmal
- Schlafen gehen
- ...
Wie gesagt, ich warte einfach bis der Stick da ist, dann sollte sich das ganz einfach lösen lassen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 5. Nov 2022, 22:55
von Hightech
Außen Temperaturanzeige aus der Influxdb gesaugt.

897095CB-1351-4407-981B-CD98EEFF98C1.jpeg

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 6. Nov 2022, 14:14
von ProgBernie
omega hat geschrieben: Sa 5. Nov 2022, 20:52 Der Ausschnitt reicht erstmal, danke. Der Hinweis mit den 2,5 V ist gut, das Display bekommt hier aber externe 3.3 V, daher schließe ich das momentan noch aus,
Ich denke es sind nicht die 2.5V, aber die Displays die beim Booten nur noch 2.5V zeigen laden hier kein Bild mehr, die Zellen sind wohl zu hochohmig. Beim Laden der Bild-Chunks werden am Labornetzteil 40mA gezogen, das wird gemittelt sein und der Funkkram zieht ordentlich Strom. Das Umschalten der Displays zieht nur etwa 2mA.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 6. Nov 2022, 14:16
von ProgBernie
Hightech hat geschrieben: Sa 5. Nov 2022, 22:55 Außen Temperaturanzeige aus der Influxdb gesaugt.


897095CB-1351-4407-981B-CD98EEFF98C1.jpeg
Nett. Ich häkel gerade eine Wetteranzeige aus OWM zusammen. Bin schon am Bilder malen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 12. Nov 2022, 11:23
von Hightech
Aaron bietet uns Adaperplatinen für das direkte Ansteuern über Arduino an.
Stückpreis 5Euro.

https://www.pcbway.com/project/sharepro ... a845c.html

Seine Email Adresse zum bestellen:
adapter@43u.de
C9845D34-3670-4607-90B5-1F3BF17ABDED.jpeg

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 24. Nov 2022, 22:42
von Hightech
Das Reichweitenproblem kann man erschlagen mit einem Stick, der eine SMA-Buchse hat und eine externe Antenne:

https://de.aliexpress.com/item/40006400 ... pt=glo2deu
Damit komme ich durch das ganze Haus.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 11. Dez 2022, 11:39
von omega
Mit dem CC1352 bin ich noch nicht weitergekommen, da mein CC1352 einfach nichts zu senden scheint, also auch mit anderem CC1352 als Empfänger und TI SmartRF Studio getestet. Diese Baustelle muss aber erstmals ruhen.

In der Zwischenzeit habe ich etwas gebastelt, das anzeigt, welche Mülltonne rausgestellt werden muss. Jeweils am Tag vor der Abholung erscheint eine Meldung:
restmuell.jpg
Dazu müssen die Abholtermine als Kalenderdatei in abfuhrtermine.ics gespeichert sein und das Skript regelmässig (z.B. per Cron) aufgerufen werden. Die in destination_file konfigurierte Datei wird dann entsprechend aktualisiert.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 12 12:18:43 2022

@author: omega
"""
# imports
from icalendar import Calendar, Event, vCalAddress, vText
from datetime import datetime, timedelta, time
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
from collections import namedtuple
import os
import pytz
import time
 
# init the calendar
cal = Calendar()

Display_Size_x=296
Display_Size_y=128
destination_file = '../epaper-station/0000023902443b13.png'

def generate_abhol_image(summary, datum):
    muster=Image.new("RGB",(296,128),color=(255,255,255))
    named_tuple = time.localtime() # get struct_time
    time_string = time.strftime("%d.%m.%Y, %H:%M:%S", named_tuple)
    im = ImageDraw.Draw(muster)
    font = ImageFont.load('VeraMono30.pil')
    font_klein = ImageFont.load('VeraMono8.pil')
    

    _, _, w, h = im.textbbox((0, 0), summary, font=font)
    im.text((((Display_Size_x/2)-w/2),Display_Size_y/2-h/2-30), summary ,fill=(0, 0, 0),font=font)
    
    _, _, w, h = im.textbbox((0, 0), datum, font=font_klein)
    im.text((((Display_Size_x/2)-w/2),80), datum ,fill=(0, 0, 0),font=font_klein)
    
    _, _, w, h = im.textbbox((0, 0), time_string, font=font_klein)
    im.text((((Display_Size_x/2)-w/2),100), time_string ,fill=(0, 0, 0),font=font_klein)
    
    muster=muster.rotate(angle=90,expand="true")
    muster.save(destination_file)


def generate_empty_image():
    muster=Image.new("RGB",(296,128),color=(255,255,255))
    named_tuple = time.localtime() # get struct_time
    time_string = time.strftime("%d.%m.%Y, %H:%M:%S", named_tuple)
    im = ImageDraw.Draw(muster)
    font_klein = ImageFont.load('VeraMono8.pil')
    
    _, _, w, h = im.textbbox((0, 0), time_string, font=font_klein)
    im.text((((Display_Size_x/2)-w/2),100), time_string ,fill=(0, 0, 0),font=font_klein)
    
    muster=muster.rotate(angle=90,expand="true")
    muster.save(destination_file)


generate_empty_image()
today = datetime.today().date()
e = open('abfuhrtermine.ics', 'rb')
ecal = cal.from_ical(e.read())
for component in ecal.walk():
    #print(component.name)
    if component.name == "VEVENT":
        #print (component.get('summary'))
        #print (component.get('dtstart').dt)
        nachrichttag = component.get('dtstart').dt - timedelta(days=1)
        if(today==nachrichttag):
            #print (component.get('summary'))
            #print (component.get('dtstart').dt)
            generate_abhol_image(str(component.get('summary')), str(component.get('dtstart').dt))
        
        
e.close()

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 11. Dez 2022, 16:12
von T5000
Ich hab jetzt meine PriceTags auch endlich angesteuert bekommen,
Aktuell erstelle ich noch meine PNG Dateien mit Paint.
Mich würde nur mal interessieren wie ich denn die rote Farbe vom Preisschild ansteuern kann?
Ist das ein definierter Rot-Farbton?

Gruss Thomas

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 11. Dez 2022, 16:49
von duese
Rot halt. In RGB: 255,0,0 bzw 100%,0%,0%

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 11. Dez 2022, 18:57
von T5000
hm, also wenn ich rot (255,0,0) verwende im PNG bleibt es leider grau.
Ich hatte hier gelesen das es mit der station.py von Hightech gehen soll, die Variante die ich hier gefunden habe bringt mir leider einen Fehler beim Start.
Ich nutze das pyhton aktuell noch unter Windows.

Ausgabe station.py von Hightech: (die die ich hier irgendwo gefunden habe)
station_py_hightech.PNG

Code: Alles auswählen

import timaccop
import bmp2grays
from Cryptodome.Cipher import AES
from collections import namedtuple
import struct
import os, sys
import logging
from PIL import Image, ImageDraw, ImageFont
import time

parameter=sys.argv
discover=False
laber=False

if "--d" in parameter:
    discover=True
    print ("DISCOVER-MODE")

if "--l" in parameter:
    discover=True
    print ("Labermodus")

Display_Size_x=296
Display_Size_y=128

masterkey = bytearray.fromhex("D306D9348E29E5E358BF2934812002C1")

PORT = com4("EPS_PORT", default="/dev/ttyACM0")
EXTENDED_ADDRESS = [ int(addr.strip(), 16) for addr in os.environ.get("EPS_EXTENDED_ADDRESS", default="0x00, 0x12, 0x4B, 0x00, 0x14, 0xD9, 0x49, 0x35").split(",") ]
PANID = [ int(panid.strip(), 16) for panid in os.environ.get("EPS_PANID", default="0x47, 0x44").split(",") ]
CHANNEL = int(os.environ.get("EPS_CHANNEL", default="11"))
IMAGE_DIR = os.environ.get("EPS_IMAGE_DIR", default="./")
IMAGE_WORKDIR = os.environ.get("EPS_IMAGE_WORKDIR", default="/tmp/")

CHECKIN_DELAY = int(os.environ.get("EPS_CHECKIN_DELAY", default="900000")) # 900s
RETRY_DELAY = int(os.environ.get("EPS_RETRY_DELAY", default="1000")) # 1s
FAILED_CHECKINS_TILL_BLANK = int(os.environ.get("EPS_FAILED_CHECKINS_TILL_BLANK", default="2"))
FAILED_CHECKINS_TILL_DISSOC = int(os.environ.get("EPS_FAILED_CHECKINS_TILL_DISSOC", default="2"))

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_154_INCH_ZBS_033                                = (18)
HW_TYPE_154_INCH_ZBS_033_FRAME_MODE             = (19)
HW_TYPE_42_INCH_ZBS_026                                 = (28)
HW_TYPE_42_INCH_ZBS_026_FRAME_MODE              = (29)
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)
    if laber:
        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)
    if laber:
        print("hdr:", hdr.hex())

    cntr = int(time.time())
    cntrb = struct.pack('<L', cntr)

    nonce = bytearray(cntrb)
    nonce.extend(EXTENDED_ADDRESS)
    nonce.append(0)
    if laber:
        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=CHECKIN_DELAY,
            retryDelay=RETRY_DELAY,
            failedCheckinsTillBlank=FAILED_CHECKINS_TILL_BLANK,
            failedCheckinsTillDissoc=FAILED_CHECKINS_TILL_DISSOC,
            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 = False
    base_name = os.path.join(IMAGE_DIR, bytes(client).hex())
    filename = base_name + ".png"
    print("Reading image file:" + base_name + ".bmp/.png")

    if os.path.isfile(filename):
        print("Using "+filename+" file")
    elif os.path.isfile(base_name + ".bmp"):
        is_bmp = True
        filename = base_name + ".bmp"
        print("Using .bmp file")
    elif discover == True:
        generate_discover_image(filename)
        print("NEW DEVICE")
        print(filename)
    else:
        print("Device not found")
        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 = os.path.join(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:
            bmp2grays.convertImage(1, "1bppR", filename, file_conv)
        else:
            Image.open(filename).convert("RGB").save(os.path.join(IMAGE_WORKDIR, "tempConvert.bmp"))
            bmp2grays.convertImage(1, "1bppR", os.path.join(IMAGE_WORKDIR, "tempConvert.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_MOD
E or hwType == HW_TYPE_154_INCH_ZBS_033 or hwType == HW_TYPE_154_INCH_ZBS_033_FRAME_MODE or hwType == HW_TYPE_42_INCH_ZBS_026 or hwType == HW_TYPE_42_INCH_ZBS_026_FRAME_MOD
E:
        return HW_TYPE_29_INCH_ZBS_ROM_VER_OFST

def prepare_firmware(hwType):
    filename = 'UPDT{0:0{1}X}.BIN'.format(hwType,4)
    if laber:
        print("Reading firmware file:", filename)

    if not os.path.isfile(filename):
        if laber:
            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 = os.path.join(IMAGE_WORKDIR, imgVer + ".bmp")
    if laber:
        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)
    if laber:
        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))
    if laber:
        print(cri)

    ci = ChunkInfo(
        offset = cri.offset,
        osUpdatePlz = cri.osUpdatePlz,
        rfu = 0,
    )
    if laber:
        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)
    if laber:
        print("sending chunk", len(outpkt), outpkt[:10].hex() ,"...")

    send_data(pkt['src_add'], outpkt)

def generate_discover_image(filename):
    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_default()
    length_name=font.getbbox("Aktivierung")
    im.text((((Display_Size_x/2)-length_name[2]/2),5),"Aktivierung" ,fill=(0, 0, 0),font=font)
    length_name=font.getbbox(filename)
    im.text((((Display_Size_x/2)-length_name[2]/2),45),filename ,fill=(0, 0, 0),font=font)
    box=font.getbbox(time_string)

    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),time_string,fill=(255,255,255),font=font)
    muster=muster.rotate(angle=90,expand="true")
    muster.save(filename)


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 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:
        if laber:
            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()

Meine aktuelle station.py ohne rot:

Code: Alles auswählen

import timaccop 
from Cryptodome.Cipher import AES
from collections import namedtuple
import struct
import os
import logging
from PIL import Image
import binascii
import time
from io import BytesIO

masterkey = bytearray.fromhex("D306D9348E29E5E358BF2934812002C1")

PORT = "COM5"
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)


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=300000, #check each 900sec 
	    retryDelay=1000, #retry delay 1000ms
	    failedCheckinsTillBlank=2,
	    failedCheckinsTillDissoc=0,
	    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):
    filename = bytes(client).hex() + ".png"
    print("Reading image file:", filename)

    modification_time = os.path.getmtime(filename)
    creation_time = os.path.getctime(filename)
    
    pf = open(filename,mode='rb')
    imgData = pf.read()
    imgVer = int(modification_time)<<32|int(creation_time) # This uses the mofidication time of the image to look for the newest one
    #imgVer = binascii.crc32(imgData) # This uses the CRC of the image to look for a newer one but can fail as on "stock" custom firmware the highest number is used
    pf.close()

    file_conv = IMAGE_WORKDIR + str(imgVer) + ".bmp"

    if not os.path.isfile(file_conv):
        pngdata = BytesIO(imgData)

        im = Image.open(pngdata)
        im_L = im.convert("1")
        im_L.save(file_conv)

    imgLen = os.path.getsize(file_conv)

    return (imgVer, imgLen)

def get_image_data(imgVer, offset, length):
    filename = IMAGE_WORKDIR + str(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 process_checkin(pkt, data):
    ci = CheckinInfo._make(struct.unpack('<QHHBBB6s',data))
    print(ci)

    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)
        return

    pi = PendingInfo(
        imgUpdateVer = imgVer,
        imgUpdateSize = imgLen,
        osUpdateVer = ci.swVer,
        osUpdateSize = 0,
        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 = 0,
        rfu = 0,
    )
    print(ci)

    try:
        fdata = get_image_data(cri.versionRequested, cri.offset, cri.len)
    except Exception as e :
        print("Unable to get image 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 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()

kann mir jemand weiterhelfen?

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 11. Dez 2022, 19:54
von Lokaro
Benutze am besten die aktuellste aus dem Repo, ROT habe ich letztens erst mit eingebaut.

Sieht so aus als nutzt du noch die ältere version

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 11:52
von T5000
hm, ich hab mal die aktuelle stations.py ausprobiert.
Ich sehe die Grafik auf dem Display jetzt diagonal verzerrt. Das rot scheint jetzt aber mit angezeigt zu werden.
Öfters erhalte ich aber auf dem Display nur noch den Blank-Screen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 13:34
von Bastelbruder
Diagonal verzerrt
Sieht das so aus wie auf der Deppenlampe ohne Zeilensynchronisation?
Dann tippe ich auf falsche Anzahl Pixel in X-Richtung. Das kann durchaus zu leeren Bildern führen, es ist aber nicht auszuschließen daß die Y-Größe dann auch nicht stimmt.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 13:58
von T5000
Ich hab mal eines meiner Testbilder angehängt.
Die Pixelmaße sind 296x146
000002838f9c3b12.png
000002838f9c3b12.png (2.23 KiB) 1800 mal betrachtet
Mit dem alten Script gehts, mit dem neuen nicht.
Auch eine abschneiden von jeweils 10 Pixel in Länge und Breite bringt leider keine Besserung.

Nachtrag:

wenn ich in den /tmp Ordner schaue, stelle ich fest, das die Bilder nicht korrekt konvertiert werden. TempConvert.bmp lässt sich meist noch mit einem Bildbetrachter anzeigen. Die anderen erzeugten Bilder die "000002838CCA3B12_7176246181206894028.bmp" oder ähnlich heißen lassen sich nicht öffnen. Die mit der alten Station.py erzeugten Bilder "7176216331184172200.bmp" hingegen schon.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 20:01
von berferd
Mal eine grundlegende Frage... ich überlege grade wie ich das Ding möglichst einfach & energiesparend dauerhaft betreibe.
Ich habe hier keinen extra Router, Pi o.ä. der "ohnehin immer läuft" und den ich als Server nutzen könnte. Alle meine Geräte (Desktop, Laptop) schalte ich bei Nichtgebrauch aus oder in den Ruhemodus.
Ich würde gerne vermeiden, extra einen Pi o.ä. hinzustellen, der dann 24/7 die nächsten Jahre nur dafür durchläuft und rund um die Uhr 3-5 Watt schlürft.
Also, was nimmt man als minimalistische Plattform? "alles selber entwerfen und bauen" scheidet aus.
Idealerweise sollte das Ding Zigbee (natürlich) können, und Ethernet und/oder Wifi (vermutlich ersteres stromsparender), und man sollte selber einfache eigene Programme drauf starten können (Programmiersprache egal. Meinetwegen auch nur Shell und compiliertes C.).

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 20:09
von Lokaro
Die bilder werden in 296x128 erwartet und müssen auch so vorliegen
T5000 hat geschrieben: Mo 12. Dez 2022, 13:58 Die Pixelmaße sind 296x146
Und zum nachtrag, durch das ROT in den Bildern werden sie in ein altes BMP format konvertiert was so gut wie keine software mehr unterstützt, die firmware im display aber schon.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 20:22
von Lokaro
@berferd

Du könntest eine Station auch nur für ca. 20 Minuten starten um die Displays upzudaten und den rest des Tages aus. Die Displays suchen alle 15 Minuten nach der Station.

Es gibt auch eine ESP32 Station, dadurch läuft alles auf diesem.

Als Zigbee transceiver wird eine Display Platine genommen und mit einer eigenen firmware als Access Point genutzt, diese flasht der ESP32 selber

Die software funktioniert ist aber noch im beta status.

Das Repo ist hier:
https://github.com/jjwbruijn/ESP32-epaper-station

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 22:22
von Später Gast
An dem Energieverbrauch denk ich auch grad rum. Muss grad primär eine Wohnung neu beleuchten und da wird wohl zigbee zum Einsatz kommen. Esp32 kann das auch, wenn man sich also als gateway nen esp hernimmt, passt das da vllt grad auch noch drauf.

Wenn man die Informationsbeschaffung der Displays irgendwie extern takten könnte, kann der Esp in der Zwischenzeit auch aus sein. Alle gleichzeitig anschalten führt nach längerer Betriebszeit bestimmt zu Phasenverschiebungen und damit Ausfällen.

Fritzboxen können ja nebenher teils auch schon smart Kram, leider nur sehr eingeschränkt und selber sachen dazupatchen ist eher nicht, oder gibts Freetz noch? Router mit OpenWRT?

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Mo 12. Dez 2022, 22:35
von Hightech
Mein Plan ist, ein 2x3 Displaymatrix auf dem ich meine Daten darstelle.
Die Display kann man parallel an einen Akku klemmen und über eine ttl- Daisychain hintereinander schalten und mit einem nem ESP32 mit Daten füttern.
Die Funkdaten laufen dann nur über den ESP.
Wlan halt dann.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Di 13. Dez 2022, 09:52
von T5000
Danke für den Tipp mit der richtigen Auflösung, ich weis auch nicht mehr wo ich meine falschen Werte her hatte.
epaper.PNG
Display1 : altes station.py Script - Bild in Graustufen ohne rot im PNG
Display2 : neues station.py Script - gleiches Bild wie Display1 -> die Graustufen fehlen, Mario hat keine Hände usw :shock:
Display3 : neues station.py Script - Bild mit rot im PNG

Die Graustufen fehlen halt im neuen Script. Wird sicherlich an dem ungewöhnlichen BMP Format liegen.
Ideal wäre natürlich, wenn das Script erkennt, das es ein Graustufen PNG ist und es dann in das modernere BMP wandelt. ;)

Ich bin erstmal froh, das ich überhaupt soweit gekommen bin, inkl. C2531 Flashen usw. :D

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 14:05
von Teslafreak
Diese Ständer kann man für die Displays wunderbar zweckentfremden: https://www.thingiverse.com/thing:5422488
2.jpg
1.jpg

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 16:48
von nero
kwh.png
kwh.png (4.88 KiB) 1553 mal betrachtet
Mhhhhahprprhrhprrr

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 20:53
von xanakind
Was genau möchtest du uns denn mit diesem Post sagen?
Bitte schreibe doch einen vollständigen Satz in einer Sprache, welche wir lesen können.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 20:57
von ferdimh
Es wird eindeutig die Änderungsrate der eingespeisten Leistung in Kilowatt pro Stunde angezeigt...

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 21:46
von Fritzler
Kontext Mädels!
Es geht um die ausgefransten Buchstaben durch Subpixelrendering umgemappt auf 1bit Graustufen Epaper und die immernoch fehlende Lösung dazu.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: So 25. Dez 2022, 22:09
von MSG
Aber gab es nicht früher (tm) Schriften extra für den Bildschirm? Da war doch das gleiche Problem, bis die grafischen OS die Druckerschriften entsprechend rendern konnten.

Evtl wäre das ein Ansatzpunkt?

Die Adafruit Grafikbibliotheken haben soweit mir dünkt auch spezielle Schriften für die kleinen Grafik Panels.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 30. Dez 2022, 09:21
von Hightech
Ich hab was in Python gebastelt mit Skalierung und min/Max.
Klappt leider noch nicht 100 bei negativen Zahlen kackts ab
225F09B3-6865-4023-A074-66BC901CB7C2.jpeg

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 30. Dez 2022, 21:45
von Flip
Ich bin ja in meinem Gesamten System auf der Variante ESP32-gateway-Station. Die Sendezeit ist ja durchaus begrenzt, wenn man den Äther nicht verstopft haben will.
Mich stört es etwas, immer die pixelgrafik zu übertragen, auch wenn komprimiert, hat man da doch erheblich mehr daten, als wenn man Schrift und grafik auf dem Display rechnet. Selbst mit 1MHz kerntakt dürfte das fixer gehen als das rüberschieben der grafik.


Ich denke erstmal effizienzverliebt an Protobuf-codierte Zeichenbefehle. 1 byte Typ und Farbe, 2 Byte Position und Größe, dann ggf für Text oder Kurven noch ein Datenstring Fällt da jemandem noch etwas ein, was besser für differentielle screen-updates geht?

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Sa 31. Dez 2022, 21:18
von Hightech
So, nun :D
Hier 6 Display uarts in Reihe an einem ESP32

Der holt sich die Daten direkt aus der InfluxDB und geht dann schlafen, nachdem er den Strom für die Displays aus gemacht hat.
2D741113-6334-43E6-B8CF-41871BF7204D.jpeg

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 5. Jan 2023, 14:24
von berferd
Hat jemand zufällig einige Adapterplatinen (so wie hier beschrieben https://www.pcbway.com/project/sharepro ... a845c.html) über?
Dann muss ich nicht extra nur für meine 5 Stück welche fertigen lassen....

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 5. Jan 2023, 14:56
von ProgBernie
Flip hat geschrieben: Fr 30. Dez 2022, 21:45 Ich bin ja in meinem Gesamten System auf der Variante ESP32-gateway-Station. Die Sendezeit ist ja durchaus begrenzt, wenn man den Äther nicht verstopft haben will.
Mich stört es etwas, immer die pixelgrafik zu übertragen, auch wenn komprimiert, hat man da doch erheblich mehr daten, als wenn man Schrift und grafik auf dem Display rechnet. Selbst mit 1MHz kerntakt dürfte das fixer gehen als das rüberschieben der grafik.


Ich denke erstmal effizienzverliebt an Protobuf-codierte Zeichenbefehle. 1 byte Typ und Farbe, 2 Byte Position und Größe, dann ggf für Text oder Kurven noch ein Datenstring Fällt da jemandem noch etwas ein, was besser für differentielle screen-updates geht?
Es wäre ja schon viel gewonnen, wenn nicht dieses dusselige unkomprimierte BMP-Format benutzt würde. Das sind auch für ein komplett einfarbiges Schild aktuell 9542 Byte. Als GIF sind das meist deutlich weniger Byte, bei meinen Wetterbildern etwa 2200, als PNG noch darunter 1800 Byte. Ein einfarbiges Bild sind als PNG nur noch 159 Byte.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 5. Jan 2023, 15:37
von Lokaro
Eine komprimierung ist in arbeit :)

Bei den großen ist nun Gzip implementiert und funktioniert sehr gut. Leider haben die ZBS243 aber zu wenig RAM um das dort zu implementieren.
https://youtu.be/kPy8rIQ75NU

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 5. Jan 2023, 17:07
von Bastelbruder
Ich bin jetzt nicht der Spezialist in Bilddatenformaten, aber ich war bei der Prüfung der Kinderschuhe der elektronischen Bildverarbeitung mit dabei. Viele der heute völlig unnötig mitgeschleppten Begleitdaten fressen bei so kleinen Bildern den Gewinn auf.

Da sollte man wirklch mal die Statis-Tiger dranlassen, sehr wahrscheinlich bringt eine primitivste Lauflängencodierung die höchste Ersparnis, natürlich abhängig vom Bildinhalt - ein unregelmäßiges Raster ist die Höchststrafe.
Ich hab eben geschwind mit IrfanView eine aus dem Leben gegriffene SW-Grafik (296 x 128 Pixel, bmp: 5182 Bytes) durchprobiert, da hat (tif) CCITT Fax 4 mit 1416 Bytes gegenüber allen anderen Algorithmen die Nase weit vorn. png belegt mit 2120 Bytes den zweiten Platz und huffmann kommt noch vor gif.
Schalter aus dem Watkins-Johnson
Schalter aus dem Watkins-Johnson
bitmaps.png (6.05 KiB) 1009 mal betrachtet
Alle weiter oben gesehenen Musterdisplays lassen sich natürlich viel effektiver komprimieren, für Wetterbilder dürfte Fax 4 der Spitzenreiter sein.

Ein einzelner Pixel in der Bildmitte wird in (tif) CCITT Fax 4 mit ganzen 254 Bytes dargestellt, Fax3: 666, huffmann 510, gif 295, png kommt auf Platz 1 mit 144 Bytes.

Bei der Gelegenheit (habt Ihr im IrfanView schonmal die Taste [F3] benutzt?) fällt auf daß die populären Formate natürlich auch Format, teilweise Größe (dpi) und nicht zuletzt den Namen des Kompressionsbeauftragten beinhalten, das brauchen wir hier alles nicht.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Do 5. Jan 2023, 18:26
von Lokaro
Wenn RLE auch am einfachsten zu implementieren wäre macht es leider zu schnell keinen sinn mehr da die Daten zu groß werden.

CCITT T.4 ist derzeit der Favorit noch etwas vor .png um es als System umgreifende Komprimierung zu nutzen.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 13. Jan 2023, 18:36
von Kerko
Hat noch Jemand das Problem, dass einzelne Displays Ihre Batterien innerhalb von 14 Tagen leersaugen? Hängen alle an der gleichen Basis mit dem gleichen Updateintervall. Manche ziehen neue Batterien innerhalb von 14 Tagen leer, manche nicht.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 13. Jan 2023, 18:44
von Hightech
Ich glaube da gibt es einen Bug, das Display hängt sich auf und macht die Batterie platt.

Hab ich auch schon beobachtet.

Re: Elektronisches Preisschild Sammelbestellung - Ansteuerung

Verfasst: Fr 13. Jan 2023, 18:58
von ProgBernie
Hightech hat geschrieben: Fr 13. Jan 2023, 18:44 Ich glaube da gibt es einen Bug, das Display hängt sich auf und macht die Batterie platt.

Hab ich auch schon beobachtet.
Ein Bug in der Firmware der Schilder würde das erklären. Dann wird vermutlich der RF-Kram nicht abgeschaltet. Der RF-Kram braucht Unmengen an Strom (>30mA), der Rest nicht.

Ich habe auch beobachtet daß ein Schild oft stundenlang keine neue Anzeige schaltet, obwohl diese bereit steht. Im Log habe ich gefunden, daß diese Schilder oft bei jedem Update die Datei bekommen, inzwischen läuft das im Debug hier und ich warte aufs Auftreten. Dann kann ich sehen ob der letzte Teil des Bildes auch ausgeliefert wird.