Tag: library occupancy project

  • Library Occupancy Project Follow Up

    Library Occupancy Project Follow Up

    The occupancy project is now deployed at Sorrells Library. After running for more than a week, it’s time to see how it performs…

    So I dumped the database, feed the dump into a python script for processing, and plotted occupancy for each day. And the results are surprisingly good! Let’s take a look.

    Here is occupancy plotted vs. time of the day. We are able to see multiple peaks that sometimes exceeds total capacity of the library. It may sounds strange but there is a scientific explanation. The system detects Wi-Fi devices (and therefore occupancy) present in the last ~3 minutes. So if there are a lot of people moving in and out of the library, the estimated occupancy will increase rapidly, since the system counts everyone in the library during that time, even if the person is leaving / entering the library.

    As explained above, large flows of people are shown on graphs as peaks. I marked the most identifiable ones.

    Not surprisingly, the peaks coincide start/end times of popular courses. Here’s occupancy data on Saturday for comparison.

    Now if we merge these together…

  • The Making of the Library Occupancy Estimation System, Part 5 – the Enclosure

    The Making of the Library Occupancy Estimation System, Part 5 – the Enclosure

    It’s almost time to deploy the ESP8266s. I switched from the previous board to wemos mini lite, a smaller board with a variant of ESP8266 (ESP8285). The ESP8285 includes a on-chip 1M EEPROM, reducing the cost. The most important difference is that the newer boards don’t have pre-soldered pin headers. Desoldering pins from the previous board is proven to be tedious and time-consuming.

    While waiting for the boards being shipped from China to me, I designed a enclosure for that board. I can, of course, just stick the boards to walls. But a case is always nice – it makes the project look less cheap (while it actually is pretty cheap).

    The design is consisted of 2 parts: the body and the cap. The body is going to be 3D printed while the cap is going to be cut from clear acrylic panel. 4 M1.5 screws hold the components together.

    The parts are modeled with Autodesk Fusion 360…

    and then made…

    and compared to my sketch…

  • The Making of the Library Occupancy Estimation System, Part 4 – the Frontend

    The only part missing was a front-end. It is 2017, and splitting up front-end and back-end is now a must. This is even more true in this project: serving html and other resources from my free Heroku server does not sound like a good plan – with only 1 web instance, the server can be easily saturated. So the plan was to host the front-end on GitHub.

    The frameworks I chose for this job is Vue for MVVM and MaterializeCSS for the appearance. The reason for using Vue instead of React and Angular was Vue is more suited for small project like this, and is extremely easy to setup (include a js file, add 5 lines of code and Vue is ready). The reason for using MaterializeCSS was simply because it looks nice.

    A few hours later:

    The front-end is pretty bare-bones (< 100 SLOC of js), but it does the job. And thanks to MaterializeCSS, it doesn’t look half bad. The page is also responsive (again, thank you MaterializeCSS).

    The front-end already looks pretty nice on phones, so I took a step further to make it an iOS Web App (no I don’t want to pay $99/year to make it an actual iOS App).

    The first thing to do when developing a mobile app is of course to design an app icon.

    It won’t get me any design award but hey, it’s an icon.

    The tricky part of making the iOS Web App is trying to make it act like a native app. Some CSS magic was used to make it app-like. Also I spend I lot of time working around an iOS bug that made the entire html scroll and bounce even if I told it not to… A few failed attempts later I gave in and used a library called iNoBounce. That worked well.

    How the icon looks on home screen:

    Good enough.

    Frontend Code on GitHub

  • The Making of the Library Occupancy Estimation System, Part 3 – the Server

    So the sniffer part was complete. The server was the missing piece of the puzzle.

    The server needs to do several things

    1. Receive data from the sniffer and decrypt
    2. Save sniffed data (probe requests) to a database
    3. Analyze probe requests and deduce occupancy
    4. Provide public APIs for retrieval of occupancy information

    I’m using python3 for the server since it’s one of the better-supported languages on Heroku. Unfortunately, XTEA implementations on python3 do not work well, so I reimplemented it by porting my embedded-C version. (One of the advantages of CTR mode is that the encrypting function is its own inverse. So encrypt == decrypt.) Sniffer MAC address and information of sniffed devices are recovered from decrypted data. These are stored to a DB after some simple processing (filtering out invalid MAC addresses, etc.).

    For storage of probe requests, I use sqlalchemy which is based on SQL. I didn’t use one of the now-popular no-SQL databases since I’m not storing GBs of data. Also, enforcing schemas and relationships clears up the logic of the server.

    I also made a simple linear model to deduce occupancy from probe requests. The model is run every 30 seconds and output is stored back into the DB. It is not efficient to run the model every time a user asks for occupancy information. When a user requests occupancy, pre-computed occupancy is read from DB and directly sent to the user.

    The public API is RESTful and based on simple JSON. I did not bother with pre-existing protocols like JSONAPI 1.0. These protocols are way too complicated and verbose for this project. When the cost of implementing a complicated protocol exceeds the potential benefits of that protocol, it’s generally a good idea to steer away from it.

  • The Making of the Library Occupancy Estimation System, Part 2 – the Sniffer

    So I proved that this idea is somewhat feasible. There were two major problems that need to be addressed: 1. there were too many probe requests, 2. there needed to be some way to send found devices back to a server.

    The “too many probe requests” problem was easy to fix. I implemented a bloom filter, and for each sniffing session, sniff requests from previously identified devices would be ignored. I also got rid of the Arduino environment since I need access to a newer SDK, and the Arduino environment ships with an older SDK. To set-up the SDK was quite a hassle. (SDK)

    The other problem was (in my opinion) more important: Data need to be encrypted before sent – it is a pretty bad idea to send MAC addresses in plain text. So I built a protocol around XTEA-CCM, eXtended Tiny Encryption Algorithm in CCM (CTR + CBC MAC) mode. XTEA was chosen because it is easy to implement and has no known security-breaking flaws. The weakness of XTEA is its slowness – not a problem here since data sent is usually less than 4KB: the 120MHz ESP8266 should be able to handle that easily. Now the problem is what protocol to use for transmission of this encrypted data: the ESP8266 supports TCP and UDP. I decided to go with HTTP/1.1 (which is, at its core, TCP). Using raw TCP / UDP sockets is of course convenient, but requires a standalone IP address, and server with standalone IP address is kind of expensive (a whopping $3/month!). By using HTTP, I can use services like Heroku, Google App Engine…, which are free for small projects like this. (Cost is important)

    I wrote a few wrappers around the original APIs to abstract things a bit and to make life easier. Original SDK requires you to do almost everything manually (WiFi connection management, DNS lookup, etc.), so it is nice to separate core logic from supporting code – currently user_main.c is less than 200 SLOC while the entire repository is around 1300 SLOC. Dumping 1300 lines into a single file would be a disaster.

  • The Making of the Library Occupancy Estimation System, Part 1 – the Idea

    So… Here’s a problem that most CMU students encounter on a daily basis: finding someplace to study. This process is surprisingly labor intensive: Here’s an example:

    1. You decided to find some place to study.
    2. You walk to Sorrells Library in Wean, and it was full: after the recent renovation the library has become one of the best places to study on campus, and there was no spot left.
    3. You walk to Hunt Library, climb to the 3rd floor, and it was also full. You think that Gates may have some spots left and walk to Gates…

    … and you just traversed half of the campus, wasting 15 minutes for no good reason. (Or, if you are one of the glass-half-full kind of person, it’s 15 minutes of workout.) What if there exists a web page so people can check if a library is full or not…

    The basic idea here is to estimate occupancy in a cheap and reliable way. Some ways are:

    1. Installing an IR sensor at the door of the library, and count people entering/exiting the library.
    2. Putting a camera at the door of the library, and count people entering/exiting the library.
    3. Putting cameras in the library, and count people currently in the library.
    4. Using some device to count Wi-Fi devices in the library, and estimate occupancy based on Wi-Fi devices.

    The problem with 1 and 2 is that both solutions are counting delta/difference. We need to integrate the difference to get an occupancy estimation, and error will accumulate over time. 2 and 3 both require cameras: although cameras themselves are cheap, and computer vision libraries for recognizing people exist, hardware able to process camera input is expensive. Cameras may also raise concerns about privacy: most people are not comfortable if they are “monitored”. The only cheap and reliable way is 4: using some gadget to count Wi-Fi devices.

    And that gadget is ESP8266. A Wi-Fi-enabled SoC. There are a lot of boards with this chip out there on eBay. The one I used to develop the system is this one:

    And these boards are very cheap (4-8 dollars a piece). Buy one here.

    To investigate if this is going to work, I modified some code (Github) found online and see if it is going to pick up any device.

    The code listens for probe request frames (broadcast frames from Wi-Fi enabled devices to check what access points are available nearby). I flashed the program into the ESP8266, and it worked! The problem is: there are too many probe requests…

    To be continued.