understanding Python Nextion Display - Page Change - python-3.x

tl:dr
Looking for a way to change the active page in python3 using the Nextion library,
I have tried (x = 1, x = 'page1', x = 'page 1') and a many other iterations.
client = Nextion('/dev/ttyS0', 9600, event_handler)
await client.connect()
await client.set('page', x)
Hi everyone, I am making a Nextion display to attach to the outside of a raspberry pi to display some operational values such as if a serial port is connected, gps location data, cpu operating temp etc.
The logic for collection and display of the data is all sorted but I am having issues with the basics of the Nextion library and how to do what seems like a simple thing, change the active page.

Ok so I finally worked it out,
It looks like the example I used had the await client.set(x,y) for the text fields but nothing for the page, it turns out after reading the library file for 100th time I noticed a function called write_command
I tried this
client.write_command(next_page)
And it worked

Related

Want to make Node Red on Raspberry Pi detected Data from Arduino and React to it but unsure how to do so?

I recently made a sensor that can correctly display the distances on the Serial Monitor on the Arduino, it would continuously display the distance as I would move my hand up/down the sensor. Thing is though, I intended on connecting this to a Pi (mine being Pi 3B+), use Node Red and basically have it detect that whenever the distance was "20cm" for example, then it would go straight to a YouTube video and play it. I tried researching all over the net to see if such had been done before, but to no avail as I found content much different than what I tried to pull off with Node Red and my Arduino.
I did try on my end to set up a function on Node Red to my Arduino, using a conditional statement to detect something and print something else out.
Overview of what I tried to do on Node Red
As you can see, there was not much to add as I was initially trying to test the conditional statement I made, making it output something on the debug screen using the code below:
Contents of the function created
var newMsg = {payload:msg.payload.toString()}:
if (newMsg == 'Distance: 20cm') {
newMsg = 'Distance is 20, nice'
return newMsg;
}
return newMsg;
Even with the little test I created to return a message to the debug did not work, so I'm not sure what I'm missing here.
First, you should not be creating new message objects as a rule, this breaks flows that use things like http-in/http-response nodes that require the original message to pass from start to end.
Second, you can't compare an Object to a String and get anything meaningful. The function node probably should looks something like the following:
if (msg.payload === "Distance: 20") {
msg.payload = "Distance is 20cm, nice"
return msg;
}
Third, the input message appears to be terminated with a new line character so the test should probably be:
if (msg.payload === "Distance: 20\n") {

Communication with Python and Supercollider through OSC

I'm trying to connect Python with Supercollider through OSC, but it's not working.
I'm using Python3 and the library osc4py3.
The original idea was to send a text word by word, but upon trying I realized the connection was not working.
Here's the SC code:
(
OSCdef.new(\texto,{
|msg, time, addr, port|
[msg, time, addr,port].postIn;
},
'/texto/supercollider',
n
)
)
OSCFunc.trace(true);
o = OSCFunc(\texto);
And here's the Python code:
osc_startup()
osc_udp_client("127.0.0.1", 57120, "supercollider")
## here goes a function called leerpalabras to separate words in rows.
with open("partitura.txt", "r") as f:
for palabra in leerpalabras(f):
msg = oscbuildparse.OSCMessage("/texto/supercollider", ",s", palabra)
osc_send(msg, "supercollider")
sleep(2)
osc_terminate()
I've also tried with this, to see if maybe there was something wrong with my for loop (with the startup, and terminate of course):
msg = oscbuildparse.OSCMessage("/texto/supercollider", ",s", "holis")
osc_send(msg, "supercollider")
I run the trace method on SC, nothing appears on the post window when I run the Python script on terminal, but no error appears on neither one of them, so I'm a bit lost on what I can test to make sure is getting somewhere.
It doesn't print on the SC post window, it just says OSCdef(texto, /texto/supercollider, nil, nil, nil).
When I run the SuperCollider piece of your example, and then run:
n = NetAddr("127.0.0.1", 57120);
n.sendMsg('/texto/supercollider', 1, 2, 3);
... I see the message printed immediately (note that you used postIn instead of postln, if you don't fix that you'll get an error instead of a printed message).
Like you, I don't see anything when I send via the Python library - my suspicion is that there's something wrong on the Python side? There's a hint in this response that you have to call osc_process() after sends, but that still doesn't work for me
You can try three things:
Run OSCFunc.trace in SuperCollider and watch for messages (this will print ALL incoming OSC messages), to see if your OSCdef is somehow not receiving messages.
Try a network analyzer like Packet Peeper (http://packetpeeper.org/) to watch network traffic on your local loopback network lo0. When I do this, I can clearly see messages sent by SuperCollider, but I don't see any of the messages I send from Python, even when I send in a loop and call osc_process().
If you can't find any sign of Python sending OSC packets, try a different Python library - there are many others available.
(I'm osc4py3 author)
osc4py3 store messages to send within internal lists and returns immediately. These lists are processed during osc_process() calls or directly by background threads (upon selected theading model).
So, if you have selected as_eventloop threading model, you need to call osc_process() some times, like:
…
with open("partitura.txt", "r") as f:
for palabra in leerpalabras(f):
msg = oscbuildparse.OSCMessage("/texto/supercollider", ",s", palabra)
osc_send(msg, "supercollider")
for missme in range(4):
osc_process()
sleep(0.5)
…
See doc: https://osc4py3.readthedocs.io/en/latest/userdoc.html#threading-model

Selenium don't read all the content of a webpage

I'm newbie with selenium. I have defined a batch process where I process several pages. These pages are all equals but with different data. Therefore, I process all these pages with the same code. When I start the process this works fine, but, from time to time, I always get the same error in the same point. I have found that when I try to get the data from the web page, there are two tables that I can not get their code when the process doesn't work fine. And I don't understand anything because if I restart the process in the same page that has failed previously then it works fine!!! So, it seems that selenium not always load the content of the web page correctly.
I use python 3 and selenium with these code:
caps = DesiredCapabilities().CHROME
caps["pageLoadStrategy"] = "normal"
#b = WebDriver(executable_path="./chromedriver")
b = webdriver.Chrome(desired_capabilities=caps, executable_path="./chromedriver")
b.set_window_size(300, 300)
b.get(url)
html = b.page_source
self.setSoup(bs4.BeautifulSoup(html,'html.parser'))
b.close()
How can I avoid to get always this error which is produced from time to time?
Edit I:
I have checked that when the process works fine this sentence returns me two tables:
tables = self.get_soup().findAll("table", class_="competitor-table comparative responsive")
But, when the process works wrong, this code returns me 0 tables. How I said before, If I process again the web page that previously has gave me the error, then works fine, therefore, it returns me two tables instead of zero.
For this reason, I supose that selenium is not returns me always the code of the page, because for the same page when it works wrong returns me zero tables and when it works fine returns me two tables.
Edit II:
For example, right now I've got an error in this page:
http://www.fiba.basketball/euroleaguewomen/18-19/game/1912/Olympiacos-Perfumerias-Avenida#|tab=boxscore
The tables that I try to retrieve and I don't get them are these:
How you can see, there is two tables with this CSS class. I don't post the content of the tables because are so big.
This is the code where I try to get the content of the tables:
def set_boxscore(self):
tables = self.get_soup().findAll("table", class_="competitor-table comparative responsive")
local = False
print("Total tablas: {}".format(len(tables)))
for t in tables:
local = not local
if local:
self.home_team.set_stats(t.tfoot.find("tr", class_="team-totals"))
else:
self.away_team.set_stats(t.tfoot.find("tr", class_="team-totals"))
rows = t.tbody.findAll("tr")
for row in rows:
time = row.find("td", class_="min").string
if time.find(MESSAGES.MESSAGE_PLAYER_NOT_PLAY) == -1:
if local:
player = PlayerEuropa(row)
self.home_players.append(player)
else:
player = PlayerEuropa(row)
self.away_players.append(player)
In this code I write the total tables that I can find in them and how you can see, right now, I've got zero tables:
And, now, If I restart the process, then, it will work correctly for me.
Edit III:
One example more, about the process that I have defined. These url's has been processed correctly.
http://www.fiba.basketball/eurocupwomen/18-19/game/2510/VBW-CEKK-Ceglèd-Rutronik-Stars-Keltern#|tab=boxscore
http://www.fiba.basketball/eurocupwomen/18-19/game/2510/Elfic-Fribourg-Tarbes-GB#|tab=boxscore
http://www.fiba.basketball/eurocupwomen/18-19/game/2510/Basket-Landes-BBC-Sint-Katelijne-Waver#|tab=boxscore
But when I have tried to process this other url, then, I've got the error explained previously:
http://www.fiba.basketball/eurocupwomen/18-19/game/0111/Gorzow-Sparta-k-M-R--Vidnoje#|tab=boxscore
To render the web page I use selenium and I always do it at the beginning of the process. I get the content of the web page with this code:
def __init__(self, url):
"""Constructor"""
caps = DesiredCapabilities().CHROME
caps["pageLoadStrategy"] = "normal"
#b = WebDriver(executable_path="./chromedriver")
b = webdriver.Chrome(desired_capabilities=caps, executable_path="./chromedriver")
b.set_window_size(300, 300)
b.get(url)
html = b.page_source
self.setSoup(bs4.BeautifulSoup(html,'html.parser'))
b.close()
After this code is when I start to retrieve the information of the web page. For some reason, sometimes, the web page is not rendered completely because when I try to get some information, this is not found it and get the error explained previously.

nodejs vs. ruby / understanding requests processing order

I have a simple utility that i use to size image on the fly via url params.
Having some troubles with the ruby image libraries (cmyk to rvb is, how to say… "unavailable"), i gave it a shot via nodejs, which solved the issue.
Basically, if the image does not exists, node or ruby transforms it. Otherwise when the image has already been requested/transformed, the ruby or node processes aren't touched, the image is returned statically
The ruby works perfectly, a bit slow if lot of transforms are requested at once, but very stable, it always go through whatever the amount (i see the images arriving one the page one after another)
With node, it works also perfectly, but when a large amount of images are requested, for a single page load, the first images is transformed, then all the others requests returns the very same image (the last transformed one). If I refresh the page, the first images (already transformed) is returned right away, the second one is returned correctly transformed, but then all the other images returned are the same as the one just newly transformed. and it goes on the same for every refresh. not optimal , basically the resquests are "merged" at some point and all return the same image. for reason i don't understand
(When using 'large amount', i mean more than 1)
The ruby version :
get "/:commands/*" do |commands,remote_path|
path = "./public/#{commands}/#{remote_path}"
root_domain = request.host.split(/\./).last(2).join(".")
url = "https://storage.googleapis.com/thebucket/store/#{remote_path}"
img = Dragonfly.app.fetch_url(url)
resized_img = img.thumb(commands).to_response(env)
return resized_img
end
The node js version :
app.get('/:transform/:id', function(req,res,next){
parser.parse(req.params,function(resized_img){
// the transform are done via lovell/sharp
// parser.parse parse the params, write the file,
// return the file path
// then :
fs.readFileSync(resized_img, function(error,data){
res.write(data)
res.end()
})
})
})
Feels like I'm missing here a crucial point in node. I expected the same behaviour with node and ruby, but obviously the same pattern transposed in the node area just does not work as expected. Node is not waiting for a request to process, rather processes those somehow in an order that is not clear to me
I also understand that i'm not putting the right words to describe the issue, hoping that it might speak to some experienced users, let them provide clarifiactions to get a better understanding of what happens behind the node scenes

How to use "standardized track listings" in Spotify apps

The Spotify UI guidelines for Spotify apps (at https://developer.spotify.com/technologies/apps/guidelines/design/) say "When listing tracks in your app, use our standardized track listings". I cannot find any examples in the documentation on how to use these "standardized track listings". By using the Inspector I have found classes in list.css (such as sp-list and sp-item) which it looks like I need to use but have not been able to work out quite how to use these to recreate the look of the Spotify track listings.
The Billboard Top Charts app appears to use track listings like I need, but I can't find ay way to see how they are doing this as the Inspector only works for your own apps as far as I can tell.
Does anybody have any advice or examples?
Some examples
sp = getSpotifyApi(1);
var m = sp.require("sp://import/scripts/api/models");
var v = sp.require("sp://import/scripts/api/views");
// Example 1
var tpl = new m.Playlist();
var tempList = new v.List(tpl);
tpl.add(m.Track.fromURI("spotify:track:4z4t4zEn4ElVPGmDWCzRQf"));
tpl.add(m.Track.fromURI("http://open.spotify.com/track/7E8JGVhbwWgAQ1DtfatQEl"));
tpl.add(m.Track.fromURI("spotify:track:40YBc3mR3yyqyYvtesQOMj"));
tpl.add(m.Track.fromURI("spotify:local:Rolling+Stones:A+Bigger+Bang:Rain+Fall+Down:293"));
document.body.appendChild(tempList.node);
// Example 2
var pl = m.Playlist.fromURI("spotify:user:username:playlist:424km2k4m24");
var list = new v.List(pl);
document.body.appendChild(list.node);
// Example 3
var album = m.Album.fromURI("spotify:album:1vWnB0hYmluskQuzxwo25a");
var albumList = new v.List(album);
albumList.node.classList.add("album");
document.body.appendChild(albumList.node);
Thanks for asking, I had exactly the same question too!
I too get the issue where i get no actual content added - just the wrapper div. Not including api.css makes it work, but the list is obviously not styled. Including css/list.css directly breaks it too. Creating my own copy and selectively commenting out list.css I found the offending rule to be:
.sp-list > div {
if you change this to be
.sp-list {
then it renders fine. No idea what is going on. Obviously this solution is not idea because I've just duplicated what's meant to be a common resource...

Resources