Herringbone, light up! Part 3: Web Interface and Android Application
With this text, Master Gambs completes the description of his new Christmas tree garland.2015 Moscow
Hi, Habr!
So, we got to the final stage: since we have a garland that is controlled by a Black Swift nanocomputer with integrated Wi-Fi, then it is logical to make a web interface for it and a smartphone application to flash the LED , if you know what I mean. ')
But first, at the request of readers, we publish a video of a Christmas tree garland. I do not think that someone has not seen Christmas tree garlands, I think that just not everyone believes that I really followed the LEDs on December 28-29 to decorate the Christmas tree ...
I sit behind the scenes and with one hand hold the camera, and with the other I switch its modes of operation, poking the mouse into the browser.
Now, when the last traces of mistrust have evaporated, we will continue. In the previous series, we got a working garland controller that can receive commands via a UNIX socket — they specify the mode of operation, as well as the speed and brightness of the garland. The easiest way to make a layer between the web and the socket on banal PHP is literally a few lines.
Web server and PHP5 on the nanocomputer
We already have a standard uhttpd web server in Black Swift that serves the regular LuCI web interface. To work with PHP, we will install a second web server - lighttpd (I think it’s necessary to include it by default in the final firmware and php5), as well as a convenient nano text editor:
The web server and PHP will pull up their dependencies themselves. The average three commands, I think, are obvious, the first one will pull up the updated list of packages from the repository, and the last one will enable autorun for lighttpd at system startup.
Now a little tweak the configs:
nano /etc/config/uhttpd
In the first lines we look for the directives "list listen_http", of which there are two pieces, and change the port in them: 80 to: 8080 (or some other). Then restart uhttpd with /etc/init.d/uhttpd restart.
Similarly, we edit /etc/lighttpd/lighttpd.conf (it is long, using Ctrl-W to search for the desired text in nano):
server.modules = ( "mod_cgi" )
The config has a long commented out list of plugins, we only need mod_cgi, which will work with php_cgi.
Everything is quite obvious here for anyone who has ever seen a web server on Linux: the root folder, the root files (add to the index.php list) and the binding to the * .php files of a specific handler.
Now open /etc/php.ini and edit one line:
doc_root = "/www/tree"
And the final touch is /etc/init.d/lighttpd start
Now we have a web server with working PHP on port 80, so all that remains is to create the directory / www / tree and put the index.php file in it. Which, of course, you first need to write.
index.php
The task is also extremely banal, let's face it.
Writing to a file socket from PHP is not easy, but very simple:
Where $ cmd is the command that we want to transmit, for example, brightness, and $ val is the corresponding value, for example, 2.
Then everything is obvious: the user moves the slider (in HTML5 sliders appeared, hooray hooray), javascript pulls out its position and sends it to the PHP file:
When the slider is moved, the first function immediately changes the numerical value next to it, the second one sends the command and this value to the PHP file as soon as the user releases the slider. NB: the first HTML5 implementations suffered from the fact that onchange and oninput in the range worked the same way, popping up at each shift of the slider, but now this is not very important for us.
You probably already paid attention to two points: JS calls the same index.php in which it is written, only with parameters, and in HTML there are inserts in PHP that substitute some previously defined position of the slider when generating code.
The first is done because, for ease of demonstration, I did not use AJAX, and the second was that when I opened the page it showed the current state of the garland, if any, was previously installed.
Processing the parameters passed with the file is simple:
Everything is just as trivial here: if the parameters are passed, then we first stuff them into a socket, and then we will show the web interface, if not, we’ll just show the web interface.
We don't have much garland settings, so it’s logical to store them in a regular file. However, it is worth remembering that we wrote a C program without saving the parameters, so PHP, after restarting the system, should show the default parameters, and not those previously saved. It is very easy to do this in OpenWRT - save everything unnecessary in / tmp, it lives in RAM and disappears forever upon reboot.
Now you can access our Christmas tree from the browser.
Application for Android and Network Service Discovery
Disclaimer: in general, I myself can write about Android in some way, so do not judge strictly. On the other hand, the fact that I did it and it works says a lot about the simplicity of implementing such Black Swift applications, when prototypes of all the main parts of the system can be made in the literal sense of the word on the knee.
So, we have a web interface at a certain IP address. A banal way would be to show on the smartphone its contents in the WebView component, but we will go a little further and auto-detect this address (well, right word, you won’t dictate to your wife, ”Darling, turn off the garland, she’s at 192.168.1.158, if DHCP tells her that something new did not give ") with the help of the Network Service Discovery service. NSD works fine in Android starting with something like 4.1 or 4.2, but this is unlikely to stop us now.
In the light of the disclaimer, I will not tell you how to write for Android, but will immediately give you a link: an application that I did for my smart home interface . You need to download it, put it somewhere neatly, then put Android Studio , open a project in it and fix it a bit.
Open the Gradle Scripts → build.gradle (Module: app) and change the applicationId "lightcontrol" to something more adequate for the Christmas tree. Although you can leave “lightcontrol” in general, you probably will not have any confusion with the “smart home” software with the same name.
The same cosmetics: in Manifests → AndroidManifest.xml, we change the android: label to something about the Christmas tree (NB: com.example.lightcontrol.app here and in all other places except build.gradle, we don’t touch!). Similarly, go to res → values ​​→ strings.xml and change the value of app_name to something about Christmas.
Finally, open the main application code and at the beginning change the value of the TAG variable to something of your own. This word must be remembered, it will come in handy to us at the next step - the fact is that by this name the application will search for the necessary service in the local network. Let it be "Treelights", for example.
Have you changed everything? You can still go through the messages displayed by the application (I did not bother with the localization, everything is crammed right into the code) and change for beauty the phrases in the spirit of "controlling the light in the house" to "controlling the garland on the tree."
Now the final: Build → Generate signed APK, create our own key for signing the application and compile everything ourselves. In terms of responsiveness of the user interface, Android Studio is absolutely nightmarish, but building the project takes about ten seconds, not more, after which you either get an error in the log, or a suggestion to open the folder with ready APK in explorer.exe. Open, copy app-release.apk to your smartphone and install (in the Android settings, you must enable the installation from all sources in a row).
Now we return to the Christmas tree and configure the avahi service there, which will send notifications received by the NSD component:
We change exactly one point: in the name tag we put down the name containing the word that we previously entered in the TAG variable in the mobile application (this was the word "Treelights"):
We save, open /etc/avahi/avahi-daemon.conf and enter the line enable-dbus = no in the first section (we do not have DBUS, therefore without it avahi will start swearing when it starts).
We take the smartphone again, launch our application and rejoice, seeing after a split second of searches it opens the web interface of the Christmas tree garland.
The remaining time before the New Year can be spent on drawing a beautiful web interface with large buttons.
Instead of conclusion
I immediately anticipate two questions from the “why did you do it” series: 1) why do I need a garland with Wi-Fi and 2) why do it on the Black Swift, and not on the same Raspberry, since the dimensions here do not play a role.
In fact, of course, Wi-Fi is not really needed for the garland, and replacing BSB with RPi will not change anything in this. But you know the work of Akerlof “Market for Lemons”, he showed in it how the market with free competition can independently roll into the sale of cheap rubbish, that's just like those New Year's garlands lying in stores? Akerlof received for her the Nobel Prize in economics, and the work itself became best known for illustrating the process on the example of the automobile market - although the preface states that the example is neither important nor realistic, but was chosen simply because of the simplicity and clarity of explanation.
So, in my case, the situation is exactly the same, except that I have not been called from the Nobel Committee yet (Akerlof, however, also waited for 31 years for the call). I wanted to show how easy it is to use Black Swift from the point of view of connection, and from the point of view of programming in a rather complex project that has both specialized hardware, a web interface, and a mobile application. In fact, this is a normal, suitable example of the automation of a device within the framework of the now popular “Internet of things” concept.
At the same time, although I wrote three articles and a lot of letters in them, if you look at the volume of the final work, this is actually a “weekend project”, one evening in which it will take to solder garlands, and the second to write all the software.
The next time I will show an example of development in which Black Swift is critical and difficult to replace - because the dimensions of the same Raspberry Pi will be comparable with the external dimensions of the body of the entire final device.