Python - can't decipher serial port bits - python

I have a MaxiMet GMX600 weather station.
Here is the manual:
http://gillinstruments.com/data/manuals/maximet-manual-iss1.pdf
I have it connect to my serial port and it's spitting out data every 1 second. Which is great!
Unfortunately, I can't decipher the data...
I should be seeing strings like this:
$WIMWV ,069,R,004.06,N,A*00
$WIMWV,122,T,,N,A*14
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,037,P,RH,Y,000.0,M,PRECIP*0A
Followed 1 second later by:
$WIMWV ,238,R,000.46,N,A*06
$WIMWV,303,T,,N,A*15
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,037,P,RH,Y,000.0,M,PRECIP*0A
Followed 1 second later by:
$WIMWV ,130,R,000.21,N,A*0C
$WIMWV,205,T,,N,A*12
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,038,P,RH,Y,000.0,M,PRECIP*05
Unfortunately, all I'm seeing is gobbledy-gook such as:
�����������������W���������������������������������������������������������������]���}���������������������u���+��+����; ���; �����; k��K; ���K;k��;� ����;���;� ���;���u������������
Followed one second later by:
�叙���������������������W�����������������������������������������������������������������]��哙���������������������W���������������������������������������������������������������]��坙
Followed one second later by:
�����]���y����������������������W�����������������������������������������������������������������]��叙���������������������W�����������������������������������������������������������������]�
Here's my Python code:
import time
import serial
import binascii
import struct
ser=serial.Serial(
port='/dev/ttyAMA0',
baudrate=19200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=5
)
while 1:
y=0
str=""
while y<200:
#x=binascii.b2a_qp(ser.read()).strip().strip("=")
#x=binascii.hexlify(ser.read()).strip()
x=ser.read().strip()
#x=struct.pack('<h',int(ser.read()))
str=x+str
y=y+1
#ser.flush()
print str
You can see I've been trying to manipulate the bytes, but nothing is happening. I keep getting gobbldy-gook.
If I uncomment the line bin2ascii.hexlify(ser.read()).strip(), I get output like:
9fa78d919fa75dfb00ebe59599f9a79f9f9f9fa78fa3979fa9a795a38d998b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da78d9b9fa79d9fa39f9f9fa7998f9fa75dfb00ebe57d99f9a79f9f9f9fa78fa3979fa9a795a38f998b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79b999fa79f9fa39f9f9fa7938f9fa75dfb
Followed one second later by:
9f9fa79d9fa39f9f9fa78d959fa75dfb00ebe57999f9a79f9f9f9fa78fa3979fa9a795a39d978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79d9599a79d9fa39f9f9fa795979fa75dfb00ebe59b99f9a79f9f9f9fa78fa3979fa9a795a39f978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da7959b9fa79d9fa39f9f
Followed one second later by:
99a39d9d9f9da79b9d9fa79d9fa39f9f9fa793939fa75dfb00ebe57b99f9a79f9f9f9fa78fa3979fa9a795a399978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79f9d9fa79d9fa39f9f9fa797939fa75dfb00ebe59f99f9a79f9f9f9fa78fa3979fa9a795a39b978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da795
ASCII only goes up to 0x7F, so I guess all these 0x9_ numbers are producing the funny characters?
I'm afraid I'm really stuck. I can't decipher it - my Python skills aren't good enough and I've been at this for hours... Does anyone have any Python suggestions as to how I can fix this output?

Related

Controls computer keyboard through pyserial

I don't know how to use regular expression in a pile of code and I'm not sure how to code it correctly either. I tried to lookup for tutorial, guides, everything. But I'm still not understand about it, so please help me to fix my stupid code.
Summary of the working, I'm trying to code a small program that controls my computer keyboard through pyserial and with the help of microbit. For example, when button A is pressed, the microbit sends data to my computer through uart and my python shell at the end receiving the message, try to match it and execute the respective command.
This is the code of microbit
from microbit import *
uart.init(baudrate=57600, bits=8, parity=None, stop=1, tx=None, rx=None)
while True:
if button_a.is_pressed():
uart.write("Up")
display.show(Image.ARROW_NW)
if button_b.is_pressed():
uart.write("Down")
display.show(Image.ARROW_S)
else:
display.show(Image.ASLEEP)
This is the code of my python end
import re
import serial
import keyboard
serialPort = serial.Serial(port = "COM5", baudrate=57600,
bytesize=8, timeout=2, stopbits=serial.STOPBITS_ONE)
serialString = ""
while(1):
(serialPort.in_waiting > 0)
serialString = serialPort.readline()
wordsa = ("up")
wordsb = ("down")
if():
words = [word.lower() for word in wordsa if re.match('^[a-zA-Z]+', word)]
keyboard.press_and_release('up')
The problem is I want to have re to match the string or data received from microbit through uart at serialString = serial.Port.readline(), if the microbit sends UP, I would want python to match the data received is UP or Down, then press the keyboard key UP or DOWN respectively. Upon running this shitty code of mine, there are no errors showing up and it won't work at all. I think this is a very stupid question to ask, but please help me. This problem has burned a hole at my brain already.
Thank you and Kudos to DarryIG, Profile Link. He saved my days
If any beginners like me just wanting to do a match-up on a string.
You don't need to use regular expression. You can do it with operator == while = is assignment.
For example:
Game = ['Dota2', 'LoL']; #Games that you play
Like = ['Dota2', 'LoL']; #Games that your friend likes
if Game == Like:
print ('True')
else:
print ('False')
Output : True
Note: I know my answer sucks, but I just wanna keep this question answered just in case someone like me will need this information. Thanks for understanding.

Communicate via rs485 in python

I am new in python. I am trying to catch data from temperature sensor via RS485 in python
Here my code:
ser = serial.Serial(
port='COM3',
baudrate=19200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
print ser.write('{02RDD}\r')
Response: >> 8
The response is always string length (ex ser.write("abcd"), response is "4") no matter what I send.
Please help me how to solve this problem, Thanks
If you want to read from the serial port use ser.read() or ser.readline().
The ser.write(), which you have used, only returns the number of bytes sent, which should correspond to the length of the string. So it seems to work correctly.
You should maybe go though the examples that are given in the pyserial documentation to make youself more familiar with the library.

Why is a part of my Python code interpreted diffently when I add a seemingly unrelated part?

Some background: I'm implementing a GUI to interact with equipment via GPIB. The issue arises in this method:
from tkinter import *
from tkinter import ttk
import visa #PyVisa Package. pyvisa.readthedocs.io
from time import sleep
import numpy as np #NumPy Package. Scipy.org
def oneDSweep():
Voltage =[]
Current =[]
Source = []
try:
#Gate = parseGate(Gate1Input.get()) #Not implemented yet.
Min = float(Gate1MinInput.get()) #Add a check for valid input
#if Min < .001:
#Throw exception
Max = float(Gate1MaxInput.get()) #Add a check for valid input
VoltageInterval = .02 #Prompt user for interval?
rm = visa.ResourceManager()
SIM900 = rm.open_resource("GPIB0::1::INSTR") #Add a check that session is open.
x = 0
Volt = Min
while Volt <= Max:
SIM900.write("SNDT 1, 'VOLT " + str(Volt) + "'") #Set voltage.
SIM900.write("SNDT 7, 'VOLT? 1'") #Ask a port for voltage.
Vnow = SIM900.query("GETN? 7, 50") #Retrieve data from previous port.
Vnow = Vnow[6:15]
Vnow = float(Vnow) ############Error location
Voltage = np.append(Voltage, Vnow)
SIM900.write("SNDT 1, 'VOLT?'") #Ask a different port for voltage.
Snow = SIM900.query("GETN? 1, 50") #Retrieve data.
print(Snow) #Debugging method. Probably not problematic.
Snow = Snow[4:]
Snow = float(Snow)
sleep(1) #Add a delay for science reasons.
#The code below helps the while loop act like a for loop.
x = x+1
Volt = Min + VoltageInterval*x
Volt = float(truncate(Volt, 7))
finally:
print(Voltage)
print(Source)
Voltage.tofile("output.txt.",sep=",")
SIM900.write("FLSH")#Flush the ports' memories to ensure no bad data stays there.
I get a simple ValueError at the marked location during the first pass of the while loop; Python says it cannot convert the string to a float(more on this later). However, simply remove these five lines of code:
SIM900.write("SNDT 1, 'VOLT?'")
Snow = SIM900.query("GETN? 1, 50")
print(Snow)
Snow = Snow[4:]
Snow = float(Snow)
and the program runs perfectly. I understand the source of the error. With those lines added, when I send these two lines to my instrument:
SIM900.write("SNDT 7, 'VOLT? 1'")
Vnow = SIM900.query("GETN? 7, 50")
I get essentially a null error. #3000 is returned, which is a blank message the machine sends when it is asked to output data and it has none to output. However, these same two lines produce something like #3006 00.003 when the four lines I mentioned are excluded from the program. In other words, simply adding those four lines to my program has changed the message sent to the instrument at the beginning of the while loop, despite adding them near the end.
I am convinced that Python's interpreter is at fault here. Earlier, I was cleaning up my code and discovered that one particular set of quotes, when changed from ' to ", produced this same error, despite no other quote pair exhibiting this behavior, even within the same line. My question is, why does the execution of my code change dependent upon unrelated alterations to the code(would also appreciate a fix)? I understand this problem is difficult to replicate given my somewhat specific application, so if there is more information that would be helpful that I can provide, please let me know.
EDIT: Functionality has improved after moving from the command prompt to IDLE. I'm still baffled by what happened, but due to my meager command prompt skills, I can't provide any proof. Please close this question.
Python is telling you exactly what is wrong with your code -- a ValueError. It even gives you the exact line number and the value that is causing the problem.
'#3006 00.003'
That is the value of SNOW that is being printed out. Then you do this
SNOW = SNOW[4:]
Now SNOW is
'6 00.003'
You then try to call float() on this string. 6 00.003 can't be converted to a float because it's a nonsensical number.
I am convinced that Python's interpreter is at fault here. Earlier, I was cleaning up my code and discovered that one particular set of quotes, when changed from ' to ", produced this same error, despite no other quote pair exhibiting this behavior, even within the same line.
Python generates exactly the same bytecode for single and double quoted strings (unless embedded quotes are involved, of course). So either the environment you're running your script in is seriously broken (I'm counting the python interpreter as part of the "environment"), or your diagnosis is incorrect. I'd put my money on the second.
Here's an alternative explanation. For whatever reason, the hardware you hooked up is returning inconsistent results. So one time you get what you expect, the next time you get an error-- you think your changes to the code account for the differences, but there's no relationship between cause and effect and you end up pulling your hair out. When you run the same code several times in a row, do you get consistent results? I.e. do you consistently get the odd behavior? Even if you do, the problem must be with the hardware or the hookup, not with Python.

Python, serial - changing baudrate, strange behaviour

I am having troubles with changing baudrate while the port is running. All the communication is run at 100k baud, but I also need to send some data at 10k baud. I've read I should use setBaudrate method, so I tried this:
ser = serial.Serial(2, baudrate=BAUD, timeout=TIMEOUT)
def reset(string):
if string:
ser.flushInput() #erase input and output buffers
ser.flushOutput()
ser.setBaudrate(RESET_BAUD) #change baudrate to 10k
ser.write(string)
ser.setBaudrate(BAUD) #go back to 100k
The problem is, it doesn't work right. I don't know what is wrong here, but the string just isn't received properly. But here is interesting part - if I remove the last line (going back to 100k) and run this function from the shell, everything is fine. Then I can just run the last command directly in shell, not inside function.
My question is what exactly happens here and how to avoid it? All I need is a function to send a string with different baudrate and then return to the original baudrate...
You need to wait long enough for the string to be sent before resetting the BAUD rate - otherwise it changes while some of it is still in the serial port (hardware) buffer.
Add time.sleep(0.01*len(string)) before the last line.
BTW try not to use reserved words like string as variable names as it can cause problems.
My guess is that the baud rate is being changed before the data is actually sent. A good bet is to force the data to be sent before trying to change the baud rate.
According to the docs, this is done by calling Serial.flush() (not flushInput() or flushOutput(), as these just discard the buffer contents).

extracting ip address from raw_input

I have compiled a script in python 2.6.5, The script is simply to automate my most used functions for nmap and log the output to a txt file on the desktop.
I haven't written this all myself as i am still only learning python. I found an update script for updating backtrack and used that as a template for indentation and commands and modified it and added some of my own stuff to give me what i needed.
The problem i'm having is with this block
def nmap_target():
try: ip = raw_input(" [>] Enter ip to scan: ")
except KeyboardInterrupt:
print "\n [>] Exiting!\n"
sleep(1)
sys.exit()
print " [>] Attempting targeted scan.\n"
#print ip
if subprocess.Popen("nmap ip >> //root/Desktop/Target.txt && tail /root/Desktop/Target.txt",shell=True).wait() == 0:
print "\n"
print " [>] Targeted scan completed successfully!\n"
menu_main()
else:
print "\n"
print " [>] Nmap scan failed.\n"
The idea behind it is that it asks the user to input an ip address into raw_input() and call it ip, I'm trying to then pass it to nmap using subprocess.Popen("nmap ip as can be seen above.
The problem is its just writing nmap ip rather than printing the ip address and then returning errors, It even tries to scan out of my network, every time i test it i make sure the internet cable is unplugged from my router, This causes a bug with my internet test though, so if you try running the code bellow you may need to hash out the internet_check() option in the menu_main() section if you have your internet unplugged from the router
I have spent 4 days on this now and its driving me mad, At first i thought i needed to convert the number to floating point so i tried that and still the same, I've tried all sorts of things and spent hours trawling the internet looking for an answer to no avail.
I am now convinced its not the command i'm trying that is to blame i think it is the exit statement, I have tried putting "print ip" right after the line where it says "print " [>] Attempting targeted scan.\n" and sure enough the ip address that was entered is displayed on the screen, That proved to me that raw_input() is working. As soon as i move it anywhere bellow that it fails, This suggests to me that it must be either a problem with the exit statement or maybe indentation, I'm not sure though.
I have also tried hashing out the keyboard interrupt as well as the couple of lines bellow, i tried moving the try: and if statements around and even tried other commands instead but it just wont work aaaarrrrrgggghhhhhh
Would i be right in thinking that the ip is being entered into raw_input() and then the file ip that was created that holds the ip address is being destroyed before i can pass it to subprocess.Popen("nmap ip.
Like i mentioned i didn't write this script from scratch and this is my first project like this so i've got a lot to learn, I've been all through the python man pages and looked through all sorts of tutorials but just can't figure this out.
Any help will be much appreciated
i will post the full script if anyone is interested,just as soon as i can figure out how to post code properly
You need to seperate the variable from the string! Try this :D
if subprocess.Popen('nmap '+ip+' >> //root/Desktop/Target.txt && tail /root/Desktop/Target.txt',shell=True).wait() == 0:
Hope it helps!
EDIT - If for some reason python takes the raw input as an integer, convert it to string like so:
if subprocess.Popen('nmap '+str(ip)+' >> //root/Desktop/Target.txt && tail /root/Desktop/Target.txt',shell=True).wait() == 0:
Python doesn't like to concatenate str and int types, or so it tells when my script fails :P I am pretty sure your ip variable will be str type though so the first example should work.
Cheers!
You need to format the string properly or the string ip won't be interpreted at all, i.e. it won't get replaced wth the actual IP. Try something like:
cmd = "nmap ${0} >> [....] root/Desktop/Target.txt".format(ip)
if subprocess.Popen(cmd):
You could also use the % operator:
cmd = "nmap %s >> [....] root/Desktop/Target.txt" % ip

Categories