sys:1: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensors' was never awaited - async-await

I am a beginner trying to get the data from airthings plus to hubitat using a raspberry pi. When running a python script I get this error message :
readwaveplus.py:391: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensor_data' was never awaited
data = airthingsdetect.get_sensor_data()[MAC]
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Read Error
^CTraceback (most recent call last):
File "readwaveplus.py", line 414, in <module>
time.sleep(SamplePeriod)
KeyboardInterrupt
sys:1: RuntimeWarning: coroutine 'AirthingsWaveDetect.get_sensors' was never awaited
It seems I need to add "await" somewhere but I am not able to figure out where. I tried to add await but not sure where It should be added.
Here is the script :
async def main():
logging.basicConfig()
_LOGGER.setLevel(logging.DEBUG)
ad = AirthingsWaveDetect(0)
num_dev_found = await ad.find_devices()
if num_dev_found > 0:
devices = await ad.get_info()
for mac, dev in devices.items():
_LOGGER.info("Device: {}: {}".format(mac, dev))
devices_sensors = await ad.get_sensors()
for mac, sensors in devices_sensors.items():
for sensor in sensors:
_LOGGER.info("Sensor: {}: {}".format(mac, sensor))
sensordata = await ad.get_sensor_data()
for mac, data in sensordata.items():
for name, val in data.items():
_LOGGER.info("Sensor data: {}: {}: {}".format(mac, name, val))
if __name__ == "__main__":
asyncio.run(main())
import time
import requests
# The period between two measurements in seconds (Default: 300)
SamplePeriod = 300
MAC = 'd8:71:4d:ca:de:dc'
# The hostname or IP address of the MQTT broker Hubitat hub to connect
makerAPIHostname = "192.168.1.38"
makerAPIAppID = "2416"
makerAPIToken = "8ca5e2ac-7d0b-4c24-a89b-f6022844e2ae"
makerAPIDeviceID = "AirThings Wave Plus"
from airthings import AirthingsWaveDetect
scan_interval = 120
airthingsdetect = AirthingsWaveDetect(scan_interval, MAC)
V_MAX = 3.0
V_MIN = 2.0
#---- Initialize ----#
URL = "http://{}/apps/api/{}/devices/{}/{}?access_token={}".format(makerAPIHostname, makerAPIAppID, makerAPIDeviceID, '{}/{}', makerAPIToken)
devices_sensors = airthingsdetect.get_sensors()
while True:
try:
data = airthingsdetect.get_sensor_data()[MAC]
except:
print( 'Read Error' )
pass
else:
sensorData = "{},{},{},{},{},{},{},{},{}".format(
data['temperature'],
data['humidity'],
data['rel_atm_pressure'],
data['co2'],
data['voc'],
round(data['radon_1day_avg']/37.,2),
round(data['radon_longterm_avg']/37.,2),
max(0, min(100, round( (data['battery']-V_MIN)/(V_MAX-V_MIN)*100))),
round(data['illuminance'])
)
#print( sensorData )
try:
request = URL.format('setValues', sensorData)
requests.get(request)
except:
pass
finally:
time.sleep(SamplePeriod)
Any idea ? Thanks.
Async needs an await but I don't know where. Thanks.

Related

python coroutine asyncio/ await / aiohttp

new in asyncio world.
going straight to the point...
I want to do/make a request(aiohttp) to a site.
if the wait for an answer pass than N seconds I want to stop the process of waiting.
Do the process again by setting a limit of attempts if needed.
async def search_skiping_add(name_search):
start_time = time()
async with aiohttp.ClientSession() as session:
url = f'https://somesitehere.com'
r = await session.get(url)
final_time = time()
result_time =round(final_time-start_time)
print(result_time)
Maybe, I know, have some way to do it synchronously, but it's an excuse to start using asyncio somehow too.
This should give you an idea of how to use async with aiohttp:
from aiohttp import ClientSession
from asyncio import gather, create_task, sleep, run
from traceback import format_exc
def returnPartionedList(inputlist: list, x: int = 100) -> list: # returns inputlist split into x parts, default is 100
return([inputlist[i:i + x] for i in range(0, len(inputlist), x)])
# You could change validate to an integer and thereby increasing the retry count as needed.
async def GetRessource(url: str, session: ClientSession, validate: bool = False) -> dict:
try:
async with session.get(url) as response:
if response.status == 200:
r: dict = await response.json() # Set equal to .text() to get results as a string
return(r)
else:
r: str = await response.text()
if not validate:
await sleep(3) # Sleep for x amount of seconds before retry
return(await GetRessource(url, session, True))
print(f"Error, got response code: {response.status} message: {r}")
except Exception:
print(f"General Exception:\n{format_exc()}")
return({})
async def GetUrls(urls: list) -> list:
resultsList: list = []
UrlPartitions: list = returnPartionedList(urls, 20) # Rate limit to 20 requests per loop
async with ClientSession(timeout=15) as session: # Timeout is equal to the time to wait in seconds before terminating, default is 300 seconds or 5 minutes.
for partition in UrlPartitions:
partitionTasks: list = [create_task(GetRessource(url, session)) for url in partition]
resultsList.append(await gather(*partitionTasks, return_exceptions=False))
return(resultsList) # Or you can do more processing here before returning
async def main():
urls: list = ["...", "...", "..."] # list of urls to get from
results: list = await GetUrls(urls)
print(results)
if __name__ == "__main__":
run(main())

I am trying to make a rank card using PIL and discord.py UPDATED

i have a leveling system, using discord.py, i am trying to make a rank card, like mee6 and arcane. i wanna get the image to display the users rank and xp
heres the command that works, but i want to make it into a image.
#bot.command(aliases = ['rank','lvl'])
async def level(ctx,member: discord.Member = None):
if not member:
user = ctx.message.author
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP " ,color = discord.Color.green())
embed.set_author(name = ctx.author, icon_url = ctx.author.avatar_url)
await ctx.send(embed = embed)
else:
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(member.id)]['level']
exp = users[str(ctx.guild.id)][str(member.id)]['experience']
embed = discord.Embed(title = 'Level {}'.format(lvl), description = f"{exp} XP" ,color = discord.Color.green())
embed.set_author(name = member, icon_url = member.avatar_url)
await ctx.send(embed = embed)
and heres my crappy atempt.
#bot.command()
async def text(ctx):
text = [f"level {lvl}, exp {exp}"]
user = ctx.message.author
img = Image.open("rank.jpg")
with open('level.json','r') as f:
users = json.load(f)
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
text = ['Level {}'.format(lvl)]
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("font.ttf", 150)
draw.text((480,445), text, (0, 0, 0,), font=font)
img.save("rankcard.jpg")
await ctx.send(file = discord.File("rankcard.jpg"))
and heres the console error, i doubt theres only one error with my code
Ignoring exception in command text:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\Jack\Desktop\just some code\bot.py", line 33, in text
text = [f"level {lvl}, exp {exp}"]
UnboundLocalError: local variable 'lvl' referenced before assignment
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: UnboundLocalError: local variable 'lvl' referenced before assignment
if you could fix up the code for me. i would be ever so greatful.
-thanks
UPDATE: i have now sorted those issues out but still trying to figure this out, my code:
#bot.command()
async def test(ctx,member: discord.Member = None):
global lvl, exp
if not member:
user = ctx.message.author
with open('level.json','r') as f:
users = json.load(f)
img = Image.open("rank.jpg")
lvl = users[str(ctx.guild.id)][str(user.id)]['level']
exp = users[str(ctx.guild.id)][str(user.id)]['experience']
text = [f"level {lvl}, exp {exp}"]
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("font.ttf", 150)
draw.text((480,445), text, (0, 0, 0,), font=font)
img.save("rankcard.jpg")
await ctx.send(file = discord.File("rankcard.jpg"))
and my error:
Traceback (most recent call last):
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Jack\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: expected string
You have to firstly define lvl and exp in the text function or global it as this is not found.
#bot.command()
async def text(ctx):
lvl = ...
exp = ...
text = [f"level {lvl}, exp {exp}"]
user = ctx.message.author
OR
#bot.command(aliases = ['rank','lvl'])
async def level(ctx,member: discord.Member = None):
global lvl, exp
if not member:
user = ctx.message.author
with open('level.json','r') as f:

Can't exit asynchronous process

I have a problem with the exiting from the asynchronous process which is handled by asyncio. This is the ftp server + client project and I want to kill the client process after 'exit' command.
The most important part of this code is here:
class FtpCommandsReceiver:
def __init__(self, loop, sock):
self.loop = loop
self.sock = sock
self.loop.create_task(self.recieve_data())
self.commands_to_handle = {
'exit': self.exit_handler
}
async def recieve_data(self):
while True:
self.data_to_send = input('ftp> ')
if self.data_to_send == '':
continue
await self.loop.sock_sendall(self.sock, self.data_to_send.encode())
try:
await self.commands_to_handle.get(self.data_to_send)()
except TypeError:
pass
self.received_data = await self.loop.sock_recv(self.sock, 10000)
print(self.received_data.decode())
if not self.received_data:
break
print('Connection closed by the server')
self.sock.close()
async def exit_handler(self):
self.loop.stop()
self.loop.close()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
FTP_connection = FtpConnection(loop)
task = loop.create_task(FTP_connection.connect())
try:
loop.run_forever()
finally:
loop.close()
When it calls exit_handler method, the exception raises:
Task exception was never retrieved
future: exception=RuntimeError('Cannot close a running event loop',)>
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "FTPclient.py", line 54, in recieve_data
await self.commands_to_handle.get(self.data_to_send)()
File "FTPclient.py", line 66, in exit_handler
self.loop.close()
File "/usr/lib/python3.5/asyncio/unix_events.py", line 56, in close
super().close()
File "/usr/lib/python3.5/asyncio/selector_events.py", line 94, in close
raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
I will be grateful for your help and thank you in advance!

WinError 10038 an operaton was attempted on something that is not a socket

I'm trying to make chatting server in Python and I can't solve it. I'm running my code in CMD by using command python client.py localhost 9009.
this is the code that I am using:
#chat_client.py
import sys
import socket
import select
def chat_client():
if(len(sys.argv) < 3):
print("Usage: python chat_client.py hostname port")
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
# connect to remote host
try:
s.connect((host, port))
except:
print("Unable to connect")
sys.exit()
print("Connected to remote host. You can start sending messages")
sys.stdout.write("[Me] "); sys.stdout.flush()
while 1:
socket_list = [sys.stdin, s]
# Get the list sockets which are readable
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
for sock in read_sockets:
if sock == s:
# incoming message from remote server, s
data = sock.recv(4096)
if not data:
print("\nDisconnected from chat server")
sys.exit()
else:
#print data
sys.stdout.write(data)
sys.stdout.write("[Me] "); sys.stdout.flush()
else:
# user entered a message
msg = sys.stdin.readline()
s.send(msg)
sys.stdout.write("[Me] "); sys.stdout.flush()
if __name__ == "__main__":
sys.exit(chat_client())
And this is the error that I'm getting:
I don't have a clue how to fix it. Help would be appreciated! :)
[Me] Traceback (most recent call last):
File "client.py", line 54, in <module>
sys.exit(chat_client())
File "client.py", line 32, in chat_client
read_sockets, write_sockets, error_sockets = select.select(socket_list , [],
[])

Python 3 Tkinter multiple functions running at once

I have a chat window for the client portion of a chat application that uses Tkinter for the GUI:
import socket
import select
import time
from threading import Thread
from multiprocessing import Process
import sys
from tkinter import *
HOST = "localhost"
PORT = 5678
client_socket = socket.socket()
client_socket.settimeout(2)
try:
client_socket.connect((HOST, PORT))
except:
print("Connection failed.")
sys.exit()
print("Connected to [" + str(HOST) + "," + str(PORT) + "] successfully")
class ChatWindow:
def __init__(self):
form = Tk()
form.minsize(200, 200)
form.resizable(0, 0)
form.title("Chat")
box = Entry(form)
form.bind("<Return>", lambda x: self.sendmessage(self.textbox.get()))
area = Text(form, width=20, height=10)
area.config(state=DISABLED)
area.grid(row=0, column=1, padx=5, pady=5, sticky=W)
box.grid(row=1, column=1, padx=5, pady=5, sticky=W)
self.textbox = box
self.textarea = area
p1 = Process(target=updating)
p1.start()
p2 = Process(target=tryrecvmessage)
p2.start()
def addchat(self, msg, clear=False):
self.textarea.config(state=NORMAL)
self.textarea.insert(END, msg + "\n")
if clear:
# Option to clear text in box on adding
self.textbox.delete(0, END)
self.textarea.see(END)
self.textarea.config(state=DISABLED)
def sendmessage(self, msg):
data = str.encode(msg)
client_socket.send(data)
self.addchat("<You> " + msg, True)
def updating(self):
while True:
form.update()
form.update_idletasks()
time.sleep(0.01)
def tryrecvmessage(self):
while True:
read_sockets, write_sockets, error_sockets = select.select([client_socket], [], [])
for sock in read_sockets:
data = sock.recv(4096)
if data:
self.addchat(data)
else:
self.addchat("Disconnected...")
sys.exit()
if __name__ == "__main__":
window = ChatWindow()
I want the updating() function and the tryrecvmessage() function to run simultaneously, so that the GUI continues to update while the client still receives messages from the server. I've tried using the threading module as well, but I need to have the threads created below where the other functions are defined, but the other functions need to be defined below __init__(). What do I do?
You can attach the functions to the Tk event loop using the after method, as I explained in this question. Essentially the syntax for after goes like this:
after(ms, command = [function object])
What it does is attach the function object passed in as the command argument to the Tk event loop, repeating it each time ms milliseconds has passed.
One caveat here: you would want to remove the while True from the functions as after would be constantly repeating them anyway.

Resources