Dzień dobry
Chcę się podłączyć do kasy firmy Novitus z obsługą protokołu TANGO i co jakiś czas wysłać nowe towary i pobrać raport sprzedaży. Kasa z programami ze strony Novitus działa poprawnie. Pobrałem dokumentację protokołu ale nigdy nie robiłem tak złożonej komunikacji i składania pakietów.. Trochę mi pomogła AI, kasa coś tam niby odpowiada ale wywala się na PAKIECIE STARTOWYM.
tu jest jak ma niby działać komunikacja
Przesłanie z komputera pojedynczego pakietu danych
-> ENQ
<- ACK
-> PAKIET STARTOWY
<- ACK
-> PAKIET DANYCH
<- ACK
-> EOT
<- EOT
Przesłanie do komputera pojedynczego pakietu danych
-> ENQ
<- ACK
-> PAKIET STARTOWY
<- ACK
-> EOT
<- ENQ
-> ACK
<-PAKIET DANYCH
-> ACK
<- EOT
-> EOT
tu opis Pakiet startowy
Lp.;Offset;Długość;Zawartość;Opis
1;0;1;STX;02H
2;1;1;‘S’;Znacznik pakietu startowego
3;2;1;Typ zadania;‘A’ (41H) do ‘Z’ (5AH) lub ‘a’ (61H) do ‘s’ (73H) - znak ASCII określający typ następującego(ych) pakietu(ów) danych (poza ‘F’, i ‘O’)
4;3;1;Typ transmisji;‘0’ (30H) = pobranie danych przez komputer, ‘1’ (31H) = wysłanie danych przez komputer, ‘2’ (32H) = pobranie danych raportowych z wyzerowaniem
5;4;18;Początek;Numer początkowy dla pobierania raportów i niektórych danych
6;22;18;Koniec;Numer końcowy dla pobierania raportów i niektórych danych
7;40;1;ETX;03H
8;41;4;Suma kontrolna
Tu program który nabazgrałem z AI
import socket
import time
KASA_IP = "192.168.1.XXX"
KASA_PORT = 5001
TOUT = 3 # Zwiększony czas oczekiwania
ENQ = b"\x05"
ACK = b"\x06"
NAK = b"\x15"
EOT = b"\x04"
STX = b"\x02"
ETX = b"\x03"
# Funkcja do obliczania sumy kontrolnej (CRC)
def oblicz_sume_kontrolna(pakiet):
crc = 0
for i, znak in enumerate(pakiet):
crc ^= znak << (i % 9)
return format(crc, '04X') # Zwraca wynik jako 4-cyfrową liczbę heksadecymalną
# Funkcja do wysyłania pakietu startowego
def wyslij_pakiet_startowy(s):
# Składając pakiet na podstawie specyfikacji
numer_poczatkowy = b"000000000000000000" # Zmienny początek (np. numery raportów)
numer_koncowy = b"000000000000000000" # Zmienny koniec (np. numery raportów)
pakiet_startowy = STX + b'S' + b'A' + b'0' + numer_poczatkowy + numer_koncowy + ETX
print(pakiet_startowy)
suma = oblicz_sume_kontrolna(pakiet_startowy)
# Dodajemy sumę kontrolną (cztery bajty)
pakiet_startowy += bytes.fromhex(suma)
print(pakiet_startowy)
s.sendall(pakiet_startowy)
print(f"Wysłano pakiet startowy: {pakiet_startowy.hex()}")
def wyslij_pakiet_danych(s, dane):
pakiet_danych = STX + dane + ETX
suma = oblicz_sume_kontrolna(pakiet_danych)
# Dodajemy sumę kontrolną (cztery bajty)
pakiet_danych += bytes.fromhex(suma)
s.sendall(pakiet_danych)
print(f"Wysłano pakiet danych: {pakiet_danych.hex()}")
def komunikacja_z_kasą():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(TOUT) # Timeout na odpowiedzi
try:
s.connect((KASA_IP, KASA_PORT))
print("Połączono z kasą.")
# Wysłanie ENQ do rozpoczęcia transmisji
s.sendall(ENQ)
print("Wysłano ENQ, oczekiwanie na odpowiedź...")
odpowiedz = s.recv(1)
print(f"Odebrano odpowiedź po ENQ: {odpowiedz.hex()}")
if odpowiedz == ACK:
print("Odebrano ACK - kasa gotowa do transmisji.")
# Wysyłanie pakietu startowego
wyslij_pakiet_startowy(s)
# Oczekiwanie na ACK po wysłaniu pakietu startowego
odpowiedz = s.recv(1)
print(odpowiedz)
print(f"Odebrano odpowiedź po pakiecie startowym: {odpowiedz.hex()}")
if odpowiedz == ACK:
print("Odebrano ACK po pakiecie startowym.")
# Wysyłanie pakietu danych (przykład danych: "12345678")
dane = b"12345678" # Przykładowe dane do wysłania
wyslij_pakiet_danych(s, dane)
# Oczekiwanie na ACK po wysłaniu pakietu danych
odpowiedz = s.recv(1)
print(f"Odebrano odpowiedź po pakiecie danych: {odpowiedz.hex()}")
if odpowiedz == ACK:
print("Odebrano ACK po pakiecie danych.")
# Wysłanie EOT
s.sendall(EOT)
print("Wysłano EOT, koniec transmisji.")
# Oczekiwanie na EOT
odpowiedz = s.recv(1)
print(f"Odebrano odpowiedź po EOT: {odpowiedz.hex()}")
if odpowiedz == EOT:
print("Odebrano EOT - zakończenie transmisji.")
else:
print("Błąd komunikacji - nie otrzymano ACK po wysłaniu pakietu startowego.")
else:
print(f"Odebrano nieoczekiwaną odpowiedź po ENQ: {odpowiedz.hex()}")
except socket.timeout:
print("Timeout - kasa nie odpowiada.")
except Exception as e:
print(f"Błąd: {e}")
if __name__ == "__main__":
komunikacja_z_kasą()
A tu co mi kasa odpowiada
Połączono z kasą.
Wysłano ENQ, oczekiwanie na odpowiedź...
Odebrano odpowiedź po ENQ: 06
Odebrano ACK - kasa gotowa do transmisji.
b'\x02SA0000000000000000000000000000000000000\x03'
b'\x02SA0000000000000000000000000000000000000\x03\x00\x10'
Wysłano pakiet startowy: 02534130303030303030303030303030303030303030303030303030303030303030303030303030030010
b'\x15'
Odebrano odpowiedź po pakiecie startowym: 15
Błąd komunikacji - nie otrzymano ACK po wysłaniu pakietu startowego.
Dziękuje za pomoc. Pozdrawiam