Adafruit_requests library functions differently than Python requests library - python-requests

So I'm trying to run a post request to a TD Ameritrade API on an adafruit Magtag device using the adafruit_requests module. I have run the same code in Python using the requests module, which has proven to work fine.
My Magtag device has successfully connected to the internet and executed the test requests adafruit supplied, but will not work with my code and returns a "duplicate headers" error. Below is the complete code that I ran on my MagTag device as well as the error message that was returned.
import ssl
import wifi
import socketpool
import adafruit_requests
import json
# Get wifi details from a secrets.py file
from secrets import secrets
# Connect to wifi
wifi.radio.connect(secrets["ssid"],secrets["password"])
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
# Get json data
refreshToken = ''
client_id = ''
with open("TDtokens.json","r") as tokens_file, open("TDsecrets.json","r") as secrets_file:
refreshToken = json.load(tokens_file)['refresh_token']
client_id = json.load(secrets_file)['client_id']
# Refresh token needs to be triggered every 30 minutes, as authToken expires.
url = r"https://api.tdameritrade.com/v1/oauth2/token"
headers = {'Content-Type':'application/x-www-form-urlencoded'}
data = {'grant_type': 'refresh_token','refresh_token': refreshToken,'client_id':client_id}
authReply = requests.post(url=url, headers=headers, data=data)
print(authReply.json())
{'fault': {'faultstring': 'Duplicate Header "Content-Type"', 'detail': {'errorcode': 'protocol.http.DuplicateHeader'}}}
I have done a lot of tweaking and I can't figure out where this error is coming from, whether from adafruit or TD Ameritrade's side. Upon reading the documentation for the adafruit_requests module I do not see any reason why an error would be raised for this type of request.
If you have any experience with adafruit or Python requests any advice would be greatly appreciated.

Related

httr authentication login/password in "xtb" API

I need to authenticate and get prices using this api
I have no experience with api so my attempt to login gives an error
login <- "vikov98261#jesdoit.com"
pass <- "QazQaz123"
library(httr)
resp <- POST("xapi.xtb.com",
body=list(userId = login,
password = pass) )
Error in curl::curl_fetch_memory(url, handle = handle) :
Failed to connect to xapi.xtb.com port 80: Timed out
Can someone show me how to do it right.
I would like an example of how the login request works.
And also I would like an example of how to get the prices of any currency
Their API documentation uses WebSocket syntax, so I assume xapi.xtb.com may only be used by the clients. I, for once, only managed to get WebSocket to work.
In order to make this work in r you would need a WebSocket client library for r, such as websocket. Once you have that:
1. Define connection
ws <- WebSocket$new("wss://ws.xtb.com/demo")
2. Log in
WebSocket clients work with events. The 'open' event is generated once the connection is established and the 'message' events are generated when messages are received. You need to write handlers for them to orchestrate the way you want to use the XTB API.
The first event will be 'open', so use that to send the login command.
ws$onOpen(function(event) {
ws$send({
"command":"login",
"arguments": {
"userId":"1000",
"password":"PASSWORD",
"appId":"test",
"appName":"test"
}
})
})
3. Your logic
The response to your login command will trigger a 'message' event, the output of which you will need to handle in your code.
ws$onMessage( <your-code-goes-here> )
The easiest way would probably be to send new commands based on what is the structure of the received message, although it can get really complicated with many commands.
4. Connect
After all handles have been defined, don't forget to connect.
ws$connect()

SSE with Leshan LWM2M Demo Server

I am trying to do an http api that interact with a Leshan Demo Server.
I was trying to handle the OBSERVE in LWM2M, but I need to handle the notification with http.
I discovered that leshan notify using SSE. So I was trying to implement the sse client in python using requests and sseclient.
This is my code:
response= requests.post(url_request , "format=TLV" , stream= True)
client = sseclient.SSEClient(response)
for event in client.events():
print(json.loads(event.data))
I tried to run my script but it seems like the stream is not opening and it close immediately without waiting for the answer of the server, even if requests by default implement keep_alive for TCP connection under HTTP and the stream is True.
Does someone know why?
Reading the sseclient documentation, the correct way so use SSEClient seems to be :
from sseclient import SSEClient
messages = SSEClient('http://example.com/sse_stream/')
for msg in messages:
do_something_useful(msg)
Reading the answer on Leshan Github, the stream URL for Leshan Server Demo seems to be http://your.leshan.server.org/event?ep=your_device_endpoint_name
So I tried that :
from sseclient import SSEClient
messages = SSEClient('http://localhost:8080/event?ep=my_device')
for msg in messages:
print (msg.event, msg.data)
And it works for me 🎉 ! Getting this kind of results when I observe the temperature instance of Leshan Client Demo :
(u'NOTIFICATION', u'{"ep":"my_device","res":"/3303/0","val":{"id":0,"resources":[{"id":5601,"value":-18.9},{"id":5602,"value":31.2},{"id":5700,"value":-18.4},{"id":5701,"value":"cel"}]}}')
(u'COAPLOG', u'{"timestamp":1592296453808,"incoming":true,"type":"CON","code":"POST","mId":29886,"token":"889372029F81C124","options":"Uri-Path: \\"rd\\", \\"reWfKIgPYD\\"","ep":"my_device"}')
(u'COAPLOG', u'{"timestamp":1592296453809,"incoming":false,"type":"ACK","code":"2.04","mId":29886,"token":"889372029F81C124","ep":"my_device"}')
(u'UPDATED', u'{"registration":{"endpoint":"my_device","registrationId":"reWfKIgPYD","registrationDate":"2020-06-16T10:02:25+02:00","lastUpdate":"2020-06-16T10:34:13+02:00","address":"127.0.0.1:44400","lwM2mVersion":"1.0","lifetime":300,"bindingMode":"U","rootPath":"/","objectLinks":[{"url":"/","attributes":{"rt":"\\"oma.lwm2m\\""}},{"url":"/1/0","attributes":{}},{"url":"/3/0","attributes":{}},{"url":"/6/0","attributes":{}},{"url":"/3303/0","attributes":{}}],"secure":false,"additionalRegistrationAttributes":{}},"update":{"registrationId":"reWfKIgPYD","identity":{"peerAddress":{}},"additionalAttributes":{}}}')
(u'COAPLOG', u'{"timestamp":1592296455150,"incoming":true,"type":"NON","code":"2.05","mId":29887,"token":"3998C5DE2588F835","options":"Content-Format: \\"application/vnd.oma.lwm2m+tlv\\" - Observe: 2979","payload":"Hex:e3164563656ce8164408c03199999999999ae815e108c032e66666666666e815e208403f333333333333","ep":"my_device"}')
If you are interested by notification only, just add a if msg.event == 'NOTIFICATION': block.

Flask Mail doesn't work when deployed on Ubuntu

I'm sending password reset email with Flask-Mail. When I tried it on development server everything works fine. When deployed on Ubuntu (using NGINX, Gunicorn) sending the email leads after a long loading time to Error 502 so I don't think there's problem in sending the email rather there's a problem in the settings.
My init code after deploying:
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
from flask_socketio import SocketIO
import json
with open('/etc/config.json') as config_file:
config = json.load(config_file)
app = Flask(__name__)
app.config['SECRET_KEY'] = config.get('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = config.get('SQLALCHEMY_DATABASE_URI')
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = config.get('EMAIL_USER')
app.config['MAIL_PASSWORD'] = config.get('EMAIL_PASS')
mail = Mail(app)
In config.json the information is correctly provided
Disabling CAPTCHA for clients
If you are not using 2-factor authentication and you have verified the credentials in your Python source are correct, follow these steps:
1.) Login to gmail in your browser
2.) Navigate to the DisplayUnclockCaptcha page.
3.) Click the continue button, and you will see the message 'Account access enabled Please try signing in to your Google account again from your new device or application.'
4.)Run your Python script - your login attempt should be successful.
Hello i might be a little late for this, but thomas your problem is caused because of linode which is probably the deployment server that you used, decided to default block the ports that you are using as you can see it here.
https://www.linode.com/community/questions/19082/i-just-created-my-first-linode-and-i-cant-send-emails-why
if u follow the process given it certainly will work

Question about pymodbusTCP server implementaion

We have a simulator(client) and controller(server).
The controller sends a command signal through ModbusTCP to the simulator.
I want to emulate this controller on my computer.
What I have done
For the test, I wrote pymodbus Server script on my pc and pymodbus Client script on another PC. There was no problem to read holding and input register from client pc.
I connected my clinet pc to controller(server) to know what kind of values I have to send to actual client(simulator). I found out that 8 registers(from 0 to 7) are used to store integer values.
I tried to establish a connection between my pc(sever) and simulator computer(client).I was able to establish a connection and send a response to the client.
Problem
I have no information about this client(simulator) because we have no access to the client script.
I found out that this client sends a request not only for the reading but also for writing.
When I use the holding register, I got an error "illegal data address." But the input register does not show any error. For this reason, I am using input_register to save a specific integer number.
I stored some values on input_register, but sever input_registers are written by client(simulator) as below.
write request from client(simulator)
polling server(pc) with modpoll software
Question
why write requests from the client(simulator) overwrite my input_register? As far as I know, input_register is used for only reading. I assume that I made a mistake in storing a variable on the input_register.
When I make a connection between controller and simulator, wireshark and modpoll show that client(simulator) reads registers (from 0 to 7). But when I make a connection between my server(pc) and client(simulator), my sever response with different register numbers as below. Resister number starts from 1000. Why does simulator request different register start number? ex) from 0: controller, from 1000: PC(sever)
First response from server(pc)
Update! my server can respond with the values but with wrong register numbers. I changed starting register number(0 -->1000).
I attached picture.
response from server(pc)
Please advice me on this issue.
I will do my best effort to solve this issue.
'''
from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusBinaryFramer
#%%
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
#%%
#%%
def run_server():
store = ModbusSlaveContext(
ir=ModbusSequentialDataBlock(0, [28692,28692,28692,28692,28692,65508,65508,65508
]),zero_mode=True)
context = ModbusServerContext(slaves=store, single=True)
StartTcpServer(context, address=("192.168.1.231", 502))
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.0'
#%%
if __name__ == "__main__":
run_server()
'''
Dear MarcosG,
I attached screen-shots from wireshark as below.
write request from clinet(simulator)
- as you can see clinet(simulator) send a request for writing and register number start from 256.
read response from server(controller)
- Sever(controller) responds to the request of clinet for reading. And it send a respond and register number start from 256.
polling sever with modpoll software
- we can look the values on the registers of sever, as you can see, values are stored in the register from 0 to 7. These values are from controller lever. If I adjust lever, these values are changing.
requested address_exel_File
- We have one more simulator(bridge2). It shows the same register number with both controller(server) and pc(server).
problem: the actual registers of sever which store values are from 0 to 7. However, Client and server communicate with different registers (from 256) which contain "0" values. But there is no issue for adjusting parameters of ship on the simulator.
Best regards
Byeon Seongsu

Log entry to Splunk using python

In Splunk we have an url, index, token, host, source and sourcetype and with those detail need to post data in splunk using python.
I was able to write a code using requests with URL, index, token and it works
import requests
url='SPLUNK_URL'
Header = {'Authorization': 'Splunk '+'1234567'}
json = {"index":"xxx_yyy", "event": { 'message' : "Value" } }
r = requests.post(url, headers=Header, json, verify=False)
But sometimes get this error ConnectionError: ('Connection aborted.', OSError("(10054, 'WSAECONNRESET')")). How to avoid this error ?
Assuming this is HEC,
I would compare the times you receive this error vs times you have issues on receiver, such as high CPU utilization , or internal logs for connection drops etc. That could be your answer as receiver rejects/resets. Also if you are sending directly to Indexer rather than mid instance, I believe there is a common issue for that.

Resources