leaflet maps with websocket/mqtt integration

Leaflet (http://leafletjs.com) is a javascript library for maps. It have lot of options for maps. Let we setup & try this.

You can download and configure directly as given examples, I choose option with yarn.

$ mkdir client

$ cd client

$ yarn add leaflet

Above command create node_modules folder in current directory & download leaflet and add into this.

Then write code html/javascript map code for leaflet map

<link rel="stylesheet" href="node_modules/leaflet/dist/leaflet.css">
 < script src="node_modules/leaflet/dist/leaflet.js" type="text/javascript"></ script>

< script type="text/javascript">

var map = L.map('map').setView([28.7041, 77.1025 ], 12);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y} png', {
 attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
 }).addTo(map);

L.marker([ 28.7041, 77.1025 ]).addTo(map)
 .bindPopup('Marker Here')
 .openPopup();

</ script>

Above code successfully show the map centered at new delhi, india. It also have a marker set with info popup.

This is simple case of map with marker and info popup, But some time we need to show some real time data. Like add marker on fly when new location updated. We may have lot of solutions for achieving this. One good solution to use Web Socket Protocol get/update data.

Let first set our Data Sender. I use MQTT Mosquitto broker & php script for achieving this. MQTT protocol work on pubsub model. So our server php script work as publisher while js application would work as subscriber.

But first we would need MQTT Broker. Mosquitto is recommended broker. on ubuntu ( or other deb based systems ) we need following commands to install mosquitto.

$ sudo apt-get install mosquitto mosquitto-clients

Also create a custom mosquitto config file at /etc/mosquitto/conf.d/mosquitto.conf & put following setting into it.

port 1883
protocol mqtt

listener 9001
protocol websockets

autosave_interval 10
autosave_on_changes false

Above setting setup the mqtt ( for publish ) port to 1883, & 9001 port for subscribe. Restart mosuitto service.

$ service mosquitto restart

We may test subscribe/publish with inbuilt commands

# Test Subscriber
$ mosquitto_sub -h localhost -t test

Here we are subscribing on localhost on topic “test”

# Test Publisher
$ mosquitto_pub -h localhost -t test -m "hello world"

Here we are publishing message “hello world” on broker on localhost on topic “test”

Now we setup php script. We use dependancy solver composer for install script dependencies. You can download composer.phar from https://getcomposer.org.

$ mkdir server

$ cd server

$ php composer.phar init

$ php composer.phar require bluerhinos/phpmqtt dev-master

Above command create vendor folder and install package phpmqtt into it. This is php package for mqtt.

Then create php script for publish mqtt data let called it publish.php & put following code into it.

require("vendor/autoload.php");
 use Bluerhinos\phpMQTT;
 $server = "localhost"; // change if necessary
 $port = 1883; // change if necessary
 $username = ""; // set your username
 $password = ""; // set your password
 $client_id = "mqtt-publisher"; // make sure this is unique for connecting to sever - you could use uniqid()

$coords = [
 [ 28.6442033, 77.1118256, 'Location 1' ],
 [ 28.5501396, 77.1882317, 'Location 2' ],
 [ 28.6359866, 77.2608032, 'Location 3' ],
 [ 28.6805603, 77.1991786, 'Location 4' ]
 ];
 $mqtt = new phpMQTT($server, $port, $client_id);
 if ($mqtt->connect(true, NULL, $username, $password)) {
    for($i=0;$i<count($coords);$i++) {
       $mqtt->publish("map/coordinates", json_encode($coords[$i]), 0);
       sleep(5);
    }
    $mqtt->close();
 } else {
    echo "Time out!\n";
 }

Above script connect to mqtt broker and then some latitude/longtitude after every 5 seconds. Real applications can build their logic for publish data on actual moment.

Now we make changes in our client script to subscribe mqtt, but first install mqtt packge for javascript.

$ cd client

$ yarn add paho-mqtt

Now time to change client script.

<link rel="stylesheet" href="node_modules/leaflet/dist/leaflet.css">http://node_modules/leaflet/dist/leaflet.js
< script src="node_modules/paho-mqtt/paho-mqtt-min.js" type="text/javascript">< /script>

< script type="text/javascript">

var map = L.map('map').setView([28.7041, 77.1025 ], 12);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
 attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
 }).addTo(map);

document.addEventListener('DOMContentLoaded', function() {
   mqtt_init();
}, false);

function mqtt_init() {
    // Create a client instance
    client = new Paho.MQTT.Client('localhost', 9001, "mqtt-spublisher");

   // set callback handlers
   client.onConnectionLost = onConnectionLost;
   client.onMessageArrived = onMessageArrived;

   // connect the client
    client.connect({onSuccess:onConnect});

   // called when the client connects
   function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
      console.log("onConnect");
      client.subscribe("map/coordinates");
   }

   // called when the client loses its connection
   function onConnectionLost(responseObject) {
       if (responseObject.errorCode !== 0) {
          console.log("onConnectionLost:"+responseObject.errorMessage);
       }
    }

    // called when a message arrives
    function onMessageArrived(message) {
       console.log("onMessageArrived:" + message.payloadString);
       msg = JSON.parse(message.payloadString);
       L.marker([msg[0], msg[1] ]).addTo(map)
          .bindPopup(msg[2])
          .openPopup();

    }
 }

< /script>

 

When we publish our serve script, We see marker coming after duration (5 seconds ), which can become effective real time solution for maps.

Full code can be found at https://github.com/kuldeep-k/leaflet-mqtt

 

Composite key type duplicate key check with ZF2 Doctrine

Their are instances when we need to add some composite keys in our DBs. Then we also need a check on application side too. This is also same as duplicate check on multiple fields.

In ZF2, we know about Zend\Validator\Db\RecordExists & Zend\Validator\Db\NoRecordExists combo for duplicate check on database side (Zend DB). Their are also respective relative in doctrine called DoctrineModule\Validator\ObjectExists & DoctrineModule\Validator\NoObjectExists. They do the same job as Zend DB counter part with one caveat.

They do not support multiple fields when work with InputFilters. You can pass array but that gave error "zf2 Provided values count is 1, while expected number of fields to be matched is 2". The solution are using your custom validator.

I tried here to write a Validator Plugin which extends DoctrineModule\Validator\NoObjectExists and have support for multiple fields. See implementation code .


        $inputFilter->add($factory->createInput(array(
            'name' => 'studentId',
            'required' => true,
            'filters' => array(
                array('name' => 'StripTags'),
                array('name' => 'StringTrim'),
            ),
            'validators' => array(
                array(
                    'name' => 'Student\Validate\NoObjectExists',
                    'options' => array(
                        'object_repository' => $this->getObjectManager()->getRepository('Student\Entity\Student'),
                        'fields' => array('studentId', 'class'),
                    )
                )
            ),
        )));
        

Validator Plugin Code are as :


    namespace Student\Validate;

    use DoctrineModule\Validator\NoObjectExists as DoctrineModuleNoObjectExists;

    class NoObjectExists extends DoctrineModuleNoObjectExists
    {
        protected $messageTemplates = array(
            self::ERROR_OBJECT_FOUND    => "An object matching combination of fields was found",
        );

        public function isValid($value, $context = null)
        {
            $valueArray = array(); 
            foreach($this->fields as $name => $val)
            {
                $valueArray[] = $context[$val];
            }    
            $value = $this->cleanSearchValue($valueArray);
            
            $match = $this->objectRepository->findOneBy($value);
            
            if (is_object($match)) {
                $this->error(self::ERROR_OBJECT_FOUND, $value);

                return false;
            }

            return true;
        }
    }
      

Further link can be found at : https://github.com/kuldeep-k/zf2doctrine/blob/master/module/Student/src/Student/Validate/NoObjectExists.php

PHP 5.4 new features

PHP have introduced lot of interesting features in last few major versions. Some are obviously inspired from latest programming trends & from other languages. But these features make php more elegant and promising to code. Now I will discuss some of features in php version 5.4 I liked in following sections.

  • Short Array Syntax
  • Binary Numbers
  • Class::{expr}() and (new foo)->bar()) syntax.
  • Traits
  • Array Dereferencing

Short Array Syntax

This is my personal favorite feature. PHP have long history for define array through php function like this

$single_level = array(1, 2, "a" => "bcd");
$multi_level = array('first' => array(1, 2), 'second' => array(3,4), 'third' => array('3f' => array(5,6), '3s' => array(7,8)));

Not we have short syntax which eliminate the using array keyword using more mainstream operator for this.

$single_level = [1, 2, "a" => "bcd"];
$multi_level = ['first' => [1, 2], 'second' => [3,4], 'third' => ['3f' => [5,6], '3s' => [7,8]]];

Binary Numbers

PHP have support for octal and hexdecimal numbers for long time. But same privilege is not available for binary numbers. functions like decbin & bindec is only deal with string representation for binary numbers. Now we have binary number support they can be defined like.

$bin = 0b11011;

See 0b prefix which define for binary number. We already have prefix 0 and 0x for octal and hexadecimal repectively.

Class::{expr}()

If we need to call dynamic method for a class in earlier versions we something similar code.

class A 
{
    public static function functA()
    {
        echo "call A".PHP_EOL;
    }
    public static function functB()
    {
        echo "call B".PHP_EOL;
    }
}

$vars = array('A, 'B');
foreach($vars as $var)
{
    $c = 'funct'.$var;
    A::$c();
}

Now in 5.4 version instead of variable for method name we can code like

(new foo)->bar())

If we need to call a method for a class in earlier versions we something similar code.

class A 
{
    public $var = 10;
    public function methd()
    {
        echo $this->var.PHP_EOL;
    }
}

$a = new A();
$a->methd();

Now in 5.4 version instead of variable for method name we can code like this

(new A)->methd();

Like previous example this one too eliminate the use of variable for just one method calling.

Traits

I write a separate blog for introduce trait at https://kuldeep15.wordpress.com/2015/03/17/php-traits/

Array De-referencing

PHP provide a way to avoid creating variable when we need to access a particular member of array, specially when we accessing data dirtecly returned from function.

In previous versions :

function foo
{
    return array("a" => "First", "b" => "Second");
} 

$a = foo();
echo $a[1];

Using array de-referencing

function foo
{
    return array("a" => "First", "b" => "Second");
} 

echo foo()[1];

You can also use it for some special cases like below.

$str = "A,B,C,D,E";
echo explode(',',$str)[2];

In further articles I will explore interesting features from 5.5 & 5.6

Basic Ejabberd install/setup on ubuntu (External Script Authentication)

In first article, I discussed the installation and normal chat with users registered internally. Now i am going to discuss the external authentication through a php script.

If you want to authenticate users via your database. their are two alternatives.
1. Using odbc, It have one restriction as its internal database have and that is password must be stored plain. (Latest version may not have this restriction.)
2. Using external authentication script. In this way you can authenticate user via a custom script. Here one good php script can be found there. https://github.com/deceze/ejabberd-extauth-PHP. Now download an extract in some location of your system (not necesarily on apache document root as it will working as cli script ).

Now first create a php script in same folder. I name it auth.php. This file should have similar code suggested at github page. I am updating it using some real query.



#!/usr/bin/php
require 'ejabberd_external_auth.php';
class Auth extends EjabberdExternalAuth {
    protected function authenticate($user, $server, $password) {
        $stmt = $this->db()->prepare("SELECT user_id FROM user WHERE username = ? AND password = ? ");
        $stmt->execute(array($user, password));
        if($stmt->rowCount() >= 0 )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    protected function exists($user, $server) {
        $stmt = $this->db()->prepare("SELECT user_id FROM user WHERE username = ? ");
        $stmt->execute(array($user));
        if($stmt->rowCount() >= 0 )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
$pdo = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'user', 'password');
new Auth($pdo, 'auth.log');

I skipped $server argument in query check as If you need only users for one chat server. If you need to handle multiple servers then you may need to change code to reflect server too in query.

Now comment internal auth_method by

%%{auth_method, internal}.

And uncomment, change the line

{auth_method, external}.
{extauth_program, "/path/to/auth.php"}.

gave executing permission to auth.php by chmod 0755 auth.php.

NOTE – As this script executed by ejabberd user created at time of ejabberd installation. So this script need execute permission for ejabberd. You may add ejabberd to your user’s group and gave group to execute permission or gave other to execute permission. In both case it is advisable to check execute file after login through other user.

Add chat users in your user table. You will also need admin user to add into your DB with same password to run admin console.

Now restart ejabberd. and verify by adding user at you jabber client. if it going failed. Then verify log file var/log/ejabberd.log. If file have error to not connecting. check php script again for any error.

Ejabberd default enabled MUC (multi user chat or several other modules ), So you can verify/use also this functionality too.

That’s all for this article, In next article I will discuss message logging.

CMS usability. A core programmer view

After a long gap i am return to blog. Last time i am here talking about synfony and linux. Now i working on drupal cms for since last six months.
It is always a question in front of a php person if using a cms compared to framework or core programming is good approach.
While cms are good RAD tools. You can make applications in few days/week which will take month to complete using core or even framework.
Cms are also very rich through their plugin system. So  customizaton is easier if using fine plugins.
They have the advance cache management.
But not all things was cms is not right. They are very unflexible to their architecture. Customization is not always easy. Some time small functionality requires big work to done.
They used database for load all content which includes html also. So even small application have big db space.
Caching is just not a feature but a requirement even into development period. This can be a advantage of frameworks which can work without caching in development mode as they use only required db space.

So in case of complex projects it is not always wise decision to use cms. But project have requiring good content management and little customization are better suitable to cms.

Relational v/s Object Sql Model in PHP

Im confusing about using relational or object model for database in programming languages. while relational model is tradional, simpler, fast and easy. But It is very bad practice for frameworks where good coding standards are requirement. Object Model is good in this case but it make developer life more complex. and most of object model also lack of completeness for all sql statements in general. One example is UNION statment which is not an easy in Object Model to implement. and Also performing subquery using OM is also a big challenge.

Let see an example For Sql Query

Relational Model :

$q = “SELECT id, name FROM tbl_test WHERE id=1”;
$query = mysql_query($q);
$row = mysql_fetch_row($query);

Relational Model :(Using Symfony Framework)

$c = new Criteria();

$c->addSelectColumn(TestPeer::ID);
$c->addSelectColumn(TestPeer::NAME);
$c->add(TestPeer::ID, 1);

$RS = TestPeer::doSelectRS($c);
Now you can see the elegantness but complexity of OM.