An OpenStreetMap App written in PicoLisp (Pt. 2)
5 min read
Now it's almost summer and definitely time to finish the blog post about the PicoLisp Ice Cream Finder! This is a continuation of this post, where we explained how to work with Google Maps and OpenStreetView.
The app's purpose is simple: It should pick up the current location via GPS and display all ice cream shops and supermarkets nearby, based on the results from the OpenStreetMap API.
Setting up the Working Environment
First of all, let's set up a working environment that allows us to test and modify our code in a fast and efficient way. In order to do this, we will use the PilBox Pseudo-Terminal.
First of all, let's create a simple template. It contains a file
App.l which defines the app title as well as the app logo and some basic CSS files. You can find the template here as a reference. Compress the template folder to a .zip-File and send it to the PilBox app on your phone, for example via termux share (or email).
After opening the zip-file in the app it should look like this:
Next we expand the .zip-File in the working directory on our PC and start the pty from the same directory. This way we have the same relative paths and are able to use
pbGet to copy files.
$ cd <your favorite picolisp directory> $ unzip iceCreamApp-Template.zip $ pil ~/pil21/bin/pty <your phone's IP> android:
If you have trouble with the tty, read here.
Note that PilBox should be open on the phone for the tty to work. After we got the connection, we can check the app folder on the phone:
android: (call "ls") App.l JAVA PID RPLY Version favicon.ico lib loc src BOSS LISP PIL-369 RQST bin icecreamPt1 lib.css log steps.rc COPYING Locale Port UUID db img lib.l log- tls
This shows the folder
icecreamPt1 which includes the template files of the app, as well as
PIL-369 which is the internal app's name on my phone (unfortunately my Samsung smartphone seems to rename .zip-files before opening them in external apps).
Now for testing purposes, let's rename the app in
App.l from "PicoLisp App Stub" to "Mia' Ice Cream Finder" on the PC and transfer it to the phone like this:
android: (pbPut "<appname>/App.l")
In this example, the appname is "icecreamPt1" because this is how I called it in the repository (link in the end).
Now the app title should be changed on your smartphone as well.
Defining the general app layout
I like starting with the easy things, like setting the header and main layout features. Let's define a function
work that gets called. Inside
work, we call
pilbox, which allows us to define the App header by ourselves instead of the pre-defined "PilBox" text.
"Mias Ice Cream Finder (Pt. 1)" (de work () (pilbox (<h5> "fh" "Mia's Ice Cream Finder") ) (menu "Mia's Ice Cream Finder") ) (work)
Note: the CSS-class
fh is defined in the pre-installed
Next, we can define the background and styles with bootstrap (here for more info). We display a title called "Want ice cream?" and a search box with two buttons. The buttons can be pressed, but there is no function tied to it yet.
This is the PicoLisp code for that:
(de work () (pilbox (<h5> "fh" "Mia's Ice Cream Finder") ) (menu "Mia's Ice Cream Finder" (form NIL (<div> "bg-light container-sm border" (<div> "d-flex flex-column " (<h3> "mt-5 mb-4 d-flex justify-content-center" "Want ice cream?" ) (<div> "mb-3 d-flex justify-content-center" (<p> NIL "Find ice cream near your current location!") ) (<div> "d-flex justify-content-center" # Search button for ice cafe (gui '(+Style +Button) "button-icon bg-white mb-5 mx-3" T "icecreamPt1/img/ice.png" NIL) # Search button for supermarket (gui '(+Style +Button) "button-icon bg-white mb-5 mx-3" T "icecreamPt1/img/supermarket.png" NIL) ) ) ) ) ) )
and this is how it looks like:
Getting the current location
Now comes the interesting point: Let's take our current position and display it on OpenStreetMap. First of all, we import the relevant name spaces, some global variables and the
"Mias Ice Cream Finder (Pt. 1)" "@lib/gis.l" (symbols 'icecream 'gis 'android 'pico) (local) (*Latitude *Longitude)
Now we can fetch the current position with the
gps function, just like in the previous post on GPS. But this time we want to get the data in the background: let's refresh the location every 6 seconds. Periodic tasks can be realized with the
task function (here you can more information on
(start (scl 6) (task -6000 1000 (nond ((location?) NIL ) ((gps) NIL ) (NIL (setq *Latitude (car @) *Longitude (cdr @)) ) ) ) )
What does this do?
- First, it sets the scale for integer calculations to 6 (if you don't know the
sclfunction, check out this post).
- Then we define a periodic task, executed every 6 seconds. The first time it is executed one second after starting the app.
nondis a multi-way conditional which executes if the argument evaluates to
NIL. We distinguish three cases:
(location?)is false, i. e. GPS permissions are not given,
NIL, i. e. GPS data is not (yet) available
NIL: the exit condition - GPS data is available and stored in the global variables
Let's test it: Now the app asks for GPS permissions at start up. If we confirm with "yes", we can execute
(gps) in the tty and see the current location:
icecream: (gps) -> (142520664 . 193401665)
side note: NOT my exact location 😄
Nice! So let's use this data and display it on the map.
(<div> "map" (<osm> *Latitude *Longitude 12) (<poi> *Latitude *Longitude "icecreamPt1/img/here.png" "0.1" "1.0" "" 0 "black" ) ) ) ) )
In the next post, we will see how to use the OpenStreetMap API to fetch the supermarket and ice cream shop position and display them in the map. Also, we will use
ServerSideEvents to display some information.
You can find the source code up to this point here and the zip-File here.
- Ice Cream Icon by irasutoya.com/2015/07/3.html