Jump to content

[Python] Base58 in Int


Recommended Posts

Ich komme auf 33688 ;).

olaf@pc:~$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> BASE58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
>>> def base58decode(encoded):
...     value = 0
...     column_multiplier = 1
...     for c in encoded[::-1]:
...         column = BASE58.index(c)
...         value += column * column_multiplier
...         column_multiplier *= 58
...     return value
... 
>>> base58decode("b1Q")
33688

 

Händisch:

>>> BASE58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
>>> BASE58.index('b')
10
>>> BASE58.index('1')
0
>>> BASE58.index('Q')
48
>>> 10*58**2 + 0*58**1 + 48*58**0
33688

Link zu diesem Kommentar
Share on other sites

Ok. Danke, habe eine falsche Zeichntabelle verwendet.

 

Ich versuche direkt über die RS485 Extension (Slave, Adresse: 1) mit einem Ambient Light Bricklet (UID: b1Q) zu kommunizieren. Wenn ich folgendes sende müsste ich doch die Helligkeit als Antwort erhalten:

 

Modbus Adress: 0x01

Func. Code:    0x64

Seq. Num:      0x01

UID:          0x98 0x83 0x00 0x00

Packet Length: 0x08

Func ID:      0x01

Seq. Num.:    0x18

Flags:        0x00

CRC16:        0xAE 0x41

 

Ich bekomme aber nur 0x00 zurück. Habe ich irgendwo einen Fehler übersehen?

Link zu diesem Kommentar
Share on other sites

Sprichts du denn das Protokoll auch so wie hier beschrieben:

 

http://www.tinkerforge.com/de/doc/Low_Level_Protocols/Modbus.html#requests-and-responses

 

Sprich pollst du den Slave für Responses nachdem du ihm den Request gesendet hast? Slaves dürfen von sich aus keinen Response senden, sondern nur als Antwort auf einen Request.

 

Edit:

 

Hätte mal richtig lesen sollen. Wie handhabt dein RS485 Wandler den Transmitter und Receiver Enable? Steuerst du das von Hand, oder passiert das automatisch?

 

Wenn der Transmitter auf der Master-Seite aktiviert ist wenn der Slave antwortet dann kann die Antwort verfälscht ankommen.

Link zu diesem Kommentar
Share on other sites

  • 2 weeks later...

Hallo,

 

zur Hardware:

-Rasperry Pi mit aktuellem Raspian und Python 3

-Raspicomm Erweiterung für RS485 (andere RS485 Boards bei denen man den RTC Pin für die Datenrichtung manuell setzen muss gehen auch, machen das programmieren aber sehr aufwändig)

-ein Stück dreiadriges Kabel

-Masterbrick mit RS485 Extension

 

Hier der Python Code. Er funktioniert ist aber ein erster Entwurf und noch nicht optimiert.

 

@borg: passt denn die Bestätigung nach erfolgreicher Abfrage:

0x01, 0x64, modbus_sequence, crc16

 

 

import serial
import time
import crc16


def get_value(port, mod_adr, mod_seq, tcp_seq, func_id):		#Abfrage des Bricks

flag = True													#Flag True bis Abfrage erfolgreich


req = bytearray([0x01, 0x64, mod_seq, mod_adr[0], mod_adr[1], mod_adr[2], mod_adr[3], 0x08, func_id, tcp_seq, 0x00])		#bytearray für modbus/tcp Abfrage

crc_req = 0xFFFF
for x in range (0, 11):										#Prüfsumme berechnen
	crc_req = crc16.calcByte( int.from_bytes(req[x:x+1], byteorder='big'), crc_req)

req[11:13] = crc_req.to_bytes(2, byteorder='little')		#Prüfsumme anhängen


ack = bytearray([0x01, 0x64, mod_seq])						#bytearray für modbus Bestätigung

crc_ack = 0xFFFF
for x in range (0, 3):										#Prüfsumme berechnen
	crc_ack = crc16.calcByte( int.from_bytes(ack[x:x+1], byteorder='big'), crc_ack)

ack[3:5] = crc_ack.to_bytes(2, byteorder='little')			#Prüfsumme anhängen



while flag:													#solange Abfrage nicht erfolgreich
	port.write(req)											#Abfrage schicken
	ans = b'\x00'
	ans = port.read(20)										#Antwort empfangen

	leng = int.from_bytes(ans[7:8], byteorder='big')		#Länge des TCP Packets bestimmen

	crc_ans = 0xFFFF
	for x in range (0, leng+3):								#Prüfsumme der Antwort berechnen
		crc_ans = crc16.calcByte( int.from_bytes(ans[x:x+1], byteorder='big'), crc_ans)

	if bytearray([0x01, 0x64, mod_seq, mod_adr[0], mod_adr[1], mod_adr[2], mod_adr[3]]) in ans[0:7]:		#Antwort mit Abfrage vergleichen (Adresse)
		if (int.from_bytes(ans[leng+3:leng+5], byteorder='little')) == crc_ans:				#Prüfsumme kontrollieren
			port.write(ack)									#Bestätigung senden
			if leng > 8:									#wenn Daten vorhanden
				val = int.from_bytes(ans[11:11+leng-8], byteorder='little')			#Daten ausgeben
				return val
			else:
				return 0
			flag = False
	else:
		flag = True											#fehlerhafte Antwort, erneuter Versuch



if __name__ == "__main__":										#Hauptprogramm

port = serial.Serial(port='/dev/ttyRPC0', baudrate=115200, timeout=2)		#Port öffnen, 115200 Baud, 8N1


time.sleep(.1)

mod_adr = bytearray([0x98, 0x83, 0x00, 0x00])				#Adresse des Brick/Bricklet
mod_seq = 0x01												#Modbus sequence number
tcp_seq = 0x01												#TCP sequence number
func_id = 0x01												#Funktions ID

value = get_value(port, mod_adr, mod_seq, tcp_seq,func_id)	#Abfrage

print ("Wert: %d\n" % value)								#Wert ausgeben

 

Verbesserungsvorschläge und Fragen sind natürlich wilkommen.

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...