def post(self): # confirm that the X-Manual header was specified manual = checkXManual(request) prevId = -1 if 'X-Crop-Id' in request.headers: prevId = request.headers.get('X-Crop-Id') else: abort(400, "Need to specify header 'X-Crop-Id'!") dao = OutgoingManualDAO( defaultConfigPath()) if manual else OutgoingAutonomousDAO( defaultConfigPath()) outgoingIn = outgoing_manual( json=request.get_json()) if manual else outgoing_autonomous( json=request.get_json()) outgoingIn.crop_id = prevId resultingId = dao.upsertClassification(outgoingIn) if resultingId == -1: return { 'message': 'Failed to insert classification into outgoing table' }, 500 response = make_response( jsonify({ 'message': 'success!', 'id': resultingId })) response.headers['X-Class-Id'] = resultingId return response
def test(self): truncateTable('outgoing_autonomous') dao = OutgoingAutonomousDAO(defaultConfigPath()) testIns = outgoing_autonomous() testIns.crop_id = 42 testIns.shape = 'circle' testIns.background_color = 'white' testIns.alphanumeric = 'A' testIns.alphanumeric_color = 'black' resultingId = dao.addClassification(testIns) self.assertNotEqual(resultingId, -1) # should not be able to insert a duplicate record self.assertEqual(dao.addClassification(testIns), -1) self.assertIsNotNone(dao.getClassification(resultingId))
def run(self): # wait until we get our first gps coordinate # remember - the ros_handler code does not insert a gps record # into the table until the gps has a fix haveGps = False print("waiting for gps") while not haveGps and not self._should_shutdown: # check for any entries by just getting all dao = IncomingGpsDAO(defaultConfigPath()) results = dao.getAll() dao.close() if results is None: time.sleep(1) else: haveGps = True # we've got something! print( "Have gps! Using the first coordinate as our ground station. Starting geolocation..." ) # get the coordinates from the first recorded gps measurement # this will be the coordinates we use for the groundstation # in geolocation dao = IncomingGpsDAO(defaultConfigPath()) groundstationGps = dao.getFirst() dao.close() # now we can run stuff geo = targetGeolocation(groundstationGps.lat, groundstationGps.lon) while not self._should_shutdown: # lets deal with manual classifications in the queue dao = OutgoingManualDAO(defaultConfigPath()) classifications = dao.getUnlocatedClassifications() dao.close() if classifications is not None: for classification in classifications: self.processManualGeolocation(geo, classification) # now lets do autonomous dao = OutgoingAutonomousDAO(defaultConfigPath()) classifications = dao.getUnlocatedClassifications() dao.close() if classifications is not None: for classification in classifications: self.processAutonomousGeolocation(geo, classification) time.sleep(1)
def get(self, class_id): # confirm that the X-Manual header was specified manual = checkXManual(request) dao = OutgoingManualDAO( defaultConfigPath()) if manual else OutgoingAutonomousDAO( defaultConfigPath()) result = dao.getClassification(class_id) if result is None: return { 'message': 'Failed to locate classification with id {}'.format(class_id) }, 404 return jsonify(result.toDict())
def put(self, class_id): # confirm that the X-Manual header was specified manual = checkXManual(request) dao = OutgoingManualDAO( defaultConfigPath()) if manual else OutgoingAutonomousDAO( defaultConfigPath()) result = dao.updateClassification(class_id, request.get_json()) if result is None: return { 'message': 'No image with id {} found with a classification to update or your input was invalid (or was there a server error?)' .format(class_id) }, 404 else: return jsonify(result.toDict())
def get(self): # confirm that the X-Manual header was specified manual = checkXManual(request) outgoingList = [] dao = OutgoingManualDAO( defaultConfigPath()) if manual else OutgoingAutonomousDAO( defaultConfigPath()) outgoingList = dao.getAll() if not outgoingList: return {'message': 'Outgoing table is empty!'}, 404 exportable = [ classification.toDict() for classification in outgoingList ] return jsonify(exportable)
def processAutonomousGeolocation(self, geolocator, classification): """ See documentation for processManualGeolocation function. This is the same thing but autonomous. """ dao = CroppedAutonomousDAO(defaultConfigPath()) croppedImg = dao.getImage(classification.crop_id) dao.close() if croppedImg is None: print( "Failed to find cropped image {} for autonomous classification {}!" .format(classification.crop_id, classification.class_id)) return updateDict = self.processGeolocation(geolocator, classification, croppedImg) dao = OutgoingAutonomousDAO(defaultConfigPath()) dao.updateClassification(classification.class_id, updateDict) dao.close()
def delete(self, class_id): # confirm that the X-Manual header was specified manual = checkXManual(request) dao = OutgoingManualDAO( defaultConfigPath()) if manual else OutgoingAutonomousDAO( defaultConfigPath()) if dao.getClassification(class_id) is None: return { 'message': 'Couldnt find classification with id {}'.format(class_id) }, 404 result = dao.removeClassification(class_id) if not result: return { 'message': 'Something went wrong while trying to delete id {} (was it delete by someone else first??)' .format(class_id) }, 500 return {'message': 'success!', 'id': class_id}
def test(self): truncateTable('outgoing_autonomous') dao = OutgoingAutonomousDAO(defaultConfigPath()) # empty table self.assertIsNone(dao.getUnlocatedClassifications()) # populate with two classifications that need geo, one that doesnt testIns = outgoing_manual() testIns.crop_id = 42 testIns.shape = 'circle' testIns.background_color = 'white' testIns.alphanumeric = 'A' testIns.alphanumeric_color = 'black' resultingId = dao.addClassification(testIns) self.assertNotEqual(resultingId, -1) testIns.crop_id = 43 testIns.background_color = 'orange' resultingId2 = dao.addClassification(testIns) self.assertNotEqual(resultingId2, -1) testIns.crop_id = 44 testIns.latitude = 40.111 testIns.longitude = -111.222 resultingId3 = dao.addClassification(testIns) self.assertNotEqual(resultingId3, -1) unlocated = dao.getUnlocatedClassifications() self.assertIsNotNone(unlocated) self.assertEqual(len(unlocated), 2) # the two models in the list should be our first two inserts and have # crop ids 42 and 43 self.assertLess(unlocated[0].crop_id, 44) self.assertLess(unlocated[1].crop_id, 44)
def test(self): truncateTable('incoming_image') truncateTable('cropped_autonomous') truncateTable('outgoing_autonomous') dao = OutgoingAutonomousDAO(defaultConfigPath()) testIns = outgoing_autonomous() testIns.crop_id = 42 testIns.shape = 'circle' testIns.background_color = 'white' testIns.alphanumeric = 'A' testIns.alphanumeric_color = 'black' self.assertNotEqual(dao.addClassification(testIns), -1) dao = CroppedAutonomousDAO(defaultConfigPath()) model = cropped_autonomous() model.image_id = 123 model.time_stamp = 1547453775.2 model.cropped_path = '/im/a/totally/real/cropped/path/i/swear.jpg' model.crop_coordinate_br = "(12, 34)" model.crop_coordinate_tl = "(56, 78)" self.assertNotEqual(dao.addImage(model), -1) dao = IncomingImageDAO(defaultConfigPath()) model = incoming_image() model.time_stamp = 1547453775.2 model.focal_length = 16.0 model.image_path = '/im/a/totally/real/path/i/swear.jpg' model.manual_tap = True model.autonomous_tap = True resultingId = dao.addImage(model) self.assertNotEqual(resultingId, -1) util = UtilDAO(defaultConfigPath()) util.resetAutonomousDB() resultingModel = dao.getImage(resultingId) self.assertIsNotNone(resultingModel) self.assertFalse(resultingModel.autonomous_tap) self.assertTrue(resultingModel.manual_tap) self.assertEqual(resultingModel.image_path, model.image_path) self.assertEqual(resultingModel.focal_length, model.focal_length) dao = CroppedAutonomousDAO(defaultConfigPath()) self.assertEqual(len(dao.getAll()), 0) dao = OutgoingAutonomousDAO(defaultConfigPath()) self.assertEqual(len(dao.getAll()), 0)
def test(self): dao = OutgoingAutonomousDAO(defaultConfigPath()) self.assertIsNotNone(dao) self.assertIsNotNone(dao.conn)
def getClassificationDAO(isManual): if isManual: return OutgoingManualDAO(defaultConfigPath()) else: return OutgoingAutonomousDAO(defaultConfigPath())