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()
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)
def publish(self, **kwargs): # logger.debug('Will publish') # publish to mqtt from mqtt.publish import SingletonPublishClient SingletonPublishClient().publish_call(self.ambulance_call.call)
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')
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')
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)
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()
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)
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)
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)
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)
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)
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)
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)
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()
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()
def remove(self): # remove topic from mqtt server from mqtt.publish import SingletonPublishClient SingletonPublishClient().remove_call(self)
def remove(self): # remove from mqtt from mqtt.publish import SingletonPublishClient SingletonPublishClient().remove_call_status(self)
def publish(self): # publish to mqtt from mqtt.publish import SingletonPublishClient SingletonPublishClient().publish_call(self.call)
def publish(self, **kwargs): # publish to mqtt from mqtt.publish import SingletonPublishClient SingletonPublishClient().publish_call_status(self, **kwargs)
def publish(self, **kwargs): # publish to mqtt from mqtt.publish import SingletonPublishClient SingletonPublishClient().publish_ambulance(self, **kwargs)
def save(self, *args, **kwargs): super().save(*args, **kwargs) from mqtt.publish import SingletonPublishClient SingletonPublishClient().publish_hospital(self)
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)
def delete(self, *args, **kwargs): from mqtt.publish import SingletonPublishClient SingletonPublishClient().remove_ambulance(self) super().delete(*args, **kwargs)
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()