a method to establish a mosquitto socket with server to receive position updates
            
        :param callable: [optional] callable to process the received positions
        :param block: [optional] boolean to block the main thread when method is called
        :param port: [optional] integer with port to connect to
        :return: None
        
        NOTE:   subscribing without a callable will update the self.positions object
                with any user message

        { 
            'time': 0.0, 
            'location': 'location.id', 
            'id': 'user_id', 
            bayes: {}, 
            svm: None, 
            rf: {} 
        }

        # https://www.internalpositioning.com/server/

def subscribe(self, callable=None, block=False, port=1883):

        '''
            a method to establish a mosquitto socket with server to receive position updates
            
        :param callable: [optional] callable to process the received positions
        :param block: [optional] boolean to block the main thread when method is called
        :param port: [optional] integer with port to connect to
        :return: None
        
        NOTE:   subscribing without a callable will update the self.positions object
                with any user message

        { 
            'time': 0.0, 
            'location': 'location.id', 
            'id': 'user_id', 
            bayes: {}, 
            svm: None, 
            rf: {} 
        }

        # https://www.internalpositioning.com/server/
        '''

        title = '%s.subscribe' % self.__class__.__name__
    
    # validate inputs
        input_fields = {
            'port': port
        }
        for key, value in input_fields.items():
            object_title = '%s(%s=%s)' % (title, key, str(value))
            self.fields.validate(value, '.%s' % key, object_title)
    
    # import dependencies
        import paho.mqtt.client as mqtt

    # define callback on connection event
        def on_connect(client, userdata, flags, rc):

            if rc == 5:
                raise ValueError('MQTT to %s authorization failed.' % self.group_name)

            print("Connected to %s with result code %s" % (self.group_name, rc))

            # Subscribing in on_connect() means that if we lose the connection and
            # reconnect then subscriptions will be renewed.
            client.subscribe("%s/location/#" % self.group_name)

    # define callback on a new message event
        def on_message(client, userdata, msg):

            import json
            user_search = self.user_pattern.findall(msg.topic)
            user_id = user_search[0]
            user_location = json.loads(msg.payload.decode())
            user_location['time'] = user_location['time'] / 1000000000
            user_location['id'] = user_id
            if callable:
                callable(user_location)
            else:
                self.positions[user_id] = { 
                    'location': user_location['location'], 
                    'time': user_location['time']
                }

    # instantiate client and configure methods
        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message
        client.username_pw_set(self.group_name, self.password)
        client.connect_async(self.server_url, port, 60)

    # start blocking listener
        if block:
            client.loop_forever()
    # start listener in separate thread
        else:
            client.loop_start()