 All right, good afternoon. Happy Friday Good day to everyone We have made it to the end of another week, which means that it is now time for the deep dive This is the deep dive, which is a Weekly live stream is my sorry. I'm a little distracted by my preview. I'm actually behind that guy That should be the other way around. Let me fix that real fast. Sorry. I know we're uh all already Jumping off into rabbit holes What is this guy's here, so let's move that up That is what we want there. We want to be on top of that guy. Okay. Sorry for that Has gone Paul Kuller as I Was about to get to How's it going also over in the YouTube there? Thanks for tuning in folks. Dave Odessa The autograph and Strathe. Pleasure to have you folks in the chat with us here So as I was about to say before I got distracted like a goldfish, my name is Tim This is the deep dive program. This is a weekly live stream program where we are working on things related to circuit Python From week to week it varies what's going on in You know overall in the world of circuit Python and certainly what I'm working on specifically varies from time to time If you do go back and watch some of the older episodes of this live stream It was started by Scott the lead developer of circuit Python. I eventually took this over once Scott had a child and did not does not still have as much time on his hands throughout the week and Can't really commit to the streaming schedule And so I've been taking over since then if you do watch some of the older ones Scott's working in the core and off a lot being the lead developer. That's where he spends most of his time. I am I would say like You know to the point where I may be dipping my feet in the core. We're a little past dipping our toes in We're probably up to dipping our feet in now Maybe up to the knee or so even though that's kind of a weird analogy So sometimes we do spend some time in the core work on different things Sometimes we work on libraries. Sometimes we work on infrastructure. Sometimes we work on projects It just depends but the thing that ties it all together is we always work on something related to circuit Python You are brand new and don't know what circuit Python is you can learn more at the website here circuit Python org This is basically an implementation of Python that runs on tiny computers called microcontrollers Here's a bunch of pictures of those microcontrollers Essentially each one of these devices has a chip on board which is basically an entire computer inside that chip Now it is a relatively small computer. This is not like a laptop or a desktop computer You know, it's not typically going to be like gigahertz of processing power or anything crazy like that It's a relatively small computer But perfectly capable of interacting with various hardware peripherals as well as doing relatively simple tasks with the network Drawing on displays things like this. So these tiny computers can be programmed in various ways And circuit Python is one of the ways to program those tiny computers With circuit Python the way this works is these little computers all will have a USB plug you plug that Accord into there you plug that device into your computer It will show up like a thumb drive and then on that thumb drive you'll be able to edit a Python code file Just right on there in whatever text editor you want And then when you save it the circuit Python system will automatically notice that your code has Been saved and changed and it will reset the device and run the latest version so you can write this Python code to interact with all sorts of hardware peripherals some devices have lots of hardware things built-in like this device has a touchscreen built-in as well as a speaker And a I think light sensor may be on the side over there This device has got some cherry MX keys built-in as well as a tiny screen and a knob Some of these devices are more general purpose where they don't have a lot of stuff built-in Like the picos up here for instance these don't have too many things built-in But they have loads of iopins along the side which you can then collect your own Connect rather I should say connect your own hardware peripherals onto those iopins and then interact with it through your Python code Let me Once that for now Syncoded Python nice. Yeah, I'd had not I had not thought of that before but yeah We do have a nice syncoded Python going here. Will this be recorded it it will be recorded. Yeah, it's recorded and Stored inside of YouTube so you can always watch the VOD In the future on YouTube under the Adafruit YouTube account I believe it should be the same link as far as I'm aware I think the link stays the same so if you are watching us on YouTube Which I assume you are as you did chat in the YouTube chat I believe you can just keep the URL of the page you're in and then just watch that whenever you want Sorry, I've kind of allowed a coffee cup today. I guess this has a logo on the front of it, doesn't it? So That is the intro I got. Oh That's interesting. Let me also say before we get the show all the way on the road Circuit Python is an open-source project. It is free to use. It's free to port to your own devices It's free to use on your own devices It would even be free if you wanted to use it in a product, although it's not warrantied for that use It's made primarily for teaching folks to develop so you could certainly take a Circuit Python device and product ties it build it into some other product for a company But you would kind of be it's up to you to do a lot of the work to kind of lock it down if you want to use it in that Capacity so all of this stuff that you can do with circuit Python You don't have to pay for any of it and the reason why that can happen is circuit Python is open-sourced and it is Fully funded by this company Adafruit They are paying the folks who work on the circuit Python project There's a team of folks who are paid to work on the project full-time like Scott who I mentioned before as well as a Few others there are some folks like me who are paid to work on the project part-time And Adafruit is the entity that is paying us to do that So huge thank you to them, of course And thank you to anybody who wants to purchase hardware from them because of course once you are purchasing hardware from them You're helping them keep the lights on run the Adafruit factory Which is of course giving them the money to be able to pay the team who's working on circuit Python So that is a way that you can help out even if you're not interested in getting involved in Development or testing or anything on a technical level if you just head over to adafruit.com and purchase hardware from there You are helping out the project. So thank you if you do Has gone Isaac Super-duper fast interesting thing that came today, which I am fascinated by it is completely unrelated to the entire rest of The stream and everything I've discussed so far, but random show-and-tell Before I jump into it. I received this book today. This is a an interesting thing, which I only became aware of Relatively recently within the last week or so. This is actually a reprint of an old book that they used Back in the days of telegraphs inside this book. It's basically just pages and pages Of all these numbers. It's pretty much just a dictionary where every word has a corresponding number And these numbers and words were used back when they sent telegraph data back and forth They would convert the real message into these numbers Apply some operation to it which was agreed upon on both sides And then convert those Resulting numbers from the operation back to the words in the dictionary and at that point They could send the data across the telegraph and it's not in plain text anybody who would see that information In the telegraph would not actually know what the real message was unless they both had a copy of this book or the data inside of it and Knew the operations that you did on the numbers On the on the front side on the side where the message came in In order to de-scramble it you would need to take those same operations in reverse So if you added a hundred to the numbers you need to subtract a hundred from the numbers on the opposite end This is a super interesting thing to me I like I said, I only learned of this very very recently And I was fascinated by this concept and so my my hug report related Related to this goes out to my wife this week Who is the one that helped me track down how to find this and be able to actually purchase it today? Which is awesome. So that's cool It's completely unrelated like I said But I wanted to just show it because I'm excited about it and I think it's neat The spelling of secrecy is old-timing. Yeah, so the book itself is from the early Actually, I think the late 1800s is when the actual like first edition first edition came out. This is a reprint of the third edition 1888 is that a date though on the first of eight so the very sorry about that on the first essentially introduction the first bit of the introduction talks about February 1st 1870 I Don't know they're talking about it as if it is Who will work they're talking about it as though it's in the future future tends to me my Reading comprehension is not the best and I did only take a quick scan but Potentially even pre 1870 the first edition of that or at least introduction Is the book available it is if you if you search online for the title Which I'll show here and I'll drop it in the chat The title is telegraphic code to ensure secrecy and the transmission of telegrams tele Graphic code to ensure secrecy Which yeah, that is a an odd I have not noticed that before that isn't an interesting spelling of secrecy, isn't it? They have some letters that are bigger, but all the letters are capital, which I find interesting if you have trouble You provide the title later. I missed the cover. Yeah If you have trouble finding that I mean I'll be on for a couple hours still if you do happen to look around While I'm still here if you have trouble finding that I can give you like the ISP and or something as well If need me and if you still have trouble you can ping me on discord. I'm happy to share what I can Yeah So maybe one of these days will make something related to that I'm interested in the concept of a book with just a bunch of numbers in it that are used for codes like this Small caps. Okay, let's get to know Maybe one day we'll we'll somehow scan that into Python or find a version of it that is digitized And then make some encoding and decoding Software for it. Maybe we'll live without one of these days, but not today today I am looking at HTTP servers In particular, I am looking at the new version of HTTP server Which I owe another big hug report to Michael poke you so who's been working on this? This is a PR over an HTTP server that adds a bunch of new features and functionality and just improvements Generally speaking to the HTTP server library today what I am interested in working on is doing some more testing of this but also I Have kind of a specific project in mind I will say the project that I have in mind while it is a specific project. I don't really have a reason for building it So, you know, I don't know. I don't know what I will do with it I don't know exactly where I'm going with it But I do know what I want it to do which is kind of the first step to building something So I'm gonna get started basically what I want is to run Web server on the feather. This happens to be a feather ESP 32 s2 tft And then I would like to use a feather tripler Which is what I have here or even truthfully I would like to bump up to a feather quadrupler And I would like to plug in two in this case or even a third extra feather wing And then I would like to run the web server on this feather and have the web server host a page that allows you to control The rest of these other feather wings. So the feather wings I have on there right now 14 by 4 segment display. That's I think HTK 1633 or something like that And then a neopixel feather wing which has 8 by 4 rows of neopixels So I'd like to add a third one to the mix and I'd like to be able to control all of them from an HTTP server. I Don't have the quadrupler yet. So we are just working with the tripler here We're working with these things, but I figure that's good enough to get us started So we're kind of going two birds one scone here to test this out as well as build this specific thing Which I happen to want to build even though I don't necessarily have a real world use case for it as Part of that process I will need to make a PR. I mean, I wouldn't need to make a PR but we're gonna be making a PR to the HTK I don't know the right number HT 16k The the library that drives the 14 segments. I Have some changes for that library in order to support the non-blocking Marquee scrolling of text and I will show you what I mean by that once we get on our device and go back to What did I call this probably I think non-blocking. Yeah, there it is not blocking Marquee, so we're gonna grab that we're gonna go to codepie oops current codepie is just a Neopixel hello world basically let's get to running Okay, oh we should I might need to turn the light off does that get any better if I turn the light off. Yeah, that's much better So we have text scrolling across here We also have LED animation running on the neopixels down here I had to modify the HTK 16 whatever library a little bit in order to make that possible See The The library as written today before these changes has a function called Marquee Right here this function Marquee pretty much does the text scrolling thing like this right pretty much does what we want The problem with it though is that it's blocking it doesn't return you have kind of two modes of operation You can tell it either loop true or loop false When you tell it loop true, it just runs forever and ever inside of here It's just a while true loop it never returns unless you control C or something to break out of it If you pass loop false, then it will play through once it will scroll the text all the way through once And then it will return when it's done Which is you know less blocking but still blocking like while it's running you cannot be doing anything else So we couldn't be taking steps in the animation We couldn't be updating the display We couldn't be serving web pages from the HTTP server or reacting to HTTP requests that are coming into the server We couldn't be doing any of those things while marquee is running So pretty fundamentally for this to work how I want we need a way to scroll the text without blocking We want to be able to Kind of refactor this to be where you call it once and it takes one step if it needs to And then you just keep calling it over and over and over again inside the main loop And it will just keep track of how long it's been since the last step and update itself accordingly Essentially, we want an interface an api That's pretty much the same as what we have for the neopixels with their animation For those familiar or not familiar I should say with neopixel animation The led animation library specifically is what i'm talking about in this case. You initialize your animations Optionally, you can put them into a sequence or a group in this case I do have them into a sequence When you want to actually animate What you do is inside your main loop you just call animations dot animate You just call that function on whichever animation you want to run or in this case the sequence of all of them This gets called over and over and over really really fast inside the main loop And each time it gets called it checks whether it's been a long enough period of time since the last step And then it turns on and off the leds accordingly to the current animation step We need a function that's like that for the marquee, which is exactly what i've made non-blocking marquee You give it the text you give it the delay it basically has Roughly the same api as the regular marquee Although I have not messed with loop yet. We should oh, I actually I have accepted loop, but we uh, that's interesting It's not actually being used yet um The goal is to make the api basically the same with the exception being that you are Expected to call it every iteration of the main loop or at least really quickly within the main root um that way you can Keep doing other stuff as well um I should say also how's it going? Uh, hello to near doc and to ship it over in the chat. Um, thank you for Dropping the knowledge of the way that that word is spelled and also the capitalization I mentioned before Those are both new facts to me and I'm happy to have learned them um So first thing we're gonna do is Clean this up and get the pr submitted for it. Uh, also, we're gonna probably want to do loop. I guess right so let's um Let's implement the functionality for loop first, uh, and Well, actually I kind of want to dive into the server piece of it. Yeah, I don't I'm not going to do loop just yet I'm going to dive more into the server and actually get going on that part of it We'll come back around at some point and clean up Yeah, the loop stuff One thing I do want to do though is I'm pretty sure the code in here is different now I'm also gonna probably have to go turn the fan on That I'm started up. It's actually getting kind of warm here. Um So I believe this version is yeah, this is newer actually So let me grab this and put it into the repo And yeah, I'm actually I'm gonna dive straight into the server I'm not gonna clean up and get ready for the pr yet But ultimately this code is gonna depend on this non-blocking marquee. So we're gonna have to get that submitted Um and into the library if I want this code to be usable by other people Which I do the goal here is kind of to make a medium to high level advanced Example of HTTP servers interacting with other hardware We do need the HTTP server library as well And we want the latest version of that from the pr which I don't have yet I don't believe so I'm gonna open that here Yeah, I am I'm gonna go turn the fan on real fast also P server we want to go up. We want to check out the latest one, which I'm actually Let's try it. I think I can just do this again. GHPR list GHPR check out Oh, yeah, the fan is much appreciated So nice, okay, okay. Yeah, there we go. We got the latest version Some reason I was thinking maybe that didn't work. Maybe I need to delete the branch But now it doesn't just you just grab it like that. So let's grab this We want to put that on our device It's not our device device is over here. I might need to delete something. I don't actually know I'm gonna delete the old one. I guess that's a good place to start Uh joined a bit late, but uh, thanks to 2x. I'm already up to date. Nice. Yeah, uh, youtube time Manipulation is really really nice. I do that sometimes as well either start late and speed up Or it's also really nice to be able to go down to half speed or A quarter speed if you're trying to like watch a replay or a slow-mo of something Um But yeah, I pretty regularly will do youtube at like 1.25 on stuff I can still understand the person then uh, I'm happy to watch at 125 and Just kind of consume it a bit quicker basically Although it depends on who you're watching some youtubers really speed themselves up already in the video And so you can't you start to get a little like squirrel Squirrel speech going on if uh, if you speed up too much sometimes. Okay, so there's our htp server So to start with let's go nice and easy basic. Let's just do uh, we want a web page Let's say with a text input, uh for the text that's going to be scrolling We want a drop down. Let's say To select the currently executing animation and then probably like I guess a submit button to submit it Um, you know, we could submit it automatically from javascript, right? Like whenever it changes we could submit it, but Then it's like submitting with every character or else we need some kind of logic to slow it down We don't necessarily want to hit the server super hard because it is running inside a microcontroller I think it's probably good to have the Requests be driven by user action like clicking a submit button because the user can only click so fast And most users will click much slower than they can obviously a lot of people are not going to just Spam your button as fast as they can so Um I am gonna well actually we do have static here. I guess I'll just should I use static or should I make a new folder? Let's make a new folder for this project. Uh, what do I want to call this thing? I don't really know HTTP controller Peripheral controller, let's call it. Um, HTTP Peripheral Controller, I might have misspelled that doesn't give me spell check in there. I'm not that good at spelling Peripheral Oh We'll fix it. I haven't really gotten anywhere yet Inside of here. I want index HTML Let's call this. Uh, let's just say Are there controller? I don't know. That's probably not the best word either could be peripheral controller. It's kind of wordy. Honestly, it's way too big for a Way too big for a title, but title also doesn't matter in the grand scheme of things. So I'm not gonna spend too much time trying to Exact best thing and put type. So we're going super basic first input with text I'll tell us weird. Okay. Is this it doesn't like to be an input. Why is that? It's a seeded label. Yeah, that's fair. I guess label Uh, let's go 14 by 4 seg text 14 by 4 segment text input. Let's give this an id The id is the uh marquee text or let's just call it the segments Text I kind of like to put input as well It's overly verbose because the thing is an input But this is nice because then in your javascript if you look it up, you also can see it's in it I find that I get wordy with variable names sometimes I prefer more wordy than less peripherally. I thank you Uh, we'll have also a drop down for the animations. So let's call this uh animation It's led animation because it that's the exact name of the library is led animation This one is going to be a select Um So templating is not a thing that's necessarily built in I don't think to the htp server library, but I think I want to actually start Is that true though? Because we don't have like four loops. Um No, let's go hard coded first Sometimes I got to tamper my uh Sometimes I got to tamper my Reprint city to try to be too generic too early Like I'm thinking ahead to like wouldn't it be nice if this could be a template and we could pass in an object that has All of the available animations and then that way inside the code It just says loop over the animations and spawn an option for each one And it would be nice, but I think first first step we should just hard code at first and then worry about I'm blitting and anything like that. So value, uh, we're just going to go with the ones that are already in the code, but obviously you could make Uh, you could make it be any any ones you want, right? If I want the I think I want the Technique maybe we want both ultimately Let's go all lowercase for the value and the value is ultimately going to map to a dictionary And the dictionary is going to hold these variables But we will do the capital ones on the front end so to speak and the the text the user sees we'll do it that way Why is this changed? Oh, because I did that comment, but It gets like functionally changed No templating yet, but you can expose an api and do it from JavaScript. That's a good idea Actually, we could have a json api and then our javascript could Hit the api and render The DOM elements as needed I do like that idea. That's probably what we'll aim for ultimately What would be super convenient? Lamo, I think we're almost done. I have something duplicated chases Oh gosh, wow, we're really all messed up here. Aren't we chase comet? Base chase Comet sparkle, that's like the most basic age, but I think that's really what we want. Um Do you want them to be not on the same row or whatever? Let's go I mean we could make a div for each one that probably would work. We could add a break tag that would also probably work Could make something display block that would also probably work This refresh itself that was interesting. I do want some space between them as well. So let's get started with uh With some basic css as well and we might as well put our css in another file. That's best practice Right, so let's go style CSS will be uh, this will be what do we want to do? So let's give these a name. Let's say uh input group. Maybe input group class input group input group Let's go a little bit of margin I don't remember which one's which I believe we got it wrong way around though not taking any effect because we put it in its own file and then we did not link it link rail style sheet href Oh, that you know, that should work 304 We did get this Okay, maybe we also had it right the first time on the way around of this And I want a little bit more actually Let's put a title and then we'll call that good For version 0.01 nice and wordy Very big Really won't fit on a phone screen eventually. We'll try to make that more succinct probably. Okay, so I'm gonna keep Actually, we have this already right. This is already a non-blocking scroll test I'm gonna cut this part out. This one it makes a heart on the pixels when it very first loads up Um If we've actually caught it on the camera or not This one's not an led animation though That heart that's there for the first little second or whatever is just all hard coded from these We're gonna take that out for now Uh, eventually you might also add a mode where the user can Paint the pixels one by one or whatever instead of just setting the animation may eventually get to there as well, but I'll start here. Let's not call this display Segment display Just because like If we all if we eventually want to show stuff on the screen, then we're probably gonna have another variable called display But uh, let's do it this way. We're gonna go I also need the server code I am gonna go with Basic one first Uh auto meaning the wi-fi connection auto Which is still the case for me. That's like if you have settings dot toml necessarily matter which order I guess we do this stuff in I really want to install this important. Is that Static is not static. It was HTTP peripheral controller HTTP riff Rol I always want to I think it my deal is I want to put more eyes in it Uh, we'll leave debug true eventually. We'll maybe turn that off Now it'll be good though true I won't work the first time we load it up. So um Oops This one does use serve forever. Let's actually do this one Where we want to go start server Whoops This is basically the non blocking. This is the analogy of the non blocking essentially so The server library also can have a serve forever Which basically works the same way as that blocking marquee that I showed at the very very beginning Um, but it also has a non blocking version Which is this one here, which is expecting to be called every, you know quickly every time in the main loop basically Um, so we start it and then we call pull or something. I think right Why is my alt tabs not wanting to go it seems like okay, so we're going to leave all this stuff the same But also add server dot pull which is going to handle the HTTP server for us So that should be I think enough to run and serve our index page um There's a lot of extra prints and so it's kind of tricky to uh Whatever 102 is the ip. Whoops I want to let me copy very easily And it's on port 80. So we don't need to specify the port You just see that there's our page Serving that we're good to go so We need the page to actually like do something at this point right now. We have a page. It's here. I can type stuff I can choose something But nothing happens It's not getting sent anywhere. It's not doing anything with it right now. It's front end only no functionality Uh, one more thing we do want like I said before though is the submit button I'm just going to go ahead and make an input group for that even though it's by itself I mean, I guess the other ones are by themselves too button Uh, I'm not going to do class submit. I don't or a type submit because I don't want it to Like behave like a form I I want to handle the ajax, I think Myself rather than Relying on html form. All right, I did save and it actually will refresh but I do We do have to wait for it to get back up and running there we go. Okay, so now we have a submit button as well. Perfect um I want to handle the request when we submit rather than using a form the way that I am most familiar doing that is jQuery which I'm going to add as a cdn Rather than hosting it on the microcontroller. We can actually just have jQuery on the internet. Obviously Well jQuery is on the internet hosted in various places. We're going to use one of those places instead of posting it ourselves inside of our tiny limited web server Limited mostly in file size. Honestly the biggest thing I'm trying to save here is not storing the copy of jQuery on the device because it's like I don't know a couple under k or something. I'm not sure how big it is certainly Not to be certain I should say um Make sure it's working. We're gonna go Turn off some of the prints That's just gonna like look up the button and print an object for it Basically nothing, but it should tell us if we got jQuery successfully imported Which it looks like we did so we got a 200 on it there go over here We now have this print out which is what it printed Firefox has conveniently turned it into this object thing that we can hover on and do all sorts of interesting stuff with which is helpful for debugging In our case that's working exactly how we want. Uh, you don't need jQuery. That's true. We don't we could do it without jQuery Let's use fetch. How about that? We'll use fetch Um fetch Post request That's true. We don't need jQuery necessarily. I am just most familiar with it I am trying to use fetch more though, so Thank you for mentioning it Uh It does force a sync which I could go without my javascript, but uh, I I still kind of want to use jQuery for the click listener. I also don't have to use it for that. We could use vanilla javascript Truth is I just find it convenient Data object is build the data object and then pass it to post and then let response Object equals that wait. No, that's not returning Result. Yeah. No, that doesn't return. It's not returning I mean it returns, but it returns a promise not a not the value I can make it a little bit by id and fetch or I'll use in your examples Yeah There's a good case to be made for it Once we get to creating the elements as well I find jQuery really convenient for that as well. Like if we did want to have the JSON API which will have the list of animations that we support and then dynamically Populating the drop down in the front end the stuff here instead of hard coding it Will involve creating those elements, which I also find a lot more convenient with jQuery But it's a preference thing. You could definitely go without Uh, we don't want to post it here. In fact, we could probably just use Oh, we don't want to do blank. I guess let's give it to um Say we will call this what um Submit data, I mean that's awfully generic, but I guess it works We will need another handler inside of here So this is after we initiate the server, but before we call start Document query selector Yeah, yeah, when I do skip when I do skip jQuery, I do lean on query selector a lot more than get element by id I will say that as well That is definitely true. Sorry if that's loud like a metal coffee cup and a metal straw We don't want to handle base. We want to handle what we just linked to which was Submit data We want to handle posting which means I think we need methods or something. Is that right? list Oh, did the alt tab thing again? Why is it doing that? This one's going to accept post only the other stuff in there. Do we need anything else a pen slash? Oh, right, right, right Uh, we could do it that way Yeah, thank you for adding that by the way. I saw your message about that. I have I don't think I posted anything else back on Um on the pr and github yet, but I did see your message a pen slash It's not gonna It's not gonna return It's not gonna return an html page. It's gonna return a json response We might want this still What is it? Uh, yeah, just like what is json? We send text I like to use this as kind of my Cross the board json api if the thing works then you send back success true The thing fails. It would be success false. There would be another key called error Which would have a string for human readable message to show the user We will need to get the data That was posted also How did we do that before pretty sure we did that before? That on this device or is it on the other device? URL parameters. That's not quite what I want though. I want the body Sure, we did this out the other day even recall the It's our response. No, it wouldn't be a response to be request There's raw Bites we could do I guess body there we go. That's what we want body is gonna be a Bites json Ah, okay, that's actually that's what we want right there json. That's actually nice and convenient because I am gonna send json Uh, so for now, let's just go print Um, well, let's get the object risk request object request obj equals request json print request object this, um Segments text print that for now So then here when we are gonna send our request we need to have our build data function pixel example does uh params This one does the body And in this case does not decode it as json necessarily although it happens to be Maybe valid json, I think technically you're not supposed to be a list on the outside, but lots of stuff accepts it anyway So that should put the value from the input into this object return the object The object should get put in here then should get passed into post json Which should Put it as the body to the poster quest Seems good say that Let's see if I can cut out some of the prints really it's inside of uh Side of segments. Let me take a short detailer into there and clean prints for now. Let's just So That's interesting our two libraries are right next to each other That should print weight less it had an error anyway unsupported type for hash and list That's supposed to be not this Does it need a name? Maybe expected string but got a list Has gone axle for hash list 18 inside of route Oh, we're not in route.py. We're in server. Excuse me. There we go. It's in a function called route methods It's a set. Maybe it's uh should not be a list but a tuple or It's a set else method Maybe we should not do a list for now No one says string there Have the example as like this my example code. I wrap the handlers in try body exception error show the error and trace back Methods you did call it methods. I wonder if that's the uh, or you did method actually Oh, uh, we did seem to have gotten it. I wasn't paying attention, but it seems like it's running. I didn't see if it printed the success of the starting the server What? What? Oh, right, right, right. Let's off so we get a little bit less prints again So I'll have that one I don't know what that's from. Oh, there it is. All right 102 port 80 loads successfully Mid sent a poster quest got a 200 response That is looking good so far. Our response was success true Look at our data Nice, so we did send the we sent the data. We got a successful response We read the data successfully inside there as well because we were able to print it So from there we could use That to change the text that is scrolling In order to do that we do need to have a variable for it Start on the ip actually before you set the text. Let's make it the ip which we can get from wi-fi radio pv4 address I have all this logic in here, which was changing the text. This was basically my attempt to test that When we changed the text it was actually working properly um In actuality we don't really need that logic though Because now our string will change when the user submits the page Text to scroll and in our handler we set text to scroll equal to Uh, the new value the problem is though. It's not a global variable or whatever So if we set it inside of here, it's not going to work actually. So let me make a Context object that is a dictionary that basically will serve the same purpose context Dictionary this will actually be text to scroll Because dictionaries are special and don't have the same problem with Not being able to set variables and set functions I will eventually add the animation to this as well, but for now we have just that Because it's a dictionary now we're able to change it inside of here We should make sure we actually have it I guess All right, when we get the post it should update the value in the dictionary And our scrolling should always be scrolling the value in the dictionaries So we should be able to change the text by submitting the page Seems to have died a while ago Okay, so we have the ip 192 16 a 1.102 That's pretty cool And then for the Thing here. Let's go. Hello deep divers It's not appear to have changed It says we posted it looks like we posted it there He printed it We got the right value Ah, right. That's not There we go. Well that reruns. I'm actually gonna run to the rest of as well. There be Okay Nope crashed saw the stuff there There we go Hello deep divers. So one thing that I noticed is that it scrolls It it starts in the middle Does it maybe it doesn't At least it didn't look like it did that time That's maybe because it was longer oops No, I don't know for some reason the first time I thought it didn't For some reason the first time I thought it didn't start at the beginning, but Sorry to think I was wrong now It could also be the camera too. This camera could drop frames I was looking at it not the actual device Definitely started at the beginning animation drop-down Push to fix for the problem with methods The way you did it the first time should have worked also segment segments keys It's line 65. Yep segments keys was I had that one wrong. Yep. Thank you for that. I will Actually just go ahead and update and I've development today on the deep dive I'll update my one on the device as well. Just copy that Delete this one and we can go back to the one with a list here tree set Probably something rotophile or something Okay animations. I want to be In a dictionary. Do we want that dictionary to be on Context? I mean we might as well I This will have the name of the animation and then The actual animation object which in our case Actually do want to make our context after we create all of these able to access them Or animations each one has a key and the animation and then we also want current animation And I'm just going to set it to rainbow by default Except for not rainbow the string. We actually want rainbow the object And then in our main loop here instead of saying animations animate. We are going to say context current Animation animate So whichever animation object gets put in current animation that is the one that we will play The frame for so if we update the one that's inside the context It should change which animation is playing Let's make sure that much works. We don't actually have a way to change it just yet But let's make sure that it actually works and runs rainbow, which it looks like it is so Next we will make it so we can actually update it. So index we want When we build the data object, we want to also include the selected animation Which reminds me actually usually on selects. I like to put a default one that shows Value I like to use negative one for this it's kind of random because it's a string, but I don't know It's just a thing I do is select animation. I like to do this as like So this way when you look at the page, it will say select animation In the in the drop down except not in firefox unless you hard refresh with control f5 Because firefox saves whatever value is in User interable elements like inputs and drop downs firefox actually saves it through a refresh So you have to hard refresh Chrome I think does not Though I suspect they probably will eventually This guy it's like it's convenient sometimes and inconvenient other times. It's an interesting feature Sorry again if that's loud I have learned my lesson to stick to the glass cups for the coffee The microphone is like right in front of me here. I don't know if that's like insanely loud when it's picking it up But so I apologize So we want to grab our selected animation. The way that we do that is by Uh, well with jQuery, I think we can just say the val of our select. So let's give that an id. We'll call that the uh Is that right? I don't know if I might be wrong about being able to do that. We'll see Uh, that's gonna be the animation select And then when we build the data object, we are gonna go Animation Is Going to be Still inside the index file. So I don't know where we just went, but it's not the right place Uh animation will be the value that we get out of the select animation select Think we can do that So let's do that and then print it And see if it worked Let's print the whole object in here obviously you would want to Turn that off eventually if you were trying to like use this in a real production environment You don't want to just print all the data that user sends your web server, but Building your web server it can be kind of convenient So theoretically, oh, it's uh reloading again I'm gonna refresh the page again and make sure it doesn't reset the uh device there again. Okay, perfect So theoretically this will send our selection now Including I guess technically it should send the minus one. So Let's do a submit We did get back a 200 Our animation is still running which I'm actually Well Am I surprised? No, I'm not surprised our marquee has stopped Uh one thing we should Ah, do we want to do it that way? That would use a lot of paper We'd use a lot of paper the What would use a lot of paper? Sorry. I think I I probably just said Whatever that was related to but I'm drawing a brain fart so to speak A lot of paper to Going to do with printing. Oh print all of our yeah. Yeah. Yeah print all of our stuff print the paper. Yes. Sorry took me a minute Uh, you know, that's a funny story honestly because uh if So for folks not familiar with javascript if you You know in javascript there is a method called console.log. This is the way that you Print this is the way like in python. We would call this printing. We would say this value got printed This thing here got printed Uh in python code, we would say print and then it's gonna show up Whoever the printed text comes in circuit python. It's in here Regular python. It's it's in the console where it executed or whatever Uh, if you were to cross your wires though and do it backwards if you were to put a print inside of here accidentally though It assumes that you are trying to print to a printer with a piece of paper So then when you submit this you now get like print preview and it's like do you want to print it to this printer? Uh, I cannot tell you how many times in my life I have accidentally called print inside of javascript It's been a lot There you go. Yeah I'm hoping one of these days that will just come by default Much to the chagrin of people who make websites that actually want to print things, but All right, sorry that was a tangent That's what you made me think of though talking about the paper Teletype terminals was once a thing Uh, all right, where are we at here? Uh, we've got our text in there. We're sending our data We did print all of our data here. So we did get it Uh, one thing we could decide is do we actually want to allow sending blank for that? Or do we want to just keep that how it was? I think I would prefer to keep it how it was so I think what I'll do is on the javascript side we are gonna say We are gonna do this differently. We're gonna create object and then we're gonna I guess go ahead and make variables out of these Variables from these so we can stop calling jQuery over and over again. So this thing will stop being yellow and crying You actually want this to be different we want if If That val not a parenthesis at all though If that is not empty string Then we want to add it to object I don't know why I cannot be consistent with quotes Actually do that in my electron app. I also do it in all my javascript without semicolons anymore That's enticing I have not made it there. I forget semicolons sometimes But I have not made it to the point where I intentionally omit them, but that certainly sounds fun I do a lot of switching back and forth Between python and javascripts Is that is it like uh Is it officially supported with no semicolons or is it just still the case like last I knew it was the case that like technically semicolons are required but The browsers are really forgiving and They'll let you get away with it if you Don't put them So like officially supported now because I is there this type script have semicolons I think there is some javascript that's even like written without by default So if it's not empty, then we put it into the object and we're actually I'm gonna do the same thing for animation and then we'll get rid of the pre loaded ones This way we only send data For the ones the user has actually changed And then what we'll do is I think we'll give maybe a different button to clear the marquee So if that one is not minus one Then we set it to the value and we make the object. It's empty We check our values. We add each thing if it exists Speaking of forgetting semicolons Okay, I need to make like a key combination that I can press on my keyboard that will bring my windows back Would it be convenient to use the scrolly thing? Let's try like this. I don't know if I'm gonna like doing it this way We'll see how it goes. I don't use these. Uh, I think they call them workspaces Maybe I don't use these very often, but I'm trying to get in the habit of it because it seems like sometimes they would be Pretty helpful So this time we'll select an animation and then we will Submit That's a bit awkward. My f12 is on the other workspace I don't know if there's an easier way to trance Like to move things between workspaces. I drag them to my other screen and then back, but I get any network action. Okay segment, oh Really? Well, maybe we're not allowed to um Unicode universal Universal telegraphic phrase book Graphic phrase. Oh for back to the book I was talking about earlier Um, is that not the way that you get a value from a select? Gotta try to remember now. Okay settlements Oh, we did misspelled this but we misspelled it in both places. So nice Yeah, not python with semicolons It's gonna take some retraining segments text input dot val is not a function Outline 132 in Could be did not be Missing something. Oh Yes, I am in fact missing something Which is that we stored the value in the object instead of the object in the object Which is obviously not what we wanted to do Already selected. There we go. Oh, no, we still have And maybe I didn't refresh This was a little bit. Okay. This is the old version Now we have the new version Okay, there we go. And indeed it did Do that and uh This time our marquee is still scrolling even though we had blank in here Because we now have code that was checking it and not submitting it that means that our marquee gets to keep going Uh, sorry free association was looking at your book install Uh, unicode that wasn't unicode. Uh, no worries Okay, so now we should be getting our animation on this side So we can actually go ahead and use it It's kind of the last bit of this Link here we go if Animation in Request object Keys Then we want to go context In with the quotes. I don't even understand why I don't know why we did current animation, but just text to scroll It feels like they should either both have current or neither have current Let's call this current text That way they're both current Okay, so now what we will okay, we need to make one more Test actually we want to say so if the front end sent us an animation The next thing we need to do is check if that animation is actually in our dictionary or not If it's not then we're just going to ignore it Or we we could return an error. I guess but uh, if request object Animation Is not in context Animation dictionary dot keys, then we return the error So we will say that is still json. This is going to be false Error is going to be invalid animation specified Send how do you do the status? Wow, that's a lot of send Can you do the status in here like set status 400 or in my case I want uh I 404 and type response and send bytes Okay, we won't mess with that Looks like it's not super easy to change the status potentially But our json says successful so like the front end can still know right It's doesn't need to be specifically an error code But then if we got past this if statement that means That our animation was in the dictionary, which means we are allowed to use it Which means we can go on and set current animation to The animation from the dictionary quest object animation I use semicolons in python when it's convenient I I use semicolons in python when I want a convenient sequence of statements In a cut and paste rep or one liner Oh, yeah, that's actually a good idea. I've Cut paste multiple lines which kind of works most of the time, but Yeah, doing multiple and one with semicolons actually is probably more convenient A parameter for the response constructor. Okay, so we were not quite at the right level that would be response here Yeah, which control click is let me get in there. Let's go to their constructor It's just status or what are we looking at? That is Yeah, tuple of into our string. So we will say status this one is um 400 we're saying that's a bad request because you gave us input that's invalid So bad request and in order to test it. I'm actually going to add another one of these that is fake animation That way we can send one that The back end won't recognize Okay Oh One more thing. So look are we actually going to change animations when it goes through or Looks like it But as soon as we change context current animation that means It should change which one is actually occurring on the device To have a weird eventually slowing down. It's actually missing. It's a scroll. I think we're starting to do We're starting to probably do too much truthfully because it's like every every few scrolls every few characters It kind of hangs a little bit longer I think right now it was on a point two delay so Meaning it would scroll one character five times per second at full speed But of course, it's limited by the main loop at this point. Interesting. I hadn't noticed it slowed down before See anything interesting on the printout Okay, so if we go rainbow chase Or rainbow, let's do comet Nope network error So did we get our 400 back actually might have got our 400 Uh error net reset. We might not a center response actually. We might not a center response No, we have a response though One thing we could do is add which things actually got changed Int object is not iterable Status, um, does it want a tuple maybe? Oh, yeah, you told me this a while ago. Okay. Okay. Yeah So you either give it a status enum Or you give it a tuple which is int string. I'm guessing that's the code and then the message probably We could tell by looking at one of these. Yeah. Yeah, and I'll go with the default one Which is not imported so we'll import that Yeah, thank you for the heads up on that. Let me catch up on this You're gonna have also common statuses You import them all from status Yeah, if we wanted to use more than one operating would instead of doing individuals if you thought about something like Server on error. Oh, that's interesting. Have a separate handler function Be kind of interesting You want to have like a custom error handler Basically, if you want to define in all cases, I want this to happen on a 404 or something like that Okay, so that should be good now All right, we will just resubmit that You got false invalid animations specified So our error message does work Which is cool Say as though I understand why we got an error instead of a successful response though We did get an error. I mean most specifically that means that Request animation was That's rainbow comet Is not Oh Yes Don't want to do not equals. We want to do not in Emerging this pr. There'll be a common h2p status But separate status objects saving typing Considered that the problem is the server does not control the responses Thus, it's not aware of them due to the chunks chunked response I have to update all my examples to 4.0 Okay Getting better, but I still sometimes do it the wrong my instinct is still the wrong way to try to like click up there instead of Else we'll okay. There we go. So one thing I noticed is that we did change to comet. It was successful But it like kept the last state of the previous animation and then like used the new animation to like sweep through and erase it um And we don't want that we want to fill it with we want to turn all the leds off whenever the user changes So inside of here, we're also going to say Uh pixels dot fill zero, which will turn everything off Okay, there we go. So now rainbow comet starts up and it is just by itself. It doesn't have the rest of the stuff still Sparkle is the same way all of them will be the same way awesome So this is kind of the most basic version of what I want to make We have about 20 minutes left or so in tonight's stream. So let's see What Do we want to work on next we could either Go back to the htk 16 33 whatever and get that polished up and ready to submit a pr the non-blocking marquis Or we could keep going on the server piece of it and provide some more functionality in the server So one thing actually that we are missing right now is an ability to Set the marquis to nothing I guess we could cheat by putting a space there maybe And that will technically work because it's not an empty string Uh It would be nicer to have a way that's not using a space though See because the thing is if I just erase that you might think like just erase this and submit And you're good to go but the problem is now our front end filters that out, right? We said if that's empty then we don't submit it Um Boy the queue is pretty awkward. What does the capital queue look like? The capital queue looks way more like a queue interesting So you I you know, I don't know you can cheat with a space and like It works for turning it off because it's actually technically not A space is a lack of a character instead of a character, but it still counts in java script I think it'd be nice to have a better way to do it though Like I think it'd be nice. We add maybe one more button for just like clear the marquis basically the first ever programming book that I ever had myself Was an html programming book and it instructed you To make your code shoddy like this For whatever reason the memory of that book just popped back in my head when I accidentally typed button as uh uppercase the first time That's what we want right there. So then we'll make an api for that I don't mean I guess we could reuse this if we really wanted I think I want to have a separate url for it though I mean part of the point of this is to make the code A little bit more advanced a little bit more complex, right? We could reuse this and just the front end sends a different data object that You know has a different variable inside of it Partially though, this is like kick the tires show off as much of the functionality as we can Give somebody an idea of how you use all these things together in a more sort of real world environment even though it's like And I have that much going on. It's more than a simple test. Um for the route on this one. Let's do clear marquis That is also going to be taken a Uh, let's do a delete. We might as well, right? I think ordinarily I'd probably reach for post here, but um in the interest of again just kicking the tires using a bunch of the stuff Let's make it a delete request instead We do want append Slash I remember the old days when html was constantly shouting found it exhausting just thinking about yeah It's it's weird how much that does have an impact. Honestly, it is like It doesn't seem like it would be that big a deal But if you do spend a day just reading code that's all shouty caps at the end of the day You're like you're more anxious or whatever I am at least Uh current text is gonna be to empty and I don't think we need to do anything else it should It should take care of it once it gets to here and sets that We do need to return the response Request to get passed in here So now we're gonna want to send a delete request to this when we click on the clear button I'm gonna put it after postjson. It doesn't really matter, but In blinking and scrolling Uh, let's go No Python is showing function not def we want function clear marky Actually, we don't we want to click on the button. We want jQuery. Actually. Yeah, uh, let's make a variable for that matters less in this case, but Actually call that clear marky. I want a clear marky button. I like to put the type of the thing in the id Clear button we have Now we can go Clear button. Whoops click To make a delete request, which is going to be similar to what we're doing in here Marky beat content type up case json body. We don't actually have anything to send this time. So we can just give it empty result await I guess it's mad because it's not inside of an async function So I guess we're gonna go async function Clear marky Put this inside of that and then call that from here because that's obviously way different Therefore can work without errors coffee Oops, nope did it again clear There's nothing Got no requests By refresh Okay, I don't know Why but we got the web workflow a couple of times. Maybe we should use Uh, maybe we should not use Oh, that's default. I guess though Maybe we should make a url. That's not the root. I don't know why it would do I guess maybe if we maybe maybe it's because it wasn't running yet Maybe I loaded the page before Code pi actually had the server started That's my best guess. I don't know. That was that's interesting web editor Change to that. But then if we go clear Solid still nothing happens Uh console and the console. Okay, so literally nothing is happening when we click. I think We probably messed up the click listener, right. Yeah, that's an id. There we go There we go. Now we have a way to clear it When we clear it should we take it out of here too? Or should we leave that in case you want to go back to it? Because now you can just submit to get back to it Something wrote to the device and it rebooted Um, I don't know. I could see a case for both ways. I think I prefer to leave the text there I think I prefer to leave the text there As a user, I would say it probably feels a little bit more natural if after you click clear this also gets cleared out I would say that probably feels more correct feels more correct as a user But there's a small chance that you save text that somebody actually did want And I would say the small chance of saving text that a user did want outweighs It not feeling right to the majority of users Do I actually believe that and stand by that though? I think I'm talking myself around to the clear side actually It seems nice to store the user's data But the majority of time if they click clear they probably want to clear what they want And so we're actually just giving them extra We're just giving them extra steps because now they need to like control a backspace or something, right? Like we basically just gave them an extra thing to do Let's also clear it out Save that Oops, save that. I'll be right back Okay, oops And then we have web editor go clear I didn't refresh did I don't think I refresh Oh, uh, now we're back to uh No, it still don't work Didn't give any errors either I not save the page. Uh, yeah, we don't have this in here. Oh, I Put in the wrong spot actually Yeah, this should be in here So did We wanted to use well if we wanted to use it quote unquote in the real world and we were gonna have it plugged into a computer We should probably uh Modify boot pie to disable the auto reload There we go. Now it clears it and it takes it away from here I would say that's a pretty good start for what I'm aiming for Look handler for catching the file not exist Right to the way I could do error handling How flask does it returns a response? But if you pass a generator as a body it uses shrunk encoding seems logical But it's more advanced and requires some more knowledge and understanding of python All right, I think I'm going to call it a night there. So this has uh, again been the deep dive program Um, I will be back tomorrow morning if you are interested in this sort of content, um with working on circuit python stuff You can catch more of this, uh every Saturday morning at 10 a.m. Central time I stream Over on my own channel foamy guy underscore twitch You can follow me there if you want to get notifications I'll also drop links in the live broadcast chat when I'm getting started Um, I think tomorrow I will for sure be working on polishing up the non blocking marquee to get that submitted as a pr Also, I know that there is still some There are prs that are ready for another look, um So we'll probably be back to doing some more prs a lot of the uh A lot of the rounds of picon submissions I went through and did the first review and the feedback on all of them and a couple of them The author has gotten back and posted another comment as a response. So it's either ready for another look Or it has a response and a new question or something like that. So I'll be following up on that stuff Tonight, I really wanted to get my own hands dirty and work on my own code More so than reviewing. I've been doing a lot of reviewing lately and I was eager to get back to tinkering myself So, um, that's why we worked on this tonight instead of doing some of those um But that is it for now. I appreciate all of you for watching Uh, definitely as well. Like we said before huge heart reports. Thank you, of course to Michael pocusa for working on all of these extended features in the htp server library Uh, including for Noticing that bug we ran across earlier and fixing it live. That's super awesome. Definitely appreciate that Um for everybody else. Thanks for watching along. I hope you found this interesting Uh, if you are interested in tinkering on it yourself again, the way to get started right now is it's in the pr only So you'll have to head to htp server Library and then check it out from this pr number 54 That's where you can get the version of the library That you saw me working with today, which is the one that has all the latest Features and stuff in it. So I will head out for now I will see you all later and thanks again for watching and I hope you have a good evening and a good rest of your weekend Thanks