def test(self):

        # Start client as admin
        broker = {
            'HOST': 'localhost',
            'PORT': 1883,
            'KEEPALIVE': 60,
            'CLEAN_SESSION': True
        }

        # Start subscribe client

        broker.update(settings.MQTT)
        broker['CLIENT_ID'] = 'test_mqttclient'

        subscribe_client = SubscribeClient(broker, debug=True)
        self.is_connected(subscribe_client)
        self.is_subscribed(subscribe_client)

        # Start test client

        broker.update(settings.MQTT)
        client_id = 'test_mqtt_subscribe_admin'
        username = broker['USERNAME']
        broker['CLIENT_ID'] = client_id

        test_client = SingletonPublishClient()
        # self.is_connected(test_client)

        # clear cache
        cache_clear()

        # retrieve permissions for user u1
        get_permissions(self.u1)
        get_permissions(self.u1)
        get_permissions(self.u1)
        get_permissions(self.u1)
        info = cache_info()
        self.assertEqual(info.hits, 3)
        self.assertEqual(info.misses, 1)
        self.assertEqual(info.currsize, 1)

        # send cache_clear
        # test_client.publish('message', '"cache_clear"')
        test_client.publish_message('cache_clear')

        # process messages
        count = 0
        while info.hits > 0 or count < 10:
            self.loop(test_client, subscribe_client)
            time.sleep(0.1)
            info = cache_info()
            count += 1

        self.assertEqual(info.hits, 0)
        self.assertEqual(info.misses, 0)
        self.assertEqual(info.currsize, 0)

        # wait for disconnect
        subscribe_client.wait()
示例#2
0
    def save(self, *args, **kwargs):

        # creation?
        created = self.pk is None

        # if no value, set default value
        if not self.value:
            self.value = self.equipment.default

        # save to EquipmentItem
        super().save(*args, **kwargs)
        from mqtt.publish import SingletonPublishClient

        # publish to mqtt
        client = SingletonPublishClient()
        client.publish_equipment_item(self)
示例#3
0
    def publish(self, **kwargs):

        # logger.debug('Will publish')

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_call(self.ambulance_call.call)
示例#4
0
    def save(self, *args, **kwargs):

        # creation?
        created = self.pk is None

        # create equipment holder?
        try:
            if created or self.equipmentholder is None:
                self.equipmentholder = EquipmentHolder.objects.create()
        except EquipmentHolder.DoesNotExist:
            self.equipmentholder = EquipmentHolder.objects.create()

        # enforce type hospital
        self.type = LocationType.h.name

        # save to Hospital
        super().save(*args, **kwargs)

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_hospital(self)

        # just created?
        if created:
            # invalidate permissions cache
            from mqtt.cache_clear import mqtt_cache_clear
            mqtt_cache_clear()
def mqtt_cache_clear():

    # call cache_clear locally
    cache_clear()

    # and signal through mqtt
    from mqtt.publish import SingletonPublishClient
    SingletonPublishClient().publish_message('cache_clear')
示例#6
0
def mqtt_cache_clear():

    # call cache_clear locally
    cache_clear()

    if env.bool("DJANGO_ENABLE_MQTT_PUBLISH", default=True):
        # and signal through mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_message('cache_clear')
示例#7
0
    def save(self, *args, **kwargs):

        # creation?
        created = self.pk is None

        # if no value, set default value
        if not self.value:
            self.value = self.equipment.default

        # save to EquipmentItem
        super().save(*args, **kwargs)

        if env.bool("DJANGO_ENABLE_MQTT_PUBLISH", default=True):

            from mqtt.publish import SingletonPublishClient

            # publish to mqtt
            client = SingletonPublishClient()
            client.publish_equipment_item(self)
示例#8
0
    def tearDownClass(cls):

        # disconnect singleton publish client
        SingletonPublishClient().disconnect()

        # os.environ["DJANGO_ENABLE_MQTT_PUBLISH"] = "False"
        # logger.info('Disabling MQTT after testing')

        # call super to shutdown server
        super().tearDownClass()
示例#9
0
    def save(self, *args, **kwargs):

        # save to UserAmbulancePermission
        super().save(*args, **kwargs)

        # invalidate permissions cache
        cache_clear()

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_profile(self.user)
示例#10
0
    def delete(self, *args, **kwargs):

        # delete from UserAmbulancePermission
        super().delete(*args, **kwargs)

        # invalidate permissions cache
        cache_clear()

        # publish to mqtt
        # does not remove because user still exists!
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_profile(self.user)
示例#11
0
    def delete(self, *args, **kwargs):

        # remove from mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().remove_ambulance(self)

        # invalidate permissions cache
        from login.permissions import cache_clear
        cache_clear()

        # delete from Ambulance
        super().delete(*args, **kwargs)
示例#12
0
    def save(self, *args, **kwargs):

        # save to GroupAmbulancePermission
        super().save(*args, **kwargs)

        # invalidate permissions cache
        cache_clear()

        # update all profiles for users in the group
        for user in self.group.user_set.all():
            # publish to mqtt
            from mqtt.publish import SingletonPublishClient
            SingletonPublishClient().publish_profile(user)
示例#13
0
    def delete(self, *args, **kwargs):

        # delete from GroupHospitalPermission
        super().delete(*args, **kwargs)

        # invalidate permissions cache
        cache_clear()

        # update all profiles for users in the group
        for user in self.group.user_set.all():
            # publish to mqtt
            from mqtt.publish import SingletonPublishClient
            SingletonPublishClient().publish_profile(user)
示例#14
0
 def save(self, *args, **kwargs):
     created = self.pk is None
     super().save(*args, **kwargs)
     from mqtt.publish import SingletonPublishClient
     client = SingletonPublishClient()
     client.publish_hospital_equipment(self)
     if created:
         client.publish_hospital_metadata(self.hospital)
示例#15
0
    def delete(self, *args, **kwargs):

        # remove from mqtt
        from mqtt.publish import SingletonPublishClient
        client = SingletonPublishClient()
        client.remove_equipment_item(self)
        client.publish_equipment_metadata(self.equipmentholder)

        # delete from EquipmentItem
        super().delete(*args, **kwargs)
示例#16
0
    def save(self, *args, **kwargs):
        # save to Ambulance
        super().save(*args, **kwargs)

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_ambulance(self)

        # save to AmbulanceUpdate
        data = {
            k: getattr(self, k)
            for k in ('status', 'orientation', 'location',
                      'location_timestamp', 'comment', 'updated_by',
                      'updated_on')
        }
        data['ambulance'] = self
        obj = AmbulanceUpdate(**data)
        obj.save()
示例#17
0
    def save(self, *args, **kwargs):

        # creation?
        created = self.pk is None

        # loaded_values?
        loaded_values = self._loaded_values is not None

        # create equipment holder?
        try:
            if created or self.equipmentholder is None:
                self.equipmentholder = EquipmentHolder.objects.create()
        except EquipmentHolder.DoesNotExist:
            self.equipmentholder = EquipmentHolder.objects.create()

        # has location changed?
        has_moved = False
        if (not loaded_values) or \
                calculate_distance(self._loaded_values['location'], self.location) > stationary_radius:
            has_moved = True

        # calculate orientation only if location has changed and orientation has not changed
        if has_moved and loaded_values and self._loaded_values[
                'orientation'] == self.orientation:
            # TODO: should we allow for a small radius before updating direction?
            self.orientation = calculate_orientation(
                self._loaded_values['location'], self.location)
            logger.debug('< {} - {} = {}'.format(
                self._loaded_values['location'], self.location,
                self.orientation))

        logger.debug('loaded_values: {}'.format(loaded_values))
        logger.debug('_loaded_values: {}'.format(self._loaded_values))
        logger.debug('self.location_client: {}'.format(self.location_client))

        # location_client changed?
        if self.location_client is None:
            location_client_id = None
        else:
            location_client_id = self.location_client.id
        location_client_changed = False
        if loaded_values and location_client_id != self._loaded_values[
                'location_client_id']:
            location_client_changed = True

        logger.debug(
            'location_client_changed: {}'.format(location_client_changed))
        # TODO: Check if client is logged with ambulance if setting location_client

        # if comment, capability, status or location changed
        model_changed = False
        if has_moved or \
                self._loaded_values['status'] != self.status or \
                self._loaded_values['capability'] != self.capability or \
                self._loaded_values['comment'] != self.comment:

            # save to Ambulance
            super().save(*args, **kwargs)

            logger.debug('SAVED')

            # save to AmbulanceUpdate
            data = {
                k: getattr(self, k)
                for k in ('capability', 'status', 'orientation', 'location',
                          'timestamp', 'comment', 'updated_by', 'updated_on')
            }
            data['ambulance'] = self
            obj = AmbulanceUpdate(**data)
            obj.save()

            logger.debug('UPDATE SAVED')

            # model changed
            model_changed = True

        # if identifier changed
        # NOTE: self._loaded_values is NEVER None because has_moved is True
        elif (location_client_changed
              or self._loaded_values['identifier'] != self.identifier):

            # save only to Ambulance
            super().save(*args, **kwargs)

            logger.debug('SAVED')

            # model changed
            model_changed = True

        # Did the model change?
        if model_changed:

            # publish to mqtt
            from mqtt.publish import SingletonPublishClient
            SingletonPublishClient().publish_ambulance(self)

            logger.debug('PUBLISHED ON MQTT')

        # just created?
        if created:
            # invalidate permissions cache
            from login.permissions import cache_clear
            cache_clear()
示例#18
0
    def remove(self):

        # remove topic from mqtt server
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().remove_call(self)
示例#19
0
    def remove(self):

        # remove from mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().remove_call_status(self)
示例#20
0
    def publish(self):

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_call(self.call)
示例#21
0
    def publish(self, **kwargs):

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_call_status(self, **kwargs)
示例#22
0
    def publish(self, **kwargs):

        # publish to mqtt
        from mqtt.publish import SingletonPublishClient
        SingletonPublishClient().publish_ambulance(self, **kwargs)
示例#23
0
 def save(self, *args, **kwargs):
     super().save(*args, **kwargs)
     from mqtt.publish import SingletonPublishClient
     SingletonPublishClient().publish_hospital(self)
示例#24
0
 def delete(self, *args, **kwargs):
     from mqtt.publish import SingletonPublishClient
     client = SingletonPublishClient()
     client.remove_hospital_equipment(self)
     client.publish_hospital_metadata(self.hospital)
     super().delete(*args, **kwargs)
示例#25
0
 def delete(self, *args, **kwargs):
     from mqtt.publish import SingletonPublishClient
     SingletonPublishClient().remove_ambulance(self)
     super().delete(*args, **kwargs)
示例#26
0
    def save(self, *args, **kwargs):

        from ambulance.models import Ambulance
        from hospital.models import Hospital

        # creation?
        created = self.pk is None

        # loaded_values?
        loaded_values = self._loaded_values is not None

        # log
        log = []

        # publication list
        publish_ambulance = set()
        publish_hospital = set()

        # logger.debug('self = {}'.format(self))
        # if loaded_values:
        #     logger.debug('_loaded_values = {}'.format(self._loaded_values))

        # online or reconnect
        if self.status == ClientStatus.O.name or self.status == ClientStatus.R.name:

            # log operation
            log.append({
                'client': self,
                'user': self.user,
                'status': self.status,
                'activity': ClientActivity.HS.name
            })

            if self.status == ClientStatus.R.name and self.ambulance is None:

                try:

                    # retrieve latest ambulance logout
                    latest = ClientLog.objects.filter(
                        status=ClientStatus.D.name,
                        activity=ClientActivity.AO.name).latest('updated_on')

                    identifier = latest.details
                    if identifier is not None:

                        # restore latest ambulance client
                        ambulance = Ambulance.objects.get(
                            identifier=identifier)
                        self.ambulance = ambulance

                except ClientLog.DoesNotExist:
                    pass

            # last ambulance
            if loaded_values and self._loaded_values[
                    'ambulance_id'] is not None:
                last_ambulance = Ambulance.objects.get(
                    id=self._loaded_values['ambulance_id'])
            else:
                last_ambulance = None

            # changed ambulance?
            if last_ambulance != self.ambulance:

                # ambulance logout?
                if last_ambulance is not None:

                    # log ambulance logout operation
                    log.append({
                        'client': self,
                        'user': self.user,
                        'status': ClientStatus.O.name,
                        'activity': ClientActivity.AO.name,
                        'details': last_ambulance.identifier
                    })

                    # publish ambulance
                    publish_ambulance.add(last_ambulance)

                # ambulance login?
                if self.ambulance is not None:

                    # log ambulance login operation
                    log.append({
                        'client': self,
                        'user': self.user,
                        'status': ClientStatus.O.name,
                        'activity': ClientActivity.AI.name,
                        'details': self.ambulance.identifier
                    })

                    # publish ambulance
                    publish_ambulance.add(self.ambulance)

            # last hospital
            if loaded_values and self._loaded_values['hospital_id'] is not None:
                last_hospital = Hospital.objects.get(
                    id=self._loaded_values['hospital_id'])
            else:
                last_hospital = None

            # changed hospital?
            if last_hospital != self.hospital:

                # hospital logout?
                if last_hospital is not None:

                    # log hospital logout operation
                    log.append({
                        'client': self,
                        'user': self.user,
                        'status': ClientStatus.O.name,
                        'activity': ClientActivity.HO.name,
                        'details': last_hospital.name
                    })

                    # publish hospital
                    publish_hospital.add(last_hospital)

                # hospital login?
                if self.hospital is not None:

                    # log hospital login operation
                    log.append({
                        'client': self,
                        'user': self.user,
                        'status': ClientStatus.O.name,
                        'activity': ClientActivity.HI.name,
                        'details': self.hospital.name
                    })

                    # publish hospital
                    publish_hospital.add(self.hospital)

        # offline or disconnected
        elif self.status == ClientStatus.D.name or self.status == ClientStatus.F.name:

            # has ambulance?
            if loaded_values and self._loaded_values[
                    'ambulance_id'] is not None:

                # log ambulance logout activity
                last_ambulance = Ambulance.objects.get(
                    id=self._loaded_values['ambulance_id'])
                log.append({
                    'client': self,
                    'user': self.user,
                    'status': self.status,
                    'activity': ClientActivity.AO.name,
                    'details': last_ambulance.identifier
                })

                if self.status == ClientStatus.F.name and last_ambulance.status != AmbulanceStatus.UK.name:

                    # change status of ambulance to unknown; do not publish yet
                    last_ambulance.status = AmbulanceStatus.UK.name
                    last_ambulance.save(publish=False)

                # publish ambulance
                publish_ambulance.add(last_ambulance)

            if self.ambulance is not None:

                # log warning
                logger.error(
                    "Client.save() called with status '{}' and ambulance '{} not None"
                    .format(self.status, self.ambulance))

                # logout ambulance
                self.ambulance = None

            # has hospital?
            if loaded_values and self._loaded_values['hospital_id'] is not None:

                # log hospital logout activity
                last_hospital = Hospital.objects.get(
                    id=self._loaded_values['hospital_id'])
                log.append({
                    'client': self,
                    'user': self.user,
                    'status': self.status,
                    'activity': ClientActivity.HO.name,
                    'details': last_hospital.name
                })

                # publish hospital
                publish_hospital.add(last_hospital)

            if self.hospital is not None:
                # log warning
                logger.error(
                    "Client.save() called with status '{}' and hospital '{} not None"
                    .format(self.status, self.hospital))

                # logout hospital
                self.hospital = None

            # log operation
            log.append({
                'client': self,
                'user': self.user,
                'status': self.status,
                'activity': ClientActivity.HS.name
            })

        # check permissions
        if self.ambulance is not None or self.hospital is not None:

            permissions = get_permissions(self.user)
            if self.ambulance is not None and not permissions.check_can_write(
                    ambulance=self.ambulance.id):
                raise PermissionDenied(_('Cannot write on ambulance'))

            if self.hospital is not None and not permissions.check_can_write(
                    hospital=self.hospital.id):
                raise PermissionDenied(_('Cannot write on hospital'))

        # call super
        super().save(*args, **kwargs)

        # save logs
        for entry in log:
            # logger.debug(entry)
            ClientLog.objects.create(**entry)

        # publish to mqtt
        # logger.debug('publish_ambulance = {}'.format(publish_ambulance))
        # logger.debug('publish_hospital = {}'.format(publish_hospital))
        from mqtt.publish import SingletonPublishClient

        for ambulance in publish_ambulance:
            SingletonPublishClient().publish_ambulance(ambulance)

        for hospital in publish_hospital:
            SingletonPublishClient().publish_hospital(hospital)
    def test(self):
        # Start client as admin
        broker = {
            'HOST': settings.MQTT['BROKER_TEST_HOST'],
            'PORT': 1883,
            'KEEPALIVE': 60,
            'CLEAN_SESSION': True
        }

        # Start test client

        broker.update(settings.MQTT)
        broker['CLIENT_ID'] = 'test_buffer_1'

        client = MQTTTestClient(broker, check_payload=False, debug=True)
        self.is_connected(client)

        # process messages
        self.loop(client)

        # Access singleton publish client
        publish_client = SingletonPublishClient()

        # disconnect temporarily
        publish_client.client.disconnect()
        self.is_disconnected(publish_client)

        # subscribe to ambulance/+/data
        topic = 'ambulance/{}/data'.format(self.a1.id)
        client.expect(topic)
        self.is_subscribed(client)

        # modify data in ambulance and save should trigger message
        obj = Ambulance.objects.get(id=self.a1.id)
        self.assertEqual(obj.status, AmbulanceStatus.UK.name)
        obj.status = AmbulanceStatus.OS.name
        obj.save()

        # save will trigger failed publish
        publish_client.buffer_lock.acquire()
        self.assertTrue(len(publish_client.buffer) > 0)
        publish_client.buffer_lock.release()

        # reconnect
        publish_client.client.reconnect()
        self.is_connected(publish_client)

        # wait for timer to come alive
        time.sleep(2 * RETRY_TIMER_SECONDS)

        # make sure timer got called
        publish_client.buffer_lock.acquire()
        self.assertTrue(len(publish_client.buffer) == 0)
        publish_client.buffer_lock.release()

        # process messages
        self.loop(client, publish_client)
        client.wait()

        # assert change
        obj = Ambulance.objects.get(id=self.a1.id)
        self.assertEqual(obj.status, AmbulanceStatus.OS.name)
    def test(self):

        # Make sure publish client is looped
        SingletonPublishClient().loop()

        # Start client as admin
        broker = {
            'HOST': 'localhost',
            'PORT': 1883,
            'KEEPALIVE': 60,
            'CLEAN_SESSION': True
        }

        # Start subscribe client

        broker.update(settings.MQTT)
        broker['CLIENT_ID'] = 'test_websocket_test_mqtt_subscribe'

        subscribe_client = SubscribeClient(broker, debug=True)
        self.is_connected(subscribe_client)
        self.is_subscribed(subscribe_client)

        # Start test client over websockets
        broker.update(settings.MQTT)
        client_id = 'test_websocket_mqtt_test_mqtt_subscribe_admin'
        username = broker['USERNAME']

        broker['CLIENT_ID'] = client_id
        broker['PORT'] = 8884

        test_client = MQTTTestClient(broker,
                                     transport='websockets',
                                     tls_set={
                                         'ca_certs': None,
                                         'cert_reqs': ssl.CERT_NONE
                                     },
                                     check_payload=False,
                                     debug=True)
        self.is_connected(test_client)

        # Client handshake
        test_client.publish(
            'user/{}/client/{}/status'.format(username, client_id),
            ClientStatus.O.name)

        # process messages
        self.loop(test_client, subscribe_client)

        # check record
        clnt = Client.objects.get(client_id=client_id)
        self.assertEqual(clnt.status, ClientStatus.O.name)

        # check record log
        obj = ClientLog.objects.get(client=clnt)
        self.assertEqual(obj.status, ClientStatus.O.name)

        # start django client
        django_client = DjangoClient()

        # login as admin
        django_client.login(username=broker['USERNAME'],
                            password=broker['PASSWORD'])

        # handshake ambulance and hospital
        response = django_client.post('/en/api/client/',
                                      content_type='application/json',
                                      data=json.dumps({
                                          'client_id':
                                          client_id,
                                          'status':
                                          ClientStatus.O.name,
                                          'ambulance':
                                          self.a1.id,
                                          'hospital':
                                          self.h1.id
                                      }),
                                      follow=True)
        self.assertEqual(response.status_code, 201)

        # check record
        clnt = Client.objects.get(client_id=client_id)
        self.assertEqual(clnt.status, ClientStatus.O.name)
        self.assertEqual(clnt.ambulance, self.a1)
        self.assertEqual(clnt.hospital, self.h1)

        # Modify ambulance

        # retrieve current ambulance status
        obj = Ambulance.objects.get(id=self.a1.id)
        self.assertEqual(obj.status, AmbulanceStatus.UK.name)

        # publish change
        test_client.publish('user/{}/client/{}/ambulance/{}/data'.format(
            self.u1.username, client_id, self.a1.id),
                            json.dumps({
                                'status': AmbulanceStatus.OS.name,
                            }),
                            qos=0)

        # process messages
        self.loop(test_client, subscribe_client)

        # verify change
        obj = Ambulance.objects.get(id=self.a1.id)
        self.assertEqual(obj.status, AmbulanceStatus.OS.name)

        # Modify hospital

        # retrieve current hospital status
        obj = Hospital.objects.get(id=self.h1.id)
        self.assertEqual(obj.comment, 'no comments')

        test_client.publish('user/{}/client/{}/hospital/{}/data'.format(
            self.u1.username, client_id, self.h1.id),
                            json.dumps({
                                'comment': 'no more comments',
                            }),
                            qos=0)

        # process messages
        self.loop(test_client, subscribe_client)

        # verify change
        obj = Hospital.objects.get(id=self.h1.id)
        self.assertEqual(obj.comment, 'no more comments')

        # Modify hospital equipment

        # retrieve current equipment value
        obj = EquipmentItem.objects.get(
            equipmentholder=self.h1.equipmentholder, equipment=self.e1)
        self.assertEqual(obj.value, 'True')

        test_client.publish(
            'user/{}/client/{}/equipment/{}/item/{}/data'.format(
                self.u1.username, client_id, self.h1.equipmentholder.id,
                self.e1.id),
            json.dumps({
                'value': 'False',
            }),
            qos=0)

        # process messages
        self.loop(test_client, subscribe_client)

        # verify change
        obj = EquipmentItem.objects.get(
            equipmentholder=self.h1.equipmentholder, equipment=self.e1)
        self.assertEqual(obj.value, 'False')

        # Client handshake
        test_client.publish(
            'user/{}/client/{}/status'.format(username, client_id),
            ClientStatus.F.name)

        # process messages
        self.loop(test_client, subscribe_client)

        # wait for disconnect
        test_client.wait()
        subscribe_client.wait()
        django_client.logout()