def on_ambulance(self, clnt, userdata, msg): try: logger.debug("on_ambulance: msg = '{}'".format( msg.topic, msg.payload)) # parse topic user, client, data, ambulance_id = self.parse_topic(msg, 4) except Exception as e: logger.debug("on_ambulance: ParseException '{}'".format(e)) return try: # retrieve ambulance logger.debug('ambulance_id = {}'.format(ambulance_id)) ambulance = Ambulance.objects.get(id=ambulance_id) except Ambulance.DoesNotExist: # send error message to user self.send_error_message( user, client, msg.topic, msg.payload, "Ambulance with id '{}' does not exist".format(ambulance_id)) return except Exception as e: # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, "Exception: '{}'".format(e)) return try: logger.debug("on_ambulance: ambulance = '{}', data = '{}'".format( ambulance, data)) # updates must match client if client.ambulance != ambulance: # send error message to user self.send_error_message( user, client, msg.topic, msg.payload, "Client '{}' is not currently authorized to update ambulance '{}'" .format(client.client_id, ambulance.identifier)) return is_valid = False if isinstance(data, (list, tuple)): # update ambulances in bulk serializer = AmbulanceUpdateSerializer(data=data, many=True, partial=True) if serializer.is_valid(): # save to database serializer.save(ambulance=ambulance, updated_by=user) is_valid = True else: # update ambulance serializer = AmbulanceSerializer(ambulance, data=data, partial=True) if serializer.is_valid(): # save to database serializer.save(updated_by=user) is_valid = True if not is_valid: logger.debug('on_ambulance: INVALID serializer') # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, serializer.errors) except Exception as e: logger.debug('on_ambulance: EXCEPTION') # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, "Exception '{}'".format(e)) logger.debug('on_ambulance: DONE')
def on_ambulance(self, clnt, userdata, msg): try: logger.debug("on_ambulance: msg = '{}'".format( msg.topic, msg.payload)) # parse topic user, client, data, ambulance_id = self.parse_topic(msg, 4) except Exception as e: logger.debug("on_ambulance: ParseException '{}'".format(e)) return try: # retrieve ambulance logger.debug('ambulance_id = {}'.format(ambulance_id)) ambulance = Ambulance.objects.get(id=ambulance_id) except Ambulance.DoesNotExist: # send error message to user self.send_error_message( user, client, msg.topic, msg.payload, "Ambulance with id '{}' does not exist".format(ambulance_id)) return except Exception as e: # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, "Exception: '{}'".format(e)) return try: logger.debug("on_ambulance: ambulance = '{}', data = '{}'".format( ambulance, data)) is_valid = False if isinstance(data, (list, tuple)): # bulk updates must match location_client if ambulance.location_client is None or ambulance.location_client.client_id != client.client_id: # send error message to user self.send_error_message( user, client, msg.topic, msg.payload, "Client '{}' is not currently authorized to update ambulance '{}'" .format(client.client_id, ambulance.identifier)) return # update ambulances in bulk serializer = AmbulanceUpdateSerializer(data=data, many=True, partial=True) if serializer.is_valid(): # save to database serializer.save(ambulance=ambulance, updated_by=user) is_valid = True else: # update ambulance serializer = AmbulanceSerializer(ambulance, data=data, partial=True) if serializer.is_valid(): try: # wrap in atomic in case of errors with transaction.atomic(): # current location client old_location_client = ambulance.location_client # save to database serializer.save(updated_by=user) is_valid = True # retrieve location client new_location_client = Ambulance.objects.get( id=ambulance_id).location_client # logger.debug("old_location_client: {}".format(old_location_client)) # logger.debug("new_location_client: {}".format(new_location_client)) # change in location client? if old_location_client != new_location_client: # logger.debug("location_client changed from '{}' to {}".format(old_location_client, # new_location_client)) # log out old client if old_location_client: client_ambulance = old_location_client.ambulance if client_ambulance: details = client_ambulance.identifier else: details = 'None' log = ClientLog( client=old_location_client, status=old_location_client.status, activity=ClientActivity.TL.name, details=details) log.save() # log in new client if new_location_client: client_ambulance = new_location_client.ambulance if client_ambulance: details = client_ambulance.identifier else: details = 'None' log = ClientLog( client=new_location_client, status=new_location_client.status, activity=ClientActivity.SL.name, details=details) log.save() # otherwise must match location_client elif ambulance.location_client is None or ambulance.location_client.client_id != client.client_id: # raise error to rollback transaction raise ClientException() except ClientException: # send error message to user self.send_error_message( user, client, msg.topic, msg.payload, "Client '{}' is not currently authorized to update ambulance '{}'" .format(client.client_id, ambulance.identifier)) if not is_valid: logger.debug('on_ambulance: INVALID serializer') # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, serializer.errors) except Exception as e: logger.debug('on_ambulance: serializer EXCEPTION') # send error message to user self.send_error_message(user, client, msg.topic, msg.payload, e) logger.debug('on_ambulance: DONE')
def test(self): # Bulk update ambulance a1 a = self.a1 user = self.u1 location0 = {'latitude': -3., 'longitude': 6.} location = {'latitude': -2., 'longitude': 7.} orientation = calculate_orientation(dict2point(location0), dict2point(location)) data = [{ 'status': AmbulanceStatus.AH.name, 'location': location0, }, { 'location': location, 'timestamp': timezone.now() }, { 'status': AmbulanceStatus.OS.name }] serializer = AmbulanceUpdateSerializer(data=data, many=True, partial=True) serializer.is_valid(raise_exception=True) serializer.save(ambulance=Ambulance.objects.get(id=a.id), updated_by=user) # test AmbulanceUpdateSerializer queryset = AmbulanceUpdate.objects.filter(ambulance=a) answer1 = [] for u in queryset: serializer = AmbulanceUpdateSerializer(u) result = { 'id': u.id, 'ambulance_id': u.ambulance.id, 'ambulance_identifier': u.ambulance.identifier, 'comment': u.comment, 'capability': u.capability, 'status': u.status, 'orientation': u.orientation, 'location': point2str(u.location), 'timestamp': date2iso(u.timestamp), 'updated_by_username': u.updated_by.username, 'updated_on': date2iso(u.updated_on) } answer1.append(serializer.data) self.assertDictEqual(serializer.data, result) # make sure last update is reflected in ambulance a = Ambulance.objects.get(id=a.id) serializer = AmbulanceSerializer(a) self.assertEqual(math.fabs(orientation - a.orientation) < 1e-4, True) orientation = a.orientation result = { 'id': a.id, 'identifier': a.identifier, 'comment': a.comment, 'capability': a.capability, 'status': AmbulanceStatus.OS.name, 'orientation': orientation, 'location': point2str(location), 'timestamp': date2iso(a.timestamp), 'client_id': None, 'updated_by': a.updated_by.id, 'updated_on': date2iso(a.updated_on) } self.assertDictEqual(serializer.data, result) # Bulk update ambulance a2 a = self.a3 user = self.u3 data = [{ 'status': AmbulanceStatus.AH.name, 'location': location0 }, { 'status': AmbulanceStatus.OS.name }, { 'location': location, 'timestamp': timezone.now() }] serializer = AmbulanceUpdateSerializer(data=data, many=True, partial=True) serializer.is_valid(raise_exception=True) serializer.save(ambulance=Ambulance.objects.get(id=a.id), updated_by=user) # test AmbulanceUpdateSerializer queryset = AmbulanceUpdate.objects.filter(ambulance=a) answer3 = [] for u in queryset: serializer = AmbulanceUpdateSerializer(u) result = { 'id': u.id, 'ambulance_id': a.id, 'ambulance_identifier': a.identifier, 'comment': u.comment, 'capability': u.capability, 'status': u.status, 'orientation': u.orientation, 'location': point2str(u.location), 'timestamp': date2iso(u.timestamp), 'updated_by_username': u.updated_by.username, 'updated_on': date2iso(u.updated_on) } answer3.append(serializer.data) self.assertDictEqual(serializer.data, result) # make sure last update is reflected in ambulance a = Ambulance.objects.get(id=a.id) serializer = AmbulanceSerializer(a) self.assertEqual(math.fabs(orientation - a.orientation) < 1e-4, True) orientation = a.orientation result = { 'id': a.id, 'identifier': a.identifier, 'comment': a.comment, 'capability': a.capability, 'status': AmbulanceStatus.OS.name, 'orientation': orientation, 'location': point2str(location), 'timestamp': date2iso(a.timestamp), 'client_id': None, 'updated_by': a.updated_by.id, 'updated_on': date2iso(a.updated_on) } self.assertDictEqual(serializer.data, result) # Test api # instantiate client client = Client() # login as admin client.login(username=settings.MQTT['USERNAME'], password=settings.MQTT['PASSWORD']) # retrieve ambulances updates response = client.get('/en/api/ambulance/{}/updates/'.format( self.a1.id), follow=True) self.assertEqual(response.status_code, 200) result = JSONParser().parse(BytesIO(response.content)) self.assertCountEqual(result, answer1) self.assertEqual(len(result), 4) # retrieve ambulances updates response = client.get('/en/api/ambulance/{}/updates/'.format( self.a3.id), follow=True) self.assertEqual(response.status_code, 200) result = JSONParser().parse(BytesIO(response.content)) self.assertCountEqual(result, answer3) self.assertEqual(len(result), 4) # logout client.logout() # login as testuser1 client.login(username='******', password='******') # retrieve ambulances response = client.get('/en/api/ambulance/{}/updates/'.format( self.a1.id), follow=True) self.assertEqual(response.status_code, 404) # retrieve ambulances response = client.get('/en/api/ambulance/{}/updates/'.format( self.a3.id), follow=True) self.assertEqual(response.status_code, 404) # logout client.logout() # login as testuser2 client.login(username='******', password='******') # retrieve ambulances response = client.get('/en/api/ambulance/{}/updates/'.format( self.a1.id), follow=True) self.assertEqual(response.status_code, 404) # retrieve ambulances updates response = client.get('/en/api/ambulance/{}/updates/'.format( self.a3.id), follow=True) self.assertEqual(response.status_code, 200) result = JSONParser().parse(BytesIO(response.content)) self.assertCountEqual(result, answer3) self.assertEqual(len(result), 4) # logout client.logout()