Loop through all serial addresses to locate hardware - python

I'm new to python and I'm trying to loop through all 255 addresses to locate a specific bit of hardware over RS485. The hardware is attached, and it's address is supposed to be 0x25, but this is not the case, so I need to find what its address is.
So far I've got:
def Init_Sync_4 ():
GPIO.output(18,GPIO.HIGH)
ser.write([CID,0x17,0x20,0x01,0x14,0x1c,0x04,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x02,0x00,0x00,0$
time.sleep(0.007)
GPIO.output(18,GPIO.LOW)
and
ser=serial.Serial(port='/dev/serial0',baudrate=38400,stopbits=2,timeout=1)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,GPIO.LOW)
for i in range(0xff):
CID = '0x{:02x}'.format(i).encode('ascii')
print "at address %s" % CID
Init_Sync_4()
time.sleep(0.05)
Init_2()
time.sleep(0.05)
Here CID is the address being built, which Init_Sync_4() uses in it's byte array in ser.write, but I keep getting the error:
at address 0x00
Traceback (most recent call last):
File "rs485_test_2.py", line 97, in <module>
Init_4()
File "rs485_test_2.py", line 40, in Init_4
ser.write([CID,0x17,0x20,0x01,0x14,0x1c,0x04,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x02,0x00,0x00,0x00,0x00])
File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 518, in write
d = to_bytes(data)
File "/usr/lib/python2.7/dist-packages/serial/serialutil.py", line 66, in to_bytes
return bytes(bytearray(seq))
ValueError: string must be of size 1
I'm assuming that it's still being passed as a string, when it needs to be a single byte, but I'm lost at how the conversion would work. I've checked out some SO pages, that specify using .encode with or without params, but I'm either using it incorrectly, or it's not quite what I'm after. Any help is greatly appreciated! Thanks.

ser.write([CID,0x17,0x20,0x01, ...
CID is going into a list with a bunch of integers. But itself is a string.
You want to leave CID as an integer.
# CID = '0x{:02x}'.format(i).encode('ascii')
CID = i

Related

How to get pool.py to accept non ascii characters?

I am using Python 2.7.18
The idea is to use python to gather songs from specified directories, then create and run the commands to run them through a bunch of converters and sound processors.
Some of my songs have characters with accents and any song with a ? in the title gets changed to a ¿ (Inverted Question Mark) in the file name.
My convert_song function works correctly when ran, but when I try to run it in a Pool and the file name or directory has a non ascii character in it, it fails with:
Traceback (most recent call last):
File "C:\StreamLine.py", line 270, in <module>
result = pool.map(convert_song, qTheStack)
File "C:\Python27\lib\multiprocessing\pool.py", line 253, in map
return self.map_async(func, iterable, chunksize).get()
File "C:\Python27\lib\multiprocessing\pool.py", line 572, in get
raise self._value
UnicodeEncodeError: 'ascii' codec can't encode character u'\xbf' in position 27: ordinal not in range(128)
Here's my main where I set up the pool:
if __name__ == '__main__':
print('Reading artists.')
predir = 'G:\\Vault\\The Music\\'
artistfile = open('C:\\Controls\\ArtistList.txt', 'r')
artistlist = artistfile.readlines()
dirs = []
for artist in artistlist:
dirs.append(predir + artist.strip())
qTheStack = []
for currentPath in dirs:
for wFile in generate_next_file(currentPath):
print(repr(wFile))
#print(convert_song(wFile))
qTheStack.append(wFile)
print('List loaded.')
pool = Pool(12)
result = pool.map(convert_song, qTheStack)
for item in result:
print(item)
The print(repr(wFile)) looks like this when ran:
'G:\\Vault\\The Music\\Chicago\\1989 - Greatest Hits 1982-1989\\04 - Will You Still Love Me\xbf.flac'
'G:\\Vault\\The Music\\Chicago\\1989 - Greatest Hits 1982-1989\\06 - What Kind of Man Would I Be\xbf [Remix].flac'
How can I get the built-in Pool from multiprocessing to accept my input?
Change to Python 3, dude.
As much as I wanted there to be an answer that stayed on Python 2.7, I tried Python 3 and it didn't disappoint.
I did have to go back through the obscure steps I found to generate a file that will run a COM/DLL in Python, and I had to remove all the str.decode and encode calls throughout my script. After only one import change, I hit run and it ran as expected.

Parsing DNS RDATA using python

I'm trying to use Python to parse hex-formated DNS RDATA-values (should be RFC1035-compliant) that's generated in audit logs from Windows DNS Server when a record is created or deleted. I've tried a couple of Python dns-modules and think I'm getting close with dnslib, however all the documentation I find is for parsing a complete DNS-packet captured from the network including question and answer header ++.
The audit log only provides the class type and the RDATA it stores in AD (Active Directory-integrated zone), so I figured I might be able to use the parse(buffer,length) method of the individual record type-classes to parse it, but so far all my attempts are failing.
Sample data:
Type = MX
RDATA = 0A0011737276312E636F6E746F736F2E636F6D2E
Which should be parsed to:
preference = 10
mx = srv1.contoso.com.
Latest attempt:
import dnslib
import binascii
mxrdata = binascii.unhexlify(b'0A0011737276312E636F6E746F736F2E636F6D2E')
b = dnslib.DNSBuffer(mxrdata)
mx = dnslib.MX.parse(b,len(b))
this fails with:
Traceback (most recent call last):
File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1250, in parse
mx = buffer.decode_name()
File "C:\Python37-32\lib\site-packages\dnslib\label.py", line 235, in decode_name
(length,) = self.unpack("!B")
File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 103, in unpack
data = self.get(struct.calcsize(fmt))
File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 64, in get
(self.offset,self.remaining(),length))
dnslib.buffer.BufferError: Not enough bytes [offset=20,remaining=0,requested=1]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1254, in parse
(buffer.offset,e))
dnslib.dns.DNSError: Error unpacking MX [offset=20]: Not enough bytes [offset=20,remaining=0,requested=1]
Can anyone help me? Is it even possible using this module?
You are encoding the RDATA wrongly a bit:
First, you specify the preference:
0A00
However, this is not 10 (because integer are encoded MSB first, not LSB first), but 2560. So this should be
000A
Then, you try to encode the hostname here:
11737276312E636F6E746F736F2E636F6D2E
0x11 should be the length byte and the rest is the domain name srv1.contoso.com.. But this is not how encoding a hostname works. You have to encode each label separately with a length byte and terminate the hostname with a 0-length label. So this should be:
04 73727631 07 636F6E746F736F 03 636F6D 00
s r v 1 . c o n t o s o . c o m .
This adds up to:
mxrdata = binascii.unhexlify(b'000A047372763107636F6E746F736F03636F6D00')
Them the parser should succeed. So if you really get the RDATA in such an invalid format, you have to convert it first in to make it rfc1035-compliant.

Python For Loop errors on sedond Pass

I am trying to use a for loop as follows:
addresses = [0x30, 0x31, 0x32, 0x33]
for address in addresses:
print(address)
chirp = chirp.Chirp(address=address,
read_moist=True,
read_temp=True,
read_light=True,
min_moist=False,
max_moist=False,
temp_scale='farenheit',
temp_offset=0)
chirp.trigger()
log_values(address, chirp.moist, chirp.temp, chirp.light)
time.sleep(1)
It seems to work on the first pass in the console I see 48, then 49 then get this error:
Traceback (most recent call last):
File "readings_logger.py", line 17, in <module>
chirp = chirp.Chirp(address=address,
AttributeError: 'Chirp' object has no attribute 'Chirp'
Which I think indicates that it ran once. Then on the second pass could not run it. My first thought was a local variable issue so tried to delete 'chirp' lower case 'c' but that did not help. My guess is this threading but I am new to python and not sure how to prevent that.
You are reassigning chirp when you are setting it equal to chirp.Chirp(...).
Try to change the variable assignment (after print(address) to something like loop_chirp = chirp.Chirp(...). Each subsequent line would now be changed to loop_chirp followed by the attribute.

Generating SSH keypair with paramiko in Python

I am trying to generate a SSH key pair with the python module paramiko. There doesn't seem to be much info about key generation. I've read through the paramiko docs but can't figure out whats wrong. I can generate a private and public key without password encryption. However, when I try to encrypt the private key I get the following error.
ValueError: IV must be 8 bytes long
I believe the above error is from pycrypto. I've looked through the relevant code in paramiko.pkey and pycrypto without any luck.
Here is a small example.
import paramiko
def keygen(filename,passwd=None,bits=1024):
k = paramiko.RSAKey.generate(bits)
#This line throws the error.
k.write_private_key_file(filename,password = 'cleverpassword')
o = open(fil+'.pub' ,"w").write(k.get_base64())
traceback
Traceback (most recent call last):
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Documents/test.py", line 14, in keygen
k.write_private_key_file(filename,password = 'cleverpassword')
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/rsakey.py", line 127, in write_private_key_file
self._write_private_key_file('RSA', filename, self._encode_key(), password)
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/pkey.py", line 323, in _write_private_key_file
self._write_private_key(tag, f, data, password)
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/pkey.py", line 341, in _write_private_key
data = cipher.new(key, mode, salt).encrypt(data)
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/DES3.py", line 114, in new
return DES3Cipher(key, *args, **kwargs)
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/DES3.py", line 76, in __init__
blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs)
File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/blockalgo.py", line 141, in __init__
self._cipher = factory.new(key, *args, **kwargs)
ValueError: IV must be 8 bytes long
The Problem
This looks like a bug in paramiko.
If you look at the line that threw the error in pkey.py, it is the following line:
data = cipher.new(key, mode, salt).encrypt(data)
Let us now look at the lines before it, which set the mode by first selecting a cipher_name.
# since we only support one cipher here, use it
cipher_name = list(self._CIPHER_TABLE.keys())[0]
cipher = self._CIPHER_TABLE[cipher_name]['cipher']
keysize = self._CIPHER_TABLE[cipher_name]['keysize']
blocksize = self._CIPHER_TABLE[cipher_name]['blocksize']
mode = self._CIPHER_TABLE[cipher_name]['mode']
Here are the contents of _CIPHER_TABLE.
_CIPHER_TABLE = {
'AES-128-CBC': {'cipher': AES, 'keysize': 16, 'blocksize': 16, 'mode': AES.MODE_CBC},
'DES-EDE3-CBC': {'cipher': DES3, 'keysize': 24, 'blocksize': 8, 'mode': DES3.MODE_CBC},
}
Observe how the comment contradicts the code. Two ciphers are available, and the line above which selects the cipher_name assumes there is only one.
Based on the error, it appears that 'DES-EDE3-CBC' is selected. If we look at the comment in DES3.py, we see the following requirement for an IV.
IV : byte string
The initialization vector to use for encryption or decryption.
It is ignored for `MODE_ECB` and `MODE_CTR`.
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
and `block_size` +2 bytes for decryption (in the latter case, it is
actually the *encrypted* IV which was prefixed to the ciphertext).
It is mandatory.
From paramiko's source, we observe that no IV is passed, and hence the error we saw.
Workaround
Change the following line in pkey.py to hardcode the 'AES-128-CBC' cipher instead.
# cipher_name = list(self._CIPHER_TABLE.keys())[1]
cipher_name = 'AES-128-CBC'

Syntax error with json process ?

I have been working a solution for a game which creates stats for two different players then saves to a .txt, For some reason, unbeknownst to me a sytax error keeps on appearing, here ;
Traceback (most recent call last):
File "E:\CA2 solution.py", line 29, in <module>
json.dump(char_data,open("character_data.dat","wb"))
File "C:\Python33\lib\json\__init__.py", line 184, in dump
fp.write(chunk)
TypeError: 'str' does not support the buffer interface
Im not sure what is wrong but here is the code as well,
import random
char1=str(input('Please enter a name for character 1: '))
strh1=((random.randrange(1,4))//(random.randrange(1,12))+10)
skl1=((random.randrange(1,4))//(random.randrange(1,12))+10)
line = '%s has a strength value of %s and a skill value of %s'%(char1,strh1,skl1)
char2=str(input('Please enter a name for character 2: '))
strh2=((random.randrange(1,4))//(random.randrange(1,12))+10)
skl2=((random.randrange(1,4))//(random.randrange(1,12))+10)
line = '%s has a strength value of %s and a skill value of %s'%(char1,strh1,skl1)
char_data1 = {
"name":char1,
"STRENGTH":strh1,
"SKILL":skl1,
};
char_data2 = {
"name":char2,
"STRENGTH":strh2,
"SKILL":skl2,
};
char_data = [char_data1,char_data2]
import json
json.dump(char_data,open("character_data.dat","wb"))
char_data_loaded = json.load(open("character_data.dat"))
I don't know what is wrong, so if anyone does could they please help me and point it out and suggest a way to fix it ? Thanks !
You are giving a string input to a file opened in binary mode. json.dump serializes the char_data as a string as noted in the doc here
So open the file in w mode instead of wb and the error will be fixed.

Categories