Installing Tilestache on Centos 6.8 Minimal

(install Centos 6.8 Minimal from cdrom or iso)

yum update
service iptables stop
chkconfig iptables off
(disable selinux in /etc/selinux/xonfig)
yum install python-devel
yum install python-setuptools
yum install python-imaging
yum install libjpeg\*
yum install zlib\*
yum install gcc
yum install wget
easy_install modestmaps
easy_install simplejson
easy_install werkzeug
easy_install uuid
wget http://tilestache.org/download/TileStache-1.49.8.tar.gz
tar xfz TileStache-1.49.8.tar.gz
cd TileStache-1.49.8
python setup.py install

make simple /etc/tilestache.cfg file

{
  "cache":
  {
    "name": "Disk",
    "path": "/tmp/stache",
    "umask": "0000"
  },
  "layers":
  {
    "osm":
    {
        "provider": {"name": "proxy", "provider": "OPENSTREETMAP"}
    }
  }
}

NB: For a persistent cache, you may consider using a different location instead of /tmp, for instance /var/tilestache

cd Tilestache-1.49.8/scripts
./tilestache-server.py -c /etc/tilestache.cfg -i 0.0.0.0

Browse: http://192.168.1.124:8080/osm/preview.html

yum install httpd
yum install mod_wsgi
mkdir /var/www/wsgi

create /var/www/wsgi/tilestache.wsgi

import os, TileStache
application = TileStache.WSGITileServer('/etc/tilestache.cfg')

edit /etc/httpd/conf/httpd.conf (right after ScriptAlias /cgi-bin)

WSGIScriptAlias /tilestache /var/www/wsgi/tilestache.wsgi
service httpd restart

Browse:
http://192.168.1.124/tilestache/osm/0/0/0.png
http://192.168.1.124/tilestache/osm/preview.html

Installing Tilestache on Ubuntu 16.04 LTS

Recently I was struggling a bit to install Tilestache on a Ubuntu 16.04 server. Below are the steps that finally made it work. The server IP was 192.168.1.122

(install Ubuntu 16.04 LTS)
(sudo apt-get openssh-server) (for ssh access)

sudo apt-get update
sudo apt-get install apache2
sudo apt-get install zlib1g-dev
sudo apt-get install libjpeg-dev
sudo apt-get install python-dev
sudo apt-get install python-setuptools
sudo easy_install tilestache

edit /etc/tilestache.cfg (sudo nano or something similar)

{
  "cache":
  {
    "name": "Disk",
    "path": "/tmp/stache",
    "umask": "0000"
  },
  "layers":
  {
    "osm":
    {
        "provider": {"name": "proxy", "provider": "OPENSTREETMAP"}
    }
  }
}

NB: For a persistent cache, you may consider using a different location instead of /tmp, for instance /var/tilestache

Test by running tilestache standalone:

tilestache-server.py -c /etc/tilestache.cfg -i 0.0.0.0

browse:
http://192.168.1.122:8080/osm/preview.html

Install as WSGI program:

sudo apt-get install libapache2-mod-wsgi
sudo mkdir /var/www/wsgi

edit /var/www/wsgi/tilestache.wsgi:

import os, TileStache
application = TileStache.WSGITileServer('/etc/tilestache.cfg')

edit /etc/apache2/sites-enabled/000-default.conf (add 1 line)

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
WSGIScriptAlias /tilestache /var/www/wsgi/tilestache.wsgi

Keep python happy and restart web server:

cd /var/www
sudo mkdir .python-eggs
sudo chmod 777 .python-eggs
sudo service apache2 restart

browse:
http://192.168.1.122/tilestache/osm/0/0/0.png
http://192.168.1.122/tilestache/osm/preview.html

using tiles by leaflet: change

var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';

to:

var osmUrl='http://192.168.1.122/tilestache/osm/{z}/{x}/{y}.png';

shell script for seeding: (seed.sh)

#!/bin/sh

# World
north=80
west=-180
south=-80
east=180
tilestache-seed.py -b $north $west $south $east \
-c /etc/tilestache.cfg -l osm 0 1 2 3 4

# Netherlands
north=53.777
west=2.99
south=50.631
east=53.194
tilestache-seed.py -b $north $west $south $east \
-c /etc/tilestache.cfg -l osm 5 6 7 8

# Den Haag
north=52.137
west=4.240
south=51.999
east=4.443
tilestache-seed.py -b $north $west $south $east \
-c /etc/tilestache.cfg -l osm 9 10 11 12 13

for zoom levels: see http://wiki.openstreetmap.org/wiki/Zoom_levels

FluxBB email to Gmail fails

I recently installed a simple forum using FluxBB version 1.5.2 ( fluxbb.org ). I configured it such that on a new registration, an email is sent to the new user with a temporary password. This works fine for everyone, except for people with a Gmail account. What is wrong?

I configured FluxBB to use the SMTP server of my ISP. Email to GMail accounts are returned with the following message:

SMTP error from remote mail server after end of data:
host gmail-smtp-in.l.google.com [173.194.66.26]:
550-5.7.1 [212.54.42.164      11] Our system has detected that this message is
550-5.7.1 not RFC 2822 compliant. To reduce the amount of spam sent to Gmail,
550-5.7.1 this message has been blocked. Please review
550 5.7.1 RFC 2822 specifications for more information. gq7si2167397wib.62 – gsmtp

Unfortunately, this message gives no clue on what is wrong… After many experiments and examining the outgoing smtp traffic by Wireshark, I found that some of the email headers were separated by <nl> (“\n”)  only, instead of <cr><nl> (“\r\n”).

The problem was solved by adding one line in include/email.php, line 249:

if ($pun_config['o_smtp_host'] != '')
{
 // Headers should be \r\n
 // Message should be ??
 $headers = str_replace("\n", "\r\n", $headers); //<--ADDED
 $message = str_replace("\n", "\r\n", $message);
 smtp_mail($to, $subject, $message, $headers);
}

Compiling OMEconomy-4.0.6 for OpenSimulator-0.7.5

I also tried to compile OMEconomy-4.0.6 for OpenSimulator-0.7.5. Here I had a few more compile problems. First problem is that the OMEconomy modules use the NewtonSoft.JSon library, which was removed from OpenSimulator-0.7.5. I took the easy route and simply copied all NewtonSoft.* files from OpenSimulator-0.7.4 (in the bin directory) to the 0.7.5 bin directory.

There were also a few minor compile problems due to slight changes in interface APIs. Similarly to what I wrote about OS-0.7.4, I changed “GetClientEP()” into “RemoteEndPoint” in OMBase.cs, line 271.

Another problem was with the IClientAPI method SendChatMessage. In 0.7.5 this one got an additional parameter. Changing the parameter “senderUUID” into two parameters “senderUUID, senderUUID” solved the problem (OMBase.cs, lines 415 and 418).

Compiling OMEconomy-4.0.6 for OpenSimulator-0.7.4

Recently I tried to compile OpenSimulator-0.7.4 with the OMEconomy-4.0.6 modules for VirWox. Much to my regret, I got the following error message:

/root/opensim-0.7.4-source/addon-modules/OMEconomy/
OMEconomy.OMBase/OMBase.cs(271,45): 
error CS1061: Type `OpenSim.Framework.IClientAPI' does not 
contain a definition for `GetClientEP' and no extension method 
`GetClientEP' of type `OpenSim.Framework.IClientAPI' could  be 
found (are you missing a using directive or an assembly 
reference?)

Apperently, the definition of IClientAPI has changed in the meantime (see OpenSim/Framework/IClientAPI.cs). The problem was easily solved by changing “GetClientEP()” into “RemoteEndPoint” in OMBase.cs, line 271:

dd.Add("clientIP", "http://" + client.RemoteEndPoint.ToString() + "/");

So far, it seems to work properly.

Running Maqetta on Centos 6.3

I just tried to install a local version of the Maqetta HTML 5 visual authoring tool on Centos 6.3, but was treated on a long list of obscure error messages in its log file. Something like this:

!ENTRY maqetta.zazl 4 0 2012-12-28 09:55:58.503
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: The bundle 
"maqetta.zazl_1.0.0.master [25]" could not be 
resolved. Reason: Missing Constraint: 
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 at org.eclipse.osgi.framework.internal.core.
AbstractBundle.getResolverError
(AbstractBundle.java:1332)
 at org.eclipse.osgi.framework.internal.core.
AbstractBundle.getResolutionFailureException
(AbstractBundle.java:1316)
 at org.eclipse.osgi.framework.internal.core.
BundleHost.startWorker(BundleHost.java:323)

Obviously it didn’t work…  After some fruitless Googling and hair-pulling, I realized that I didn’t install the official Oracle Java JRE, but the open source version OpenJDK, version 1.5 (I just did a “yum install java”). But it seems I need something like version 1.6

After removing the 9 packages that yum pulled in (check your /var/log/yum.log), I installed the Oracle version of the JRE (rpm file) and everything worked fine.

Paprika Recipe Manager for iPad: export format

Another post about Paprika… Before adding a lot of new recipes, I just wanted to make sure that Paprika is not a “dead-end” in the sense that you can put things in but never get them out, for instance when you want to move to a different recipe manager. Paprika supports exports in two formats: HTML and “Paprika Recipe Format”.

In HTML, each recipe is saved as a separate HTML file in a folder called “Export <Category name> <date> <time>”. All photos are saved in the sub folder “images”. Each recipe file will contain hrecipe metadata in the HTML, so that it can easily be parsed by a recipe manager that understands hrecipe tags. The exported folder will appear in App File Sharing section of iTunes and can be copied to your PC (you can copy the complete folder, all contents in it will be copied automatically).

Although automatic parsing of the HTML files is feasible, I also had a quick look into the (proprietary) “Paprika Recipe Format” to see if that one would be easier to process, if the need may ever arise. The export is in the form of a single, huge file called “Export <Category name> <date> <time>.paprikarecipes. It turns out to be a ZIP file (at least version 2.0 to extract). When unzipped, you will get one file for each recipe, called <recipe title>.paprikarecipe (for instance “Boeuf bourguignon.paprikarecipe”). Each of these file is gzipped. Once un-gzipped, it appears to be in JSON format. There are no line breaks, so everything is on one single line. In the example below, I added some line breaks and shortened some lines (indicated by “(…)” ):

{
 "uid":"C918EB00-71BE-4AEE-A215-96373518F7A8-(...)F945F4",
 "name":"Antipasto van gemarineerde groenten",
 "directions":"1 Grill voorverwarmen.\n2 Intu(...)brood.\n",
 "servings":"4",
 "rating":0,
 "difficulty":null,
 "ingredients":"1\/2 limoen\n4 eetlepels (olijf)(...)\n",
 "notes":null,
 "created":"2012-09-29 18:06:46",
 "image_url":null,
 "cook_time":"10 min",
 "prep_time":"25 min",
 "source":"Allerhande 1998 nummer 9 pagina 23",
 "source_url":null,
 "photo_hash":"79f74b8a753fef94ee45a4981304fdd8e(...)cf",
 "photo":"20740DFC-8415-42B3-97E5-7D7049DFF0CA-1(...)8.jpg",
 "nutritional_info":"145 kcal",
 "photo_data":"\/9j\/4AAQSkZJRgABAQAAAQABAAD\/4Q(...)\/\/Z",
 "categories":["Voorgerecht"]
}

A few observations:

  • “photo_data” seems to be Base64 encoded photo (jpg?). I haven’t tried to decode it yet. Slashes seem to be escaped (“\/”).
  • Paragraphs of the directions are separated by “\n”.
  • Ingredients are separated by “\n”. Again, some characters are escaped by backslashes, such as “\/”
  • The meaning of “photo_hash” is not immediately obvious to me.
  • “source_url” is the URL of the web page  when the recipe was scraped off some website, “image_url” is the URL of the original photo. Slashes are escaped again (“\/”).
  • “photo” seems to be the internal file name of the photo. The same name is used when a recipe is exported in HTML format.
  • When exporting “All Recipes”, there doesn’t seem to be any indication about recipes being favorite. But one can export the Favorite recipes separately from Paprika (option in the Export menu)

I believe that any skilled programmer will be able to write a simple converter for the HTML or “Paprika Recipe Format” to produce whatever format is needed, so Paprika is certainly not a “dead end” for your valuable recipes.

NB: just in case anyone wonders why forward slashes are escaped: read this

Paprika Recipe Manager for iPad, importing data in yaml format

Not about virtual worlds this time… 🙂

I recently bought the Paprika Recipe Manager for my iPad to use in the kitchen. Before, I used a simple web-based database application that retrieved my recipes from a MySQL database. Now I wanted to import all my 1200 recipes into Paprika, including all the photos.

Paprika supports importing recipes in many formats, but as far as I could see, the only format that supports the inclusion of photos is yaml. Some basic instructions are given in the Paprika User Manual, but the description is very brief and lacks some details. Below are my findings from making a simple php program to convert my database into yaml format and import it into Paprika.

  • Photos should be JPG or PNG. Preferred dimensions are 280×280. Other dimensions are accepted, but the photos will be scaled.
  • I encoded the photos successfully in PHP in the following way:
$img = fread(fopen($filename, "r"), filesize($filename));
$base64 = base64_encode($img);
$lines = str_split($base64,76);
  • To improve the readability (and editability) of the file, I broke up the base64 string in multiple lines of 76 characters.
  • Avoid any characters with values above 127 (0x7f). I replaced all dangerous characters into their “nearest” regular ASCII ones by:
 $r = @iconv('UTF-8', 'ASCII//TRANSLIT', $r);
  • The ‘@’ before the “iconv” helps to prevent unwanted warning messages.
  • Don’t start a text line with ‘,’ (comma), ‘[‘ (square bracked) or ‘<‘. I didn’t research this in-depth, but I assume that this confuses the yaml parser.
  • Avoid empty lines in the list of ingredients or the preparation instructions.
  • It seems that Parika first checks the syntax of the full import file, before actually inserting recipes into its database. This saved me a lot of trouble: either all recipes were inserted or none. No half-way breaks that leave you wondering which recipes were inserted and which not. Thank you Paprika developers!
  • Line breaks in the preparation instructions cause paragraph breaks in Paprika, so a single paragraph should be formatted as one long text line.
  • Only very limited space is available for the source field (somewhere around 20 characters? I didn’t check). Long source descriptions are accepted, but only partly visible in Paprika.

Here is an example of accepted imput. Long lines are shortened here by “…”. File extension should be “.yml”. The file should be imported into your iPad by means of iTunes file sharing, then you can select it in Paprika under “Import”. 

- name: Caramel salmon
  servings: 4
  prep_time: 10 min
  cook_time: 10 min
  on_favorites: yes
  categories: [Hoofdgerecht]
  ingredients: |
    1 tbsp vegetable oil
    800 g salmon, with skin, cut into large cubes
    1 red onion, sliced
    3 cloves garlic, sliced
    3 tbsp dark soy sauce
    115 g brown sugar
    3 tbsp fish sauce
    1 tbsp lime juice
  directions: |
    1. Heat the oil in a large frying pan over a high  ...
    2. Reduce the heat to medium and add a little extr ...
    3. Return the salmon to the pan and cook for 1 mi ...
    4. Serve with steamed rice, with a little sauce dri ...
    Serve with steamed rice and cucumber salad
  photo: |
    /9j/4AAQSkZJRgABAQIAHAAcAAD/4QypaHR0cDovL25zLmFkb2Jl...
    YWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJlU3pO...
    ZXRhIHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJyB4OnhtcHRrPSdJ...
    (many more lines)
    cf8AVV/bRXloHL1+20s7obp/RQr3toh2EmNrluQhQ+jWABnGRXnA...
    if/Z

- name: Chocolate cheesecake
  servings: 12
  categories: [Gebak]
  (etc)

Dynamic web textures

The last few days I was struggling with the osSetDynamicTextureURL function of OpenSim. According to http://opensimulator.org/wiki/OsSetDynamicTextureURL the official usage is:

string URLTexture=osSetDynamicTextureURL(dynamicID, 
contentType ,srcURL  , "", refreshRate );

Although not explicitly stated, this suggests that the function returns some texture UUID. It doesn’t, you can’t use it to apply to the side of a prim with llSetTexture.  When looking in the log file, I see:

Returning 439411 bytes of image data for request 
7b654e9c-d76d-4630-8d8b-b1faea805df6

This 7b654e9c-… value is the same as returned by OsSetDynamicTextureURL. So it is a “request UUID” (whatever that is), instead of a texture ID?

Since I really want to have the UUID of the (temporary) texture, I use llGetTexture to get it after loading it. Unfortunately, this turned out to be not fail safe: loading the texture from the web takes some (asynchroneous) processing, so sometimes the texture UUID hasn’t changed yet right after calling the OsSetDynamicTextureURL function. I used the following (not so elegant) trick:

oldtexture = llGetTexture(0);
osSetDynamicTextureURL(dynamicID, contentType,
srcURL , "", refreshRate );
while( (texture = llGetTexture(0)) == oldtexture) 
     llSleep(1.0);

This seems to work quite reliably. Now you can preload various web textures and switch between them must faster than calling OsSetDynamicTextureURL each time.

Profiles and OpenSimulator 0.7.2

After upgrading my Diva OpenSimulator to version 0.7.2 (diva release r16915), I found that avatar profiles did not show anymore. Symptoms: no 2nd and 1st life pictures, no text etc. However, when you view your own, empty profile and click the OK button, the empty profile is actually written to the profile database (checked that with a database viewer). I use a (old?) version of osprofiles.

Resolution: one has to change or override

[Profile]
Module = "BasicProfileModule"

by

[Profile]
Module = "OpenProfileModule"

In my case, the “MyWorld.ini” file contains:

[Profile]
Module = "OpenProfileModule"
ProfileURL = http://yabu.example.com/osprofile/profile.php