Пример #1
0
int main(int argc, char *argv[])
{
	Conf conf;

	for (int i = 1; i < argc; i++)
	{
		string arg = argv[i];
		
		if (arg == "-h")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -h host\n");
				return EXIT_FAILURE;
			}

			conf.host = argv[++i];
		}
		else if (arg == "-u")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -u user\n");
				return EXIT_FAILURE;
			}

			conf.username = argv[++i];
		}
		else if (arg == "-p")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -p password\n");
				return EXIT_FAILURE;
			}

			conf.password = argv[++i];
		}
		else if (arg == "-s")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -s schema\n");
				return EXIT_FAILURE;
			}

			conf.schema = argv[++i];
		}
		else if (arg == "-d")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -d delay\n");
				return EXIT_FAILURE;
			}

			conf.no_rows_sleep = boost::posix_time::time_duration(0, 0, atol(argv[++i]));
		}
		else if (arg == "-i")
		{
			if (i + 1 >= argc || argv[i+1][0] == '-')
			{
				fprintf(stderr, " Usage: -i interval\n");
				return EXIT_FAILURE;
			}

			conf.scan_interval = atoi(argv[++i]);
		}
		else if (arg == "-g")
		{
			conf.display_grid = true;
		}
	}

	try
	{
		printf("Connecting to database...\n");

		driver = get_driver_instance();

		con.reset(driver->connect(conf.host, conf.username, conf.password));
		if ( ! con || con->isClosed())
		{
			printf("Failed.\n");
			return EXIT_FAILURE;
		}

		con->setSchema(conf.schema);

		printf("Connected.\n");

		for (EVER)
		{
			unique_ptr<PreparedStatement> query(con->prepareStatement("SELECT id FROM parking WHERE last_scan <= ? ORDER BY last_scan ASC LIMIT 1"));
			query->setUInt(1, (unsigned int) time(nullptr) - conf.scan_interval);

			unique_ptr<ResultSet> res(query->executeQuery());

			if ( ! res->first())
			{
				printf("No data, skipping.\n");
				boost::this_thread::sleep(conf.no_rows_sleep);
				continue;
			}

			unsigned int parking_id = res->getUInt("id");
			printf("Scanning parking (id %u)\n", parking_id);

			// insert basic parking stats
			unsigned int free_spots = 0;
			query.reset(con->prepareStatement("INSERT INTO stats_parking (parking_id) VALUES(?)")); 
			query->setUInt(1, parking_id);
			query->executeUpdate();
			unsigned int stats_parking_id = get_last_insert_id("stats_parking");
			Crawler crawler(parking_id);

			while (crawler.hasNext())
			{
				unsigned int camera_id = crawler.camera_results->getUInt("id");
				string type = crawler.camera_results->getString("type");
				string address = crawler.camera_results->getString("address");
				double threshold_high = crawler.camera_results->getDouble("threshold_high");
				double threshold_low = crawler.camera_results->getDouble("threshold_low");
				double threshold_scan = crawler.camera_results->getDouble("threshold_scan");
				double scale = crawler.camera_results->getDouble("scale");

				unique_ptr<CameraDriver> camera(CameraDriver::factory(type, address));

				if ( ! camera->isValid())
				{
					printf("    Warning: Failed to retrive image from camera (id %u); skipping\n", camera_id);
					continue;
				}

				Detector detector;
				clock_t start, end;

				start = clock();
				if ( ! detector.loadImage(camera->getImagePath(), threshold_low, threshold_high, scale))
				{
					printf("    Warning: Failed to load image from camera (id %u) into detector; skipping\n", camera_id);
					continue;
				}

				unique_ptr<vector<Spot *>> spots(crawler.loadSpots());

				detector.findFreeSpots(*spots, threshold_scan);
				end = clock();

				#ifdef _DEBUG
					printf("    Info: scanned %u spots in %u microseconds\n", spots->size(), (end - start) * 1000 / CLOCKS_PER_SEC);
				#endif

				unsigned int to_update = 0;
				unsigned int camera_free_spots = 0;
				vector<int> update_to_free_ids, update_to_occupied_ids;
				stringstream insert_spot_stats;

				// insert camera and spots stats
				query.reset(con->prepareStatement("INSERT INTO stats_camera (camera_id, stats_parking_id) VALUES(?, ?)")); 
				query->setUInt(1, camera_id);
				query->setUInt(2, stats_parking_id);
				query->executeUpdate();
				unsigned int stats_camera_id = get_last_insert_id("stats_camera");

				insert_spot_stats << "INSERT INTO stats_spot (spot_id, stats_camera_id, status) VALUES ";

				for (size_t i = 0, l = spots->size(); i < l; i++)
				{
					Spot &spot = *(*spots)[i];
					if (spot.status != spot.original_status)
					{
						to_update++;

						switch (spot.status)
						{
						case Free:
							update_to_free_ids.push_back(spot.id);
							break;
						case Occupied:
							update_to_occupied_ids.push_back(spot.id);
							break;
						}
					}

					insert_spot_stats << "(" << spot.id << "," << stats_camera_id << ",";
					switch (spot.status)
					{
					case Free:
						free_spots++;
						camera_free_spots++;
						insert_spot_stats << "'free'),";
						break;
					case Occupied:
						insert_spot_stats << "'occupied'),";
						break;
					case Blocked:
						insert_spot_stats << "'blocked'),";
						break;
					}
				}


				// insert spots stats
				if (spots->size() > 0)
				{
					string insert_query = insert_spot_stats.str();
					query.reset(con->prepareStatement(insert_query.substr(0, insert_query.length() - 1)));
					query->executeUpdate();
				}

				// update camera stats
				query.reset(con->prepareStatement("UPDATE stats_camera SET free_spots = ? WHERE id = ?"));
				query->setUInt(1, camera_free_spots);
				query->setUInt(2, stats_camera_id);
				query->executeUpdate();

				#ifdef _DEBUG
					printf("    Info: updating %i spots\n", to_update);
				#endif

				if (conf.display_grid)
				{
					detector.displayGrid(*spots);
					boost::this_thread::sleep(conf.no_rows_sleep);
				}

				size_t lf = update_to_free_ids.size();
				size_t lo = update_to_occupied_ids.size();

				if (lf > 0)
				{
					stringstream update_to_free;

					update_to_free << "UPDATE spot SET status = 1 WHERE id IN (";
					
					lf -= 1;
					for (size_t i = 0; i < lf; i++)
					{
						update_to_free << update_to_free_ids[i] << ",";
					}

					update_to_free << update_to_free_ids[lf] << ")";

					query.reset(con->prepareStatement(update_to_free.str()));
					query->executeUpdate();
				}

				if (lo > 0)
				{
					stringstream update_to_occupied;
					
					update_to_occupied << "UPDATE spot SET status = 2 WHERE id IN (";

					lo -= 1;
					for (size_t i = 0; i < lo; i++)
					{
						update_to_occupied << update_to_occupied_ids[i] << ",";
					}

					update_to_occupied << update_to_occupied_ids[lo] << ")";
					
					query.reset(con->prepareStatement(update_to_occupied.str()));
					query->executeUpdate();
				}

				for (size_t i = 0, l = spots->size(); i < l; i++)
				{
					delete spots->at(i);
				}

			}

			query.reset(con->prepareStatement("UPDATE parking SET last_scan = ? WHERE id = ?"));
			query->setUInt(1, (unsigned int) time(nullptr));
			query->setUInt(2, parking_id);
			query->executeUpdate();

			// update parkign stats
			query.reset(con->prepareStatement("UPDATE stats_parking SET free_spots = ? WHERE id = ?"));
			query->setUInt(1, free_spots);
			query->setUInt(2, stats_parking_id);
			query->executeUpdate();
		}
	}
	catch (SQLException &e)
	{
		printf("Error: SQLException in %s\n%s\n(MySQL error code: %i, SQLState: %s)\n",
				__FILE_SHORT__, e.what(), e.getErrorCode(), e.getSQLState().c_str());
	}
	catch (exception &e)
	{
		printf("Error: Exception in %s\n%s\n",
				__FILE_SHORT__,  e.what());
	}
	catch (...)
	{
		printf("Error: Unknown exception in %s\n",
				__FILE_SHORT__);
	}

	system("pause");
	return EXIT_SUCCESS;
}