Reading Response message in modbus using python - python

I am trying send the query and get the response message (data) through modbus using python with the help of pymodbus module.
response=client.read_holding_registers(19200,126,unit=135)
print(response)
The response that is being printed is the request message sent and the process status. I am interested in reading the data sent from the slave and not the process status. Can you please help me with this?

You should use the .registers
Try the following procedure:
response = client.read_holding_registers(19200, 126, unit=135)
if not response.isError():
print(response.registers)
else:
# Handle Error
[NOTE]:
.isError() method is for pymodbus 1.4.0 and above.

Related

httpx.RemoteProtocolError: peer closed connection without sending complete message body

I am getting the above error despite setting the timeout to None for the httpx call. I am not sure what I am doing wrong.
from httpx import stream
with stream("GET", url, params=url_parameters, headers=headers, timeout=None) as streamed_response:
I've got the same error when using httpx via openapi-client autogenerated client
response = httpx.request(verify=client.verify_ssl,**kwargs,)
It turned out in kwargs parameter headers contained wrong authorization token.
So basically in my case that error meant "authorization error".
You might want to check if what you sending in your parameters is correct too.

Wunderbit webhook message from python

I try to send webhook alerts to wunderbit (crypto trading platform), but i receive
<Response 403> error. Please help.
My code:
import requests
target_url= "https://wundertrading.com/bot/exchange"
message = "My open long command(generated by wunderbit)"
my_request = requests.get(target_url, data = message, headers = {"Content-Type": "text/plain"})
print(my_request)
were you trying to send a signal from a custom server?
Only signals from TradingView were allowed previously. Now you can send a custom signal, but you will need to whitelist your IP first. see WunderTrading documentation

In Django, how to re-package a Request.response as a Django response?

I have a Django App that accepts messages from a remote device as a POST message.
This fits well with Django's framework! I used the generic View class (from django.views import View) and defined my own POST function.
But the remote device requires a special reply that I cannot generate in Django (yet). So, I use the Requests library to re-create the POST message and send it up to the manufacturer's cloud server.
That server processes the data, and responds with the special message in the body. Idealy, the entire HTML response message should go back to the remote device. If it does not get a valid reply, it will re-send the message. Which would be annoying!
I've been googling, but am having trouble getting a clear picture on how to either:
(a): Reply back in Django with the Requests.response object without any edits.
(b): Build a Django response and send it back.
Actually, I think I do know how to do (b), but its work. I would rather do (a) if its possible.
Thanks in Advance!
Rich.
Thanks for the comments and questions!
The perils of late night programming: you might over-think something, or miss the obvious. I was so focused on finding a way to return the request.response without any changes/edits I did not even sketch out what option (b) would be.
Well, it turns out its pretty simple:
s = Session()
# Populate POST to cloud with data from remote device request:
req = Request('POST', url, data=data, headers=headers)
prepped = req.prepare()
timeout = 10
retries = 3
while retries > 0:
try:
logger.debug("POST data to remote host")
resp = s.send(prepped, timeout=timeout)
break
except:
logger.debug("remote host connection failed, retry")
retries -= 1
logger.debug("retries left: %d", retries)
time.sleep(.3)
if retries == 0:
pass # There isn't anything I can do if this fails repeatedly...
# Build reply to remote device:
r = HttpResponse(resp.content,
content_type = resp.headers['Content-Type'],
status = resp.status_code,
reason = resp.reason,
)
r['Server'] = resp.headers['Server']
r['Connection'] = resp.headers['Connection']
logger.debug("Returning Server response to remote device")
return r
The Session "s" allows one to use "prepped" and "send", which allows one to monkey with the request object before its sent, and to re-try the send. I think at least some of it can be removed in a refactor; making this process even simpler.
There are 3 HTTP object at play here:
"req" is the POST I send up to the cloud server to get back a special (encrypted) reply.
"resp" is the reply back from the cloud server. The body (.content) contains the special reply.
"r" is the Django HTTP response I need to send back to the remote device that started this ball rolling by POSTing data to my view.
Its pretty simple to populate the response with the data, and set headers to the values returned by the cloud server.
I know this works because the remote device does not POST the same data twice! If there was a mistake anyplace in this process, it would re-send the same data over and over. I copied the While/try loop from a Socket repeater module. I don't know if that is really applicable to HTTP. I have been testing this on live hardware for over 48 hours and so far it has never failed. Timeouts are a question mark too, in that I know the remote device and cloud server have strict limits. So if there is an error in my "repeater", re-trying may not work if the process takes too long. It might be better to just discard/give up on the current POST. And wait for the remote device to re-try. Sorry, refactoring out loud...

Why is my request in Python not registered by the server?

I am currently writing a script in Python which allows to listen the serial port from a connected device in order to guess the height of a person when passing through a door.
The final idea is to send this information to Piwik, a web analytics package through a http request.
The code is as follow:
import serial, httplib, uuid
arduino = serial.Serial('/dev/ttyACM0', 9600)
while True:
data = arduino.readline()
print data
conn = httplib.HTTPConnection("my-domain.com")
conn.request("HEAD","/piwik/piwik.php?idsite=1&rec=1&action_name=Entree-magasin&uid="+str(uuid.uuid4())+"&e_c=entree-magasin&e_a=passage&e_n=taille&e_v="+str(data)+"")
print conn.request
when I just ask to print the following line:
"/piwik/piwik.php?idsite=1&rec=1&action_name=Entree-magasin&uid="+str(uuid.uuid4())+"&e_c=entree-magasin&e_a=passage&e_n=taille&e_v="+str(data)+""
it works fine. But if I look in the logs of the server hosting my website the request is not sent.
If I remove the following part "&e_c=entree-magasin&e_a=passage&e_n=taille&e_v="+str(data)+" then it works fine and the request is sent.
If I leave the following part &e_c=entree-magasin&e_a=passage&e_n=taille&e_v="+str(data)+" and hard code the following value +str(data)+ by a figure, then the request is sent too.
I don't really where the problem can be. If anyone can help that would be great.
After reading your answers and work on and on on it, I find a way of optimizing my code by using the requests function instead, but the result is still the same i cannot get str(data) value within my request:
import serial, requests, uuid
arduino = serial.Serial('/dev/ttyACM0', 9600)
while True:
data = arduino.readline()
print data
r = requests.get('http://my-domain.com/piwik/piwik.php?idsite=1&rec=1&action_name=Entree-magasin&uid='+str(uuid.uuid4())+'&e_c=entree-magasin&e_a=passage&e_n=taille&e_v='+str(data)+'')
print r
Try the below code, the parameters are not part of header
resp, content = h.request("http://my-domain.com/piwik/piwik.php?idsite=1&rec=1&action_name=Entree-magasin&uid="+str(uuid.uuid4())+"&e_c=entree-magasin&e_a=passage&e_n=taille&e_v="+str(data), "GET")
I think I figured it out. I tried to do the same thing but with Google Analytics instead of Piwik. It works with Google Analytics, the str(data) is going back properly within the system, but for some reason it is not working with Piwik :(

How do you read a HTTP response using the python sockets module?

I am implementing a simple web-proxy using the python sockets module. After forwarding on the client's HTTP request to the server I use the following method to read the response:
def _read_response(self):
response = ''
while True:
(readable, _, error) = select.select([self.server], [], [self.server], 3)
if error:
break
if readable:
data = self.server.recv(BUFSIZE)
if not data: break
response += data
return response
The above code seems to work in most cases however it is slow. I narrowed this problem down to the line:
data = self.server.recv(BUFSIZE)
This call takes upwards of 20 seconds when there is no longer any data to receive (when data == '').
What is the correct way to read a http response and why does the call to recv() take so long?
Parse the content-length header before reading the body.
Then read only content-length bytes from the server.
You may want to set non-blocking mode of the socket by:
socket.setblocking(flag)
or set a timeout on the socket operation:
socket.settimeout(value)

Categories

Resources