[Week 4] If It Worked First Try, You’re Doing Something Wrong
Neel M -
Hey everyone! Welcome back to Week 4 of my Senior Project!
If you recall from last week, I had said that the setup server that allows users to configure the system had been installed successfully in the target image, where I had seen the files of the server installed in the correct place. However, I incorrectly assumed that this meant that it would work first try.
To preface this, we need to go over the main frameworks used to run this web server. To recap, there are two parts of this server: the frontend and the backend. The frontend is a React-based Node.JS web server that hosts a routable web-page that allows the user to configure settings. On the backend, there is a Python-based Flask server that interprets API calls from the front-end and applies them to the device using Linux commands. I know this is a lot of new information that I haven’t really gone into too much detail about, so here’s a basic explanation of everything:
- Last week, I explained the concept of the frontend and backend, linked here.
- React: This is a software library built with JavaScript (JS) that allows developers to create visually appealing user interfaces that are extremely interactive.
- JavaScript: high-level programming language that is widely known as the “language of the Web” because of its versatility in creating interactive and dynamic elements on websites.
- Node.JS: This is a standalone JavaScript runtime environment (a platform that executes JS code outside of a web browser). It’s great for building fast and efficient apps like websites and chat services.
- Flask: This is a Python-based backend framework used to handle things like routing, user requests, and connecting to databases. It’s great for building APIs or web apps because it’s simple, flexible, and easy to extend with other tools.
- An API (Application Programming Interface) is a way for different software systems to talk to each other. It lets clients (like websites or mobile apps) send requests to a server and get data or responses back.
Now, onto the progress I made this week:
One of the main blockers last week was getting all of the dependencies (other software libraries used for the functionality of the server) correctly installed into the target image. Once I got them installed into the final image, I assumed I had done it correctly, but I wasn’t able to check if the services were actually runnable, since I hadn’t paid close attention to which dependencies were installed. Upon closer inspection, I realized that certain files required for each dependency to run weren’t included in the final image because I had incorrectly entered a command that filtered out all of the packages meant for a specific architecture. I had assumed that each package was formatted for a common articulation of the ARM CPU architecture (AArch64). However, this was not the case. In each software package, they were actually labeled with the tag “ARM64,” so when I ran the installation procedure, it filtered everything out, and as a result, the actual executable files weren’t installed. I hadn’t noticed this because, for some reason, no errors were thrown, so I was blissfully unaware that anything was wrong. When I ran the server manually on the virtual machine (VM), it wouldn’t start, and at that point, I realized it was likely due to the filtering issue, as it finally threw an error when I ran the server. Once I corrected that line, the installation began including the executable binaries needed to run the server.
After this point, I also realized that the server needed to start up as quickly as possible when it detects a user connection. Once I got the server to appear and run in the VM, I noticed that it was taking upwards of ten minutes for the web server to become accessible. I realized this delay was due to the system compiling all of the files required to securely run the server at runtime. This posed a major problem for two reasons. First, the board we’re using has limited processing power and is already under significant strain from the drone platform. Second, if the server doesn’t start up immediately upon device detection, it disrupts the seamless setup experience we’re aiming to deliver.
I fixed this by running the build process of the webserver on the host machine, where it would take all of the files from the code repository and create routing tables and all of the other things it needs to seamlessly run the front-end server. I just needed to run this command, then drop the resulting compiled files into the final target image.
I want to remind you all that I was still running the server manually at this point. So, once I saw it working, I began transitioning back to the automatic startup system I had initially devised. After re-enabling the automatic startup services, I realized I had made another mistake. Yes, the server was running when a client connected, which was good, but when I navigated to the configuration page, I noticed that none of the changes I made were being applied.
Once I checked the logs (which, thankfully, I had the foresight to set up—shoutout to past me), I saw that the backend server responsible for applying the changes was encountering issues while executing Linux commands. After some digging, I realized the problem was due to incorrect folder permissions: the server didn’t have the rights to run the necessary commands to create a user. I resolved this by setting the folder’s owner to the web-server user, ensuring the server could run the commands without restrictions.
Finally, everything started working smoothly. When I launched the VM, the web server came up, I could access the web page, interact with it, and successfully apply configurations to the system.
After I confirmed that everything worked, I went to my on-site advisor to ask if we could begin flashing the Jetson Nanos, as I had initially hoped would do this week. He informed me that the kernel on the software compilation server that the team uses to compile the drone platform (without needing to do nasty cross-compilation stuff—read this for a refresher), wasn’t up-to-date. Because their platform requires a minimum kernel version to ensure that everything works optimally, I can’t begin my work without this.
To show the future of this platform, we must look first at the present. Currently, the team’s build process looks like this (without Yocto):
- The software development team pushes an update with changes to the GitHub repository.
- A continuous integration/continuous development (CI/CD) pipeline on the GitHub repository sees that a new change has been pushed, so it runs an “action” (workflow that dictates how to compile a piece of software) to compile the drone platform.
- This action runs on the Jetson Nano, which already has the necessary dependencies installed on the system to prevent any incompatibility issues.
- Once the software is compiled, it spits out a .deb package file, which holds everything necessary to install a functional software package on any Linux system.
To integrate this with the Yocto Project, all I have to do is retrieve the complete .deb file, and install it in the final image. Once this is complete, I just need to flash this image onto a Jetson Nano, test if everything works, then this portion of my work is complete.
Thanks for reading this week’s blog! Stay tuned for more progress 🙂 .