def worker_changed_update_routepools(self): with self._manager_mutex: logger.info("Updating all routepools in levelmode for {} origins", len(self._routepool)) if len(self._workers_registered) == 0: logger.info("No registered workers, aborting __worker_changed_update_routepools...") return False any_at_all = False for origin in self._routepool: origin_local_list = [] entry: RoutePoolEntry = self._routepool[origin] if len(entry.queue) > 0: logger.debug("origin {} already has a queue, do not touch...", origin) continue unvisited_stops = self.db_wrapper.stops_from_db_unvisited(self.geofence_helper, origin) if len(self._route) > 0: logger.info("Making a subroute of unvisited stops..") for coord in self._route: coord_location = Location(coord.lat, coord.lng) if coord_location in self._coords_to_be_ignored: logger.info('Already tried this Stop but it failed spinnable test, skip it') continue if coord_location in unvisited_stops: origin_local_list.append(coord_location) if len(origin_local_list) == 0: logger.info("None of the stops in original route was unvisited, recalc a route") new_route = self._local_recalc_subroute(unvisited_stops) for coord in new_route: origin_local_list.append(Location(coord["lat"], coord["lng"])) # subroute is all stops unvisited logger.info("Origin {} has {} unvisited stops for this route", origin, len(origin_local_list)) entry.subroute = origin_local_list # let's clean the queue just to make sure entry.queue.clear() [entry.queue.append(i) for i in origin_local_list] any_at_all = len(origin_local_list) > 0 or any_at_all return any_at_all
def getLessCoords(self, npCoordinates, maxRadius, maxCountPerCircle, useS2: bool=False, S2level: int=15): coordinates = [] for coord in npCoordinates: coordinates.append( (0, Location(coord[0].item(), coord[1].item())) ) clustering_helper = ClusteringHelper(max_radius=maxRadius, max_count_per_circle=maxCountPerCircle, max_timedelta_seconds=0, useS2=useS2, S2level=S2level) clustered_events = clustering_helper.get_clustered(coordinates) coords_cleaned_up = [] for event in clustered_events: coords_cleaned_up.append(event[1]) return coords_cleaned_up
def get_new_coords(init_loc, distance, bearing): """ Given an initial lat/lng, a distance(in kms), and a bearing (degrees), this will calculate the resulting lat/lng coordinates. """ # TODO: check for implementation with gpxdata start = gpxdata.TrackPoint(init_loc.lat, init_loc.lng) destination = start + gpxdata.CourseDistance(bearing, distance) origin = Point(init_loc.lat, init_loc.lng) # start = start + gpxdata.CourseDistance(course, distance) # destination = distance.distance(kilometers=distance).destination( # origin, bearing) # return Location(destination.latitude, destination.longitude) return Location(destination.lat, destination.lon)
def recalc_route(self, max_radius: float, max_coords_within_radius: int, num_procs: int = 1, delete_old_route: bool = False, nofile: bool = False): current_coords = self._coords_unstructured if nofile: routefile = None else: routefile = self._routefile new_route = self.calculate_new_route(current_coords, max_radius, max_coords_within_radius, routefile, delete_old_route, num_procs) with self._manager_mutex: self._route.clear() for coord in new_route: self._route.append(Location(coord["lat"], coord["lng"])) self._current_route_round_coords = self._route.copy() self._current_index_of_route = 0
def get_to_be_encountered(self, geofence_helper, min_time_left_seconds, eligible_mon_ids: Optional[List[int]]): if min_time_left_seconds is None or eligible_mon_ids is None: logger.warning( "DbWrapper::get_to_be_encountered: Not returning any encounters since no time left or " "eligible mon IDs specified") return [] logger.debug("Getting mons to be encountered") query = ( "SELECT latitude, longitude, encounter_id, spawnpoint_id, pokemon_id, " "TIMESTAMPDIFF(SECOND, UTC_TIMESTAMP(), disappear_time) AS expire " "FROM pokemon " "WHERE individual_attack IS NULL AND individual_defense IS NULL AND individual_stamina IS NULL " "AND encounter_id != 0 " "and (disappear_time BETWEEN DATE_ADD(UTC_TIMESTAMP(), INTERVAL %s SECOND) " "and DATE_ADD(UTC_TIMESTAMP(), INTERVAL 60 MINUTE))" "ORDER BY expire ASC") vals = (int(min_time_left_seconds), ) results = self.execute(query, vals, commit=False) next_to_encounter = [] for latitude, longitude, encounter_id, spawnpoint_id, pokemon_id, expire in results: if pokemon_id not in eligible_mon_ids: continue elif latitude is None or longitude is None: logger.warning("lat or lng is none") continue elif geofence_helper and not geofence_helper.is_coord_inside_include_geofence( [latitude, longitude]): logger.debug( "Excluded encounter at {}, {} since the coordinate is not inside the given include fences", str(latitude), str(longitude)) continue next_to_encounter.append( (pokemon_id, Location(latitude, longitude), encounter_id)) # now filter by the order of eligible_mon_ids to_be_encountered = [] i = 0 for mon_prio in eligible_mon_ids: for mon in next_to_encounter: if mon_prio == mon[0]: to_be_encountered.append((i, mon[1], mon[2])) i += 1 return to_be_encountered
def retrieve_next_spawns(self, geofence_helper): """ Retrieve the spawnpoints with their respective unixtimestamp that are due in the next 300 seconds :return: """ current_time_of_day = datetime.now().replace(microsecond=0) log.debug("DbWrapperBase::retrieve_next_spawns called") query = ( "SELECT latitude, longitude, spawndef, calc_endminsec " "FROM `trs_spawn`" "WHERE calc_endminsec IS NOT NULL" ) res = self.execute(query) next_up = [] current_time = time.time() for (latitude, longitude, spawndef, calc_endminsec) in res: if geofence_helper and not geofence_helper.is_coord_inside_include_geofence([latitude, longitude]): continue endminsec_split = calc_endminsec.split(":") minutes = int(endminsec_split[0]) seconds = int(endminsec_split[1]) temp_date = current_time_of_day.replace(minute=minutes, second=seconds) if math.floor(minutes / 10) == 0: temp_date = temp_date + timedelta(hours=1) if temp_date < current_time_of_day: # spawn has already happened, we should've added it in the past, let's move on # TODO: consider crosschecking against current mons... continue spawn_duration_minutes = 60 if spawndef == 15 else 30 timestamp = time.mktime(temp_date.timetuple()) - spawn_duration_minutes * 60 # check if we calculated a time in the past, if so, add an hour to it... timestamp = timestamp + 60 * 60 if timestamp < current_time else timestamp # TODO: consider the following since I am not sure if the prio Q clustering handles stuff properly yet # if timestamp >= current_time + 600: # # let's skip monspawns that are more than 10minutes in the future # continue next_up.append( ( timestamp, Location(latitude, longitude) ) ) return next_up
def getLessCoords(npCoordinates, maxRadius, maxCountPerCircle): coordinates = [] for coord in npCoordinates: coordinates.append((0, Location(coord[0].item(), coord[1].item()))) clustering_helper = ClusteringHelper( max_radius=maxRadius, max_count_per_circle=maxCountPerCircle, max_timedelta_seconds=0) clustered_events = clustering_helper.get_clustered(coordinates) # relations = __getRelationsInRange(coordinates, maxRadius) # summedUp = __sumUpRelations(relations, maxCountPerCircle, maxRadius) coords_cleaned_up = [] for event in clustered_events: coords_cleaned_up.append(event[1]) # print "Done summing up: " + str(summedUp) + " that's just " + str(len(summedUp)) return coords_cleaned_up
def stop_from_db_without_quests(self, geofence_helper, levelmode: bool = False): logger.debug("DbWrapper::stop_from_db_without_quests called") minLat, minLon, maxLat, maxLon = geofence_helper.get_polygon_from_fence( ) query = ( "SELECT pokestop.latitude, pokestop.longitude, '' as visited_by " "FROM pokestop " "LEFT JOIN trs_quest ON pokestop.pokestop_id = trs_quest.GUID " "WHERE (pokestop.latitude >= {} AND pokestop.longitude >= {} " "AND pokestop.latitude <= {} AND pokestop.longitude <= {}) " "AND (DATE(from_unixtime(trs_quest.quest_timestamp,'%Y-%m-%d')) <> CURDATE() " "OR trs_quest.GUID IS NULL)").format(minLat, minLon, maxLat, maxLon) if levelmode: logger.info("Leveling mode, add info about visitation") query = ( "SELECT pokestop.latitude, pokestop.longitude, GROUP_CONCAT(trs_visited.origin) as visited_by " "FROM pokestop " "LEFT JOIN trs_visited ON pokestop.pokestop_id = trs_visited.pokestop_id " "WHERE (pokestop.latitude >= {} AND pokestop.longitude >= {} " "AND pokestop.latitude <= {} AND pokestop.longitude <= {}) GROUP by pokestop.pokestop_id" ).format(minLat, minLon, maxLat, maxLon) res = self.execute(query) list_of_coords: List[Location] = [] visited_by_workers: List[LocationWithVisits] = [] for (latitude, longitude, visited_by) in res: list_of_coords.append(Location(latitude, longitude)) visited_by_workers.append( LocationWithVisits(latitude, longitude, visited_by)) if geofence_helper is not None: geofenced_coords = geofence_helper.get_geofenced_coordinates( list_of_coords) return geofenced_coords, visited_by_workers else: return list_of_coords, visited_by_workers
def _check_coords_before_returning(self, lat, lng, origin): if self.init: logger.debug('Init Mode - coord is valid') return True stop = Location(lat, lng) logger.info('Checking Stop with ID {}', str(stop)) if stop not in self._stoplist: logger.info('Stop is not in stoplist, either no longer in route or spun already...') return False if self._stops_with_visits is None or len(self._stops_with_visits) == 0: logger.info('no visit info so lets go') return True for stop in self._stops_with_visits: if stop.lat == lat and stop.lng == lng and stop.visited_by is not None and origin in stop.visited_by: logger.info("DB says we Already spun stop, ignore it...") return False logger.info('Getting new Stop') return True
def get_to_be_encountered(self, geofence_helper, min_time_left_seconds, eligible_mon_ids): if min_time_left_seconds is None or eligible_mon_ids is None: log.warning("MonocleWrapper::get_to_be_encountered: Not returning any encounters since no time left or " "eligible mon IDs specified") return [] log.debug("Getting mons to be encountered") query = ( "SELECT lat, lon, encounter_id, expire_timestamp, pokemon_id " "FROM sightings " "WHERE atk_iv IS NULL AND def_iv IS NULL AND sta_iv IS NULL AND encounter_id != 0 " "AND expire_timestamp - %s > %s " "ORDER BY sightings.expire_timestamp ASC" ) vals = ( int(min_time_left_seconds), int(time.time()) ) results = self.execute(query, vals, commit=False) next_to_encounter = [] i = 0 for lat, lon, encounter_id, expire_timestamp, pokemon_id in results: if pokemon_id not in eligible_mon_ids: continue elif lat is None or lon is None: log.warning("lat or lng is none") continue elif geofence_helper and not geofence_helper.is_coord_inside_include_geofence([lat, lon]): log.debug("Excluded encounter at %s, %s since the coordinate is not inside the given include fences" % (str(lat), str(lon))) continue next_to_encounter.append( ( i, Location(lat, lon), encounter_id ) ) i += 1 return next_to_encounter
def __worker_changed_update_routepools(self): with self._manager_mutex: logger.debug("Updating all routepools") if len(self._workers_registered) == 0: logger.info("No registered workers, aborting __worker_changed_update_routepools...") return False _, stops_with_visits = self.db_wrapper.stop_from_db_without_quests( self.geofence_helper, True) any_at_all = False for origin in self._routepool: origin_local_list = [] entry: RoutePoolEntry = self._routepool[origin] for coord in stops_with_visits: if origin not in str(coord.visited_by): origin_local_list.append(Location(coord.lat, coord.lng)) # subroute is all stops unvisited entry.subroute = origin_local_list # let's clean the queue just to make sure entry.queue.clear() any_at_all = len(origin_local_list) > 0 or any_at_all return any_at_all
def _main_work_thread(self): current_thread().name = self.id log.debug("Sub called") # first check if pogo is running etc etc self._workMutex.acquire() try: self._initRoutine() except WebsocketWorkerRemovedException: log.error("Timeout during init of worker %s" % str(self.id)) self._stop_worker_event.set() self._workMutex.release() return self._workMutex.release() # loop = asyncio.get_event_loop() # TODO:loop.create_task(self._speed_weather_check_thread()) speedWeatherCheckThread = Thread(name='speedWeatherCheckThread%s' % self.id, target=self._speed_weather_check_thread) speedWeatherCheckThread.daemon = False speedWeatherCheckThread.start() currentLocation = self._last_known_state.get("last_location", None) if currentLocation is None: currentLocation = Location(0.0, 0.0) lastLocation = None while not self._stop_worker_event.isSet(): while MadGlobals.sleep and self._route_manager_nighttime is None: time.sleep(1) __time = time.time() log.debug("Worker: acquiring lock for restart check") self._workMutex.acquire() log.debug("Worker: acquired lock") # Restart pogo every now and then... if self._devicesettings.get("restart_pogo", 80) > 0: # log.debug("main: Current time - lastPogoRestart: %s" % str(curTime - lastPogoRestart)) # if curTime - lastPogoRestart >= (args.restart_pogo * 60): self._locationCount += 1 if self._locationCount > self._devicesettings.get("restart_pogo", 80): log.error("scanned " + str(self._devicesettings.get("restart_pogo", 80)) + " locations, restarting pogo") self._restartPogo() self._locationCount = 0 self._workMutex.release() log.debug("Worker: lock released") # TODO: consider adding runWarningThreadEvent.set() lastLocation = currentLocation self._last_known_state["last_location"] = lastLocation if MadGlobals.sleep: currentLocation = self._route_manager_nighttime.getNextLocation() settings = self._route_manager_nighttime.settings else: currentLocation = self._route_manager_daytime.getNextLocation() settings = self._route_manager_daytime.settings # TODO: set position... needs to be adjust for multidevice posfile = open(self.id+'.position', "w") posfile.write(str(currentLocation.lat)+", "+str(currentLocation.lng)) posfile.close() log.debug("main: next stop: %s" % (str(currentLocation))) log.debug('main: LastLat: %s, LastLng: %s, CurLat: %s, CurLng: %s' % (lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng)) # get the distance from our current position (last) to the next gym (cur) distance = getDistanceOfTwoPointsInMeters(float(lastLocation.lat), float(lastLocation.lng), float(currentLocation.lat), float(currentLocation.lng)) log.info('main: Moving %s meters to the next position' % distance) delayUsed = 0 if MadGlobals.sleep: speed = self._route_manager_nighttime.settings.get("speed", 0) else: speed = self._route_manager_daytime.settings.get("speed", 0) if (speed == 0 or (settings["max_distance"] and 0 < settings["max_distance"] < distance) or (lastLocation.lat == 0.0 and lastLocation.lng == 0.0)): log.info("main: Teleporting...") self._communicator.setLocation(currentLocation.lat, currentLocation.lng, 0) delayUsed = self._devicesettings.get("post_teleport_delay",7) # Test for cooldown / teleported distance TODO: check this block... if self._devicesettings.get("cool_down_sleep",False): if distance > 2500: delayUsed = 30 elif distance > 5000: delayUsed = 45 elif distance > 10000: delayUsed = 60 log.info("Need more sleep after Teleport: %s seconds!" % str(delayUsed)) if 0 < self._devicesettings.get("walk_after_teleport_distance",0) < distance: toWalk = getDistanceOfTwoPointsInMeters(float(currentLocation.lat), float(currentLocation.lng), float(currentLocation.lat) + 0.0001, float(currentLocation.lng) + 0.0001) log.info("Walking a bit: %s" % str(toWalk)) time.sleep(0.3) self._communicator.walkFromTo(currentLocation.lat, currentLocation.lng, currentLocation.lat + 0.0001, currentLocation.lng + 0.0001, 11) log.debug("Walking back") time.sleep(0.3) self._communicator.walkFromTo(currentLocation.lat + 0.0001, currentLocation.lng + 0.0001, currentLocation.lat, currentLocation.lng, 11) log.debug("Done walking") else: log.info("main: Walking...") self._communicator.walkFromTo(lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng, speed) delayUsed = self._devicesettings.get("post_walk_delay",7) log.info("Sleeping %s" % str(delayUsed)) time.sleep(delayUsed) log.debug("main: Acquiring lock") while MadGlobals.sleep: # or not runWarningThreadEvent.isSet(): time.sleep(0.1) log.debug("Worker: acquiring lock") self._workMutex.acquire() log.debug("main: Lock acquired") if not self._takeScreenshot(): self._workMutex.release() log.debug("Worker: Lock released") continue log.debug("Worker: Got screenshot") curTime = time.time() if self._applicationArgs.last_scanned: log.info('main: Set new scannedlocation in Database') self._db_wrapper.set_scanned_location(str(currentLocation.lat), str(currentLocation.lng), str(curTime)) log.info("main: Checking raidcount and copying raidscreen if raids present") countOfRaids = self._pogoWindowManager.readRaidCircles(os.path.join( self._applicationArgs.temp_path, 'screenshot%s.png' % str(self.id)), self.id) if countOfRaids == -1: log.debug("Worker: Count present but no raid shown") log.warning("main: Count present but no raid shown, reopening raidTab") self._reopenRaidTab() # tabOutAndInPogo() log.debug("Done reopening raidtab") if not self._takeScreenshot(): self._workMutex.release() log.debug("Worker: Lock released") continue countOfRaids = self._pogoWindowManager.readRaidCircles(os.path.join( self._applicationArgs.temp_path, 'screenshot%s.png' % str(self.id)), self.id) # elif countOfRaids == 0: # emptycount += 1 # if emptycount > 30: # emptycount = 0 # log.error("Had 30 empty scans, restarting pogo") # restartPogo() # not an elif since we may have gotten a new screenshot.. # detectin weather if self._applicationArgs.weather: log.debug("Worker: Checking weather...") weather = checkWeather(os.path.join(self._applicationArgs.temp_path, 'screenshot%s.png' % str(self.id))) if weather[0]: log.debug('Submit Weather') cell_id = S2Helper.lat_lng_to_cell_id(currentLocation.lat, currentLocation.lng) self._db_wrapper.update_insert_weather(cell_id, weather[1], curTime) else: log.error('Weather could not detected') if countOfRaids > 0: log.debug("Worker: Count of raids >0") log.debug("main: New und old Screenshoot are different - starting OCR") log.debug("main: countOfRaids: %s" % str(countOfRaids)) curTime = time.time() copyFileName = self._applicationArgs.raidscreen_path + '/raidscreen_' + str(curTime) \ + "_" + str(currentLocation.lat) + "_" + str(currentLocation.lng) + "_" \ + str(countOfRaids) + '.png' log.debug('Copying file: ' + copyFileName) log.debug("Worker: Copying file to %s" % str(copyFileName)) copyfile(os.path.join(self._applicationArgs.temp_path, 'screenshot%s.png' % str(self.id)), copyFileName) os.remove(os.path.join(self._applicationArgs.temp_path, 'screenshot%s.png' % str(self.id))) log.debug("main: Releasing lock") self._workMutex.release() log.debug("Worker: Lock released")
def _main_work_thread(self): current_thread().name = self.id log.info("Quests worker starting") _data_err_counter, data_error_counter = 0, 0 firstround = True t_asyncio_loop = Thread(name='mitm_asyncio_' + self.id, target=self.__start_asyncio_loop) t_asyncio_loop.daemon = True t_asyncio_loop.start() clearThread = Thread(name='clearThread%s' % self.id, target=self._clear_thread) clearThread.daemon = True clearThread.start() self.get_screen_size() self._delayadd = int(self._devicesettings.get("vps_delay", 0)) self._work_mutex.acquire() try: self._start_pogo() except WebsocketWorkerRemovedException: log.error("Timeout during init of worker %s" % str(self.id)) self._stop_worker_event.set() self._work_mutex.release() return self._work_mutex.release() self.loop_started.wait() reachedMainMenu = self._checkPogoMainScreen(15, True) if not reachedMainMenu: self._restartPogo() currentLocation = self._last_known_state.get("last_location", None) if currentLocation is None: currentLocation = Location(0.0, 0.0) lastLocation = None while not self._stop_worker_event.isSet(): while MadGlobals.sleep and self._route_manager_nighttime is None: time.sleep(1) log.debug("Worker: acquiring lock for restart check") self._work_mutex.acquire() log.debug("Worker: acquired lock") # check if pogo is topmost and start if necessary try: log.debug( "Calling _start_pogo routine to check if pogo is topmost") self._start_pogo() except WebsocketWorkerRemovedException: log.error("Timeout starting pogo on %s" % str(self.id)) self._stop_worker_event.set() self._work_mutex.release() return log.debug("Checking if we need to restart pogo") # Restart pogo every now and then... if self._devicesettings.get("restart_pogo", 80) > 0: # log.debug("main: Current time - lastPogoRestart: %s" % str(curTime - lastPogoRestart)) # if curTime - lastPogoRestart >= (args.restart_pogo * 60): self._locationCount += 1 if self._locationCount > self._devicesettings.get( "restart_pogo", 80): log.error( "scanned " + str(self._devicesettings.get("restart_pogo", 80)) + " locations, restarting pogo") self._restartPogo() self._locationCount = 0 self._work_mutex.release() log.debug("Worker: lock released") # TODO: consider adding runWarningThreadEvent.set() lastLocation = currentLocation self._last_known_state["last_location"] = lastLocation log.debug("Requesting next location from routemanager") if MadGlobals.sleep and self._route_manager_nighttime is not None: currentLocation = self._route_manager_nighttime.get_next_location( ) settings = self._route_manager_nighttime.settings while self._db_wrapper.check_stop_quest( currentLocation.lat, currentLocation.lng): self._route_manager_nighttime.del_from_route() currentLocation = self._route_manager_nighttime.get_next_location( ) elif MadGlobals.sleep: # skip to top while loop to get to sleep loop continue else: currentLocation = self._route_manager_daytime.get_next_location( ) settings = self._route_manager_daytime.settings while self._db_wrapper.check_stop_quest( currentLocation.lat, currentLocation.lng): self._route_manager_daytime.del_from_route() currentLocation = self._route_manager_daytime.get_next_location( ) self.__update_injection_settings() # TODO: set position... needs to be adjust for multidevice log.debug("Updating .position file") with open(self.id + '.position', 'w') as outfile: outfile.write( str(currentLocation.lat) + ", " + str(currentLocation.lng)) log.debug("main: next stop: %s" % (str(currentLocation))) log.debug( 'main: LastLat: %s, LastLng: %s, CurLat: %s, CurLng: %s' % (lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng)) # get the distance from our current position (last) to the next gym (cur) distance = get_distance_of_two_points_in_meters( float(lastLocation.lat), float(lastLocation.lng), float(currentLocation.lat), float(currentLocation.lng)) log.info('main: Moving %s meters to the next position' % distance) delayUsed = 0 log.debug("Getting time") if MadGlobals.sleep: speed = self._route_manager_nighttime.settings.get("speed", 0) else: speed = self._route_manager_daytime.settings.get("speed", 0) if (speed == 0 or (settings['max_distance'] and 0 < settings['max_distance'] < distance) or (lastLocation.lat == 0.0 and lastLocation.lng == 0.0)): log.info("main: Teleporting...") # TODO: catch exception... try: self._communicator.setLocation(currentLocation.lat, currentLocation.lng, 0) # the time we will take as a starting point to wait for data... curTime = math.floor(time.time()) except WebsocketWorkerRemovedException: log.error("Timeout setting location for %s" % str(self.id)) self._stop_worker_event.set() return delayUsed = self._devicesettings.get('post_teleport_delay', 7) # Test for cooldown / teleported distance TODO: check this block... if firstround: delayUsed = 3 firstround = False else: if distance < 200: delayUsed = 5 elif distance < 500: delayUsed = 15 elif distance < 1000: delayUsed = 30 elif distance > 1000: delayUsed = 80 elif distance > 5000: delayUsed = 200 elif distance > 10000: delayUsed = 400 elif distance > 20000: delayUsed = 800 log.info("Need more sleep after Teleport: %s seconds!" % str(delayUsed)) # curTime = math.floor(time.time()) # the time we will take as a starting point to wait for data... else: log.info("main: Walking...") try: self._communicator.walkFromTo(lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng, speed) # the time we will take as a starting point to wait for data... curTime = math.floor(time.time()) except WebsocketWorkerRemovedException: log.error("Timeout setting location for %s" % str(self.id)) self._stop_worker_event.set() return delayUsed = 0 log.info("Sleeping %s" % str(delayUsed)) time.sleep(float(delayUsed)) if self._applicationArgs.last_scanned: log.info('main: Set new scannedlocation in Database') # self.update_scanned_location(currentLocation.lat, currentLocation.lng, curTime) self.__add_task_to_loop( self.update_scanned_location(currentLocation.lat, currentLocation.lng, curTime)) log.debug("Acquiring lock") self._work_mutex.acquire() log.debug("Processing Stop / Quest...") to = 0 data_received = '-' while self._clear_quest or self._clear_box: time.sleep(1) reachedMainMenu = self._checkPogoMainScreen(15, True) if not reachedMainMenu: self._restartPogo() while not 'Stop' in data_received and int(to) < 3: curTime = time.time() self._open_gym(self._delayadd) data_received, data_error_counter = self.wait_for_data( data_err_counter=_data_err_counter, timestamp=curTime, proto_to_wait_for=104, timeout=25) _data_err_counter = data_error_counter if data_received is not None: if 'Gym' in data_received: log.debug('Clicking GYM') x, y = self._resocalc.get_close_main_button_coords( self )[0], self._resocalc.get_close_main_button_coords( self)[1] self._communicator.click(int(x), int(y)) time.sleep(2) self._turn_map(self._delayadd) if 'Mon' in data_received: time.sleep(2) log.debug('Clicking MON') x, y = self._resocalc.get_leave_mon_coords(self)[ 0], self._resocalc.get_leave_mon_coords(self)[1] self._communicator.click(int(x), int(y)) time.sleep(.5) self._turn_map(self._delayadd) if data_received is None: data_received = '-' to += 1 time.sleep(0.5) to = 0 if 'Stop' in data_received: while not 'Quest' in data_received and int(to) < 3: curTime = time.time() self._spin_wheel(self._delayadd) data_received, data_error_counter = self.wait_for_data( data_err_counter=_data_err_counter, timestamp=curTime, proto_to_wait_for=101, timeout=20) _data_err_counter = data_error_counter if data_received is not None: if 'Box' in data_received: log.error('Box is full ... Next round!') self._close_gym(self._delayadd) to = 3 self._clear_box = True roundcount = 0 break if 'Quest' in data_received: self._close_gym(self._delayadd) self._clear_quest = True break if 'SB' in data_received: log.error('Softban - waiting...') time.sleep(10) to += 1 if to == 3: self._close_gym(self._delayadd) else: data_received = '-' log.error( 'Did not get any data ... Maybe already spinned or softban.' ) to += 1 if to == 3: self._close_gym(self._delayadd) log.debug("Releasing lock") self._work_mutex.release() log.debug("Worker %s done, next iteration" % str(self.id)) t_asyncio_loop.join()
def __init__(self, db_wrapper: DbWrapperBase, dbm: DataManager, area_id: str, coords: List[Location], max_radius: float, max_coords_within_radius: int, path_to_include_geofence: str, path_to_exclude_geofence: str, routefile: str, mode=None, init: bool = False, name: str = "unknown", settings: dict = None, level: bool = False, calctype: str = "optimized", useS2: bool = False, S2level: int = 15, joinqueue = None): self.db_wrapper: DbWrapperBase = db_wrapper self.init: bool = init self.name: str = name self._data_manager = dbm self.useS2: bool = useS2 self.S2level: int = S2level self.area_id = area_id self._coords_unstructured: List[Location] = coords self.geofence_helper: GeofenceHelper = GeofenceHelper( path_to_include_geofence, path_to_exclude_geofence) self._routefile = os.path.join(args.file_path, routefile) self._max_radius: float = max_radius self._max_coords_within_radius: int = max_coords_within_radius self.settings: dict = settings self.mode = mode self._is_started: bool = False self._first_started = False self._current_route_round_coords: List[Location] = [] self._start_calc: bool = False self._positiontyp = {} self._coords_to_be_ignored = set() self._level = level self._calctype = calctype self._overwrite_calculation: bool = False self._stops_not_processed: Dict[Location, int] = {} self._routepool: Dict[str, RoutePoolEntry] = {} self._roundcount: int = 0 self._joinqueue = joinqueue # we want to store the workers using the routemanager self._workers_registered: List[str] = [] self._workers_registered_mutex = RLock() # waiting till routepool is filled up self._workers_fillup_mutex = RLock() self._last_round_prio = {} self._manager_mutex = RLock() self._round_started_time = None self._route: List[Location] = [] if coords is not None: if init: fenced_coords = coords else: fenced_coords = self.geofence_helper.get_geofenced_coordinates( coords) new_coords = getJsonRoute( fenced_coords, max_radius, max_coords_within_radius, routefile, algorithm=calctype) for coord in new_coords: self._route.append(Location(coord["lat"], coord["lng"])) self._current_index_of_route = 0 self._init_mode_rounds = 0 if self.settings is not None: self.delay_after_timestamp_prio = self.settings.get( "delay_after_prio_event", None) self.starve_route = self.settings.get("starve_route", False) else: self.delay_after_timestamp_prio = None self.starve_route = False # initialize priority queue variables self._prio_queue = None self._update_prio_queue_thread = None self._check_routepools_thread = None self._stop_update_thread = Event()
def add_coord_to_be_removed(self, lat: float, lon: float): if lat < -90.0 or lat > 90.0 or lon < -180.0 or lon > 180.0: return with self._manager_mutex: self._coords_to_be_ignored.add(Location(lat, lon))
def add_coord_to_be_removed(self, lat: float, lon: float): if lat < -90.0 or lat > 90.0 or lon < -180.0 or lon > 180.0: return self._manager_mutex.acquire() self._coords_to_be_ignored.add(Location(lat, lon)) self._manager_mutex.release()
def _main_work_thread(self): current_thread().name = self.id log.info("MITM worker starting") _data_err_counter, data_error_counter = 0, 0 # first check if pogo is running etc etc t_mitm_data = Thread(name='mitm_receiver_' + self.id, target=self.start_mitm_receiver, args=(self._received_mapping,)) t_mitm_data.daemon = False t_mitm_data.start() t_asyncio_loop = Thread(name='mitm_asyncio_' + self.id, target=self.__start_asyncio_loop) t_asyncio_loop.daemon = False t_asyncio_loop.start() self._work_mutex.acquire() try: self._start_pogo() except WebsocketWorkerRemovedException: log.error("Timeout during init of worker %s" % str(self.id)) self._stop_worker_event.set() self._work_mutex.release() return self._work_mutex.release() self.loop_started.wait() currentLocation = self._last_known_state.get("last_location", None) if currentLocation is None: currentLocation = Location(0.0, 0.0) lastLocation = None while not self._stop_worker_event.isSet(): while MadGlobals.sleep and self._route_manager_nighttime is None: time.sleep(1) log.debug("Worker: acquiring lock for restart check") self._work_mutex.acquire() log.debug("Worker: acquired lock") # check if pogo is topmost and start if necessary try: log.debug("Calling _start_pogo routine to check if pogo is topmost") self._start_pogo() except WebsocketWorkerRemovedException: log.error("Timeout starting pogo on %s" % str(self.id)) self._stop_worker_event.set() self._work_mutex.release() return log.debug("Checking if we needto restart pogo") # Restart pogo every now and then... if self._devicesettings.get("restart_pogo", 80) > 0: # log.debug("main: Current time - lastPogoRestart: %s" % str(curTime - lastPogoRestart)) # if curTime - lastPogoRestart >= (args.restart_pogo * 60): self._locationCount += 1 if self._locationCount > self._devicesettings.get("restart_pogo", 80): log.error("scanned " + str(self._devicesettings.get("restart_pogo", 80)) + " locations, restarting pogo") self._restartPogo() self._locationCount = 0 self._work_mutex.release() log.debug("Worker: lock released") # TODO: consider adding runWarningThreadEvent.set() lastLocation = currentLocation self._last_known_state["last_location"] = lastLocation log.debug("Requesting next location from routemanager") if MadGlobals.sleep and self._route_manager_nighttime is not None: currentLocation = self._route_manager_nighttime.get_next_location() settings = self._route_manager_nighttime.settings elif MadGlobals.sleep: # skip to top while loop to get to sleep loop continue else: currentLocation = self._route_manager_daytime.get_next_location() settings = self._route_manager_daytime.settings # TODO: set position... needs to be adjust for multidevice log.debug("Updating .position file") with open(self.id + '.position', 'w') as outfile: outfile.write(str(currentLocation.lat)+", "+str(currentLocation.lng)) log.debug("main: next stop: %s" % (str(currentLocation))) log.debug('main: LastLat: %s, LastLng: %s, CurLat: %s, CurLng: %s' % (lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng)) # get the distance from our current position (last) to the next gym (cur) distance = get_distance_of_two_points_in_meters(float(lastLocation.lat), float(lastLocation.lng), float(currentLocation.lat), float(currentLocation.lng)) log.info('main: Moving %s meters to the next position' % distance) delayUsed = 0 log.debug("Getting time") if MadGlobals.sleep: speed = self._route_manager_nighttime.settings.get("speed", 0) else: speed = self._route_manager_daytime.settings.get("speed", 0) if (speed == 0 or (settings['max_distance'] and 0 < settings['max_distance'] < distance) or (lastLocation.lat == 0.0 and lastLocation.lng == 0.0)): log.info("main: Teleporting...") # TODO: catch exception... try: self._communicator.setLocation(currentLocation.lat, currentLocation.lng, 0) curTime = math.floor(time.time()) # the time we will take as a starting point to wait for data... except WebsocketWorkerRemovedException: log.error("Timeout setting location for %s" % str(self.id)) self._stop_worker_event.set() return delayUsed = self._devicesettings.get('post_teleport_delay', 7) # Test for cooldown / teleported distance TODO: check this block... if self._devicesettings.get('cool_down_sleep', False): if distance > 2500: delayUsed = 8 elif distance > 5000: delayUsed = 10 elif distance > 10000: delayUsed = 15 log.info("Need more sleep after Teleport: %s seconds!" % str(delayUsed)) # curTime = math.floor(time.time()) # the time we will take as a starting point to wait for data... if 0 < self._devicesettings.get('walk_after_teleport_distance', 0) < distance: toWalk = get_distance_of_two_points_in_meters(float(currentLocation.lat), float(currentLocation.lng), float(currentLocation.lat) + 0.0001, float(currentLocation.lng) + 0.0001) log.info("Walking a bit: %s" % str(toWalk)) try: time.sleep(0.3) self._communicator.walkFromTo(currentLocation.lat, currentLocation.lng, currentLocation.lat + 0.0001, currentLocation.lng + 0.0001, 11) log.debug("Walking back") time.sleep(0.3) self._communicator.walkFromTo(currentLocation.lat + 0.0001, currentLocation.lng + 0.0001, currentLocation.lat, currentLocation.lng, 11) except WebsocketWorkerRemovedException: log.error("Timeout setting location for %s" % str(self.id)) self._stop_worker_event.set() return log.debug("Done walking") else: log.info("main: Walking...") try: self._communicator.walkFromTo(lastLocation.lat, lastLocation.lng, currentLocation.lat, currentLocation.lng, speed) curTime = math.floor(time.time()) # the time we will take as a starting point to wait for data... except WebsocketWorkerRemovedException: log.error("Timeout setting location for %s" % str(self.id)) self._stop_worker_event.set() return delayUsed = self._devicesettings.get('post_walk_delay', 7) log.info("Sleeping %s" % str(delayUsed)) time.sleep(float(delayUsed)) if self._applicationArgs.last_scanned: log.info('main: Set new scannedlocation in Database') # self.update_scanned_location(currentLocation.lat, currentLocation.lng, curTime) self.__add_task_to_loop(self.update_scanned_location(currentLocation.lat, currentLocation.lng, curTime)) log.debug("Acquiring lock") self._work_mutex.acquire() log.debug("Waiting for data to be received...") data_received, data_error_counter = self.wait_for_data(data_err_counter=_data_err_counter, timestamp=curTime) _data_err_counter = data_error_counter log.debug("Releasing lock") self._work_mutex.release() log.debug("Worker %s done, next iteration" % str(self.id)) t_mitm_data.join() t_asyncio_loop.join()
def __init__(self, db_wrapper: DbWrapperBase, coords: List[Location], max_radius: float, max_coords_within_radius: int, path_to_include_geofence: str, path_to_exclude_geofence: str, routefile: str, mode=None, init: bool = False, name: str = "unknown", settings: dict = None): self.db_wrapper: DbWrapperBase = db_wrapper self.init: bool = init self.name: str = name self._coords_unstructured: List[Location] = coords self.geofence_helper: GeofenceHelper = GeofenceHelper( path_to_include_geofence, path_to_exclude_geofence) self._routefile = os.path.join(args.file_path, routefile) self._max_radius: float = max_radius self._max_coords_within_radius: int = max_coords_within_radius self.settings: dict = settings self.mode = mode self._is_started: bool = False self._first_started = False self._route_queue = Queue() self._start_calc: bool = False self._rounds = {} self._positiontyp = {} self._coords_to_be_ignored = set() # we want to store the workers using the routemanager self._workers_registered: List[WorkerBase] = [] self._workers_registered_mutex = Lock() self._last_round_prio = {} self._manager_mutex = RLock() self._round_started_time = None self._route: List[Location] = [] if coords is not None: if init: fenced_coords = coords else: fenced_coords = self.geofence_helper.get_geofenced_coordinates( coords) new_coords = getJsonRoute(fenced_coords, max_radius, max_coords_within_radius, routefile) for coord in new_coords: self._route.append(Location(coord["lat"], coord["lng"])) self._current_index_of_route = 0 self._init_mode_rounds = 0 if self.settings is not None: self.delay_after_timestamp_prio = self.settings.get( "delay_after_prio_event", None) self.starve_route = self.settings.get("starve_route", False) else: self.delay_after_timestamp_prio = None self.starve_route = False # initialize priority queue variables self._prio_queue = None self._update_prio_queue_thread = None self._stop_update_thread = Event()
def get_next_location(self, origin): logger.debug("get_next_location of {} called", str(self.name)) if not self._is_started: logger.info("Starting routemanager {} in get_next_location", str(self.name)) self._start_routemanager() next_lat, next_lng = 0, 0 if self._start_calc: logger.info("Another process already calculate the new route") return None # first check if a location is available, if not, block until we have one... got_location = False while not got_location and self._is_started and not self.init: logger.debug("{}: Checking if a location is available...", str(self.name)) self._manager_mutex.acquire() got_location = not self._route_queue.empty() or ( self._prio_queue is not None and len(self._prio_queue) > 0) self._manager_mutex.release() if not got_location: logger.debug("{}: No location available yet", str(self.name)) if self._get_coords_after_finish_route() and not self.init: # getting new coords or IV worker time.sleep(1) else: logger.info("Not getting new coords - leaving worker") return None logger.debug( "{}: Location available, acquiring lock and trying to return location", str(self.name)) self._manager_mutex.acquire() # check priority queue for items of priority that are past our time... # if that is not the case, simply increase the index in route and return the location on route # determine whether we move to the next location or the prio queue top's item if (self.delay_after_timestamp_prio is not None and ( (not self._last_round_prio.get(origin, False) or self.starve_route) and self._prio_queue and len(self._prio_queue) > 0 and self._prio_queue[0][0] < time.time())): logger.debug("{}: Priority event", str(self.name)) next_stop = heapq.heappop(self._prio_queue)[1] next_lat = next_stop.lat next_lng = next_stop.lng self._last_round_prio[origin] = True self._positiontyp[origin] = 1 logger.info( "Round of route {} is moving to {}, {} for a priority event", str(self.name), str(next_lat), str(next_lng)) else: logger.debug("{}: Moving on with route", str(self.name)) self._positiontyp[origin] = 0 if len(self._route) == self._route_queue.qsize(): if self._round_started_time is not None: logger.info( "Round of route {} reached the first spot again. It took {}", str(self.name), str(self._get_round_finished_string())) self.add_route_to_origin() self._round_started_time = datetime.now() if len(self._route) == 0: return None logger.info("Round of route {} started at {}", str(self.name), str(self._round_started_time)) elif self._round_started_time is None: self._round_started_time = datetime.now() # continue as usual if self.init and (self._route_queue.empty()): self._init_mode_rounds += 1 if self.init and (self._route_queue.empty()) and \ self._init_mode_rounds >= int(self.settings.get("init_mode_rounds", 1)): # we are done with init, let's calculate a new route logger.warning( "Init of {} done, it took {}, calculating new route...", str(self.name), self._get_round_finished_string()) if self._start_calc: logger.info( "Another process already calculate the new route") self._manager_mutex.release() return None self._start_calc = True self.clear_coords() coords = self._get_coords_post_init() logger.debug( "Setting {} coords to as new points in route of {}", str(len(coords)), str(self.name)) self.add_coords_list(coords) logger.debug("Route of {} is being calculated", str(self.name)) self._recalc_route_workertype() self.init = False self.change_init_mapping(self.name) self._manager_mutex.release() self._start_calc = False logger.debug("Initroute of {} is finished - restart worker", str(self.name)) return None elif (self._route_queue.qsize()) == 1: logger.info('Reaching last coord of route') elif self._route_queue.empty(): # normal queue is empty - prioQ is filled. Try to generate a new Q logger.info("Normal routequeue is empty - try to fill up") if self._get_coords_after_finish_route(): # getting new coords or IV worker self._manager_mutex.release() return self.get_next_location(origin) elif not self._get_coords_after_finish_route(): logger.info("Not getting new coords - leaving worker") self._manager_mutex.release() return None self._manager_mutex.release() # getting new coord next_coord = self._route_queue.get() next_lat = next_coord[0] next_lng = next_coord[1] self._route_queue.task_done() logger.info("{}: Moving on with location {} [{} coords left]", str(self.name), str(next_coord), str(self._route_queue.qsize())) self._last_round_prio[origin] = False logger.debug( "{}: Done grabbing next coord, releasing lock and returning location: {}, {}", str(self.name), str(next_lat), str(next_lng)) self._manager_mutex.release() if self._check_coords_before_returning(next_lat, next_lng): return Location(next_lat, next_lng) else: return self.get_next_location(origin)
def _generate_locations(distance, geofence_helper): results = [] south, east, north, west = geofence_helper.get_polygon_from_fence() corners = [ Location(south, east), Location(south, west), Location(north, east), Location(north, west) ] # get the center center = get_middle_of_coord_list(corners) # get the farthest to the center... farthest_dist = 0 for corner in corners: dist_temp = get_distance_of_two_points_in_meters( center.lat, center.lng, corner.lat, corner.lng) if dist_temp > farthest_dist: farthest_dist = dist_temp # calculate step_limit, round up to reduce risk of losing stuff step_limit = math.ceil(farthest_dist / distance) # This will loop thorugh all the rings in the hex from the centre # moving outwards log.info("Calculating positions for init scan") num_cores = multiprocessing.cpu_count() with multiprocessing.Pool(processes=num_cores) as pool: temp = [ pool.apply(S2Helper._generate_star_locs, args=(center, distance, i)) for i in range(1, step_limit) ] results = [item for sublist in temp for item in sublist] results.append(Location(center.lat, center.lng)) # for ring in range(1, step_limit): # for i in range(0, 6): # # Star_locs will contain the locations of the 6 vertices of # # the current ring (90,150,210,270,330 and 30 degrees from # # origin) to form a star # star_loc = S2Helper.get_new_coords(center, distance * ring, # 90 + 60 * i) # for j in range(0, ring): # # Then from each point on the star, create locations # # towards the next point of star along the edge of the # # current ring # loc = S2Helper.get_new_coords(star_loc, distance * j, 210 + 60 * i) # results.append(loc) log.info("Filtering positions for init scan") # Geofence results. if geofence_helper is not None and geofence_helper.is_enabled(): results = geofence_helper.get_geofenced_coordinates(results) if not results: log.error('No cells regarded as valid for desired scan area. ' 'Check your provided geofences. Aborting.') sys.exit(1) log.info("Ordering location") results = S2Helper.order_location_list_rows(results) return results
def get_next_location(self): log.debug("get_next_location of %s called" % str(self.name)) next_lat, next_lng = 0, 0 # first check if a location is available, if not, block until we have one... got_location = False while not got_location: log.debug("%s: Checking if a location is available..." % str(self.name)) self._manager_mutex.acquire() got_location = self._prio_queue is not None and len(self._prio_queue) > 0 or len(self._route) > 0 self._manager_mutex.release() if not got_location: log.debug("%s: No location available yet" % str(self.name)) time.sleep(0.5) log.debug("%s: Location available, acquiring lock and trying to return location") self._manager_mutex.acquire() # check priority queue for items of priority that are past our time... # if that is not the case, simply increase the index in route and return the location on route # determine whether we move to the next location or the prio queue top's item if (self.delay_after_timestamp_prio is not None and ((not self._last_round_prio or self.starve_route) and len(self._prio_queue) > 0 and self._prio_queue[0][0] < time.time())): log.debug("%s: Priority event" % str(self.name)) next_stop = heapq.heappop(self._prio_queue)[1] next_lat = next_stop.lat next_lng = next_stop.lng self._last_round_prio = True log.info("Round of route %s is moving to %s, %s for a priority event" % (str(self.name), str(next_lat), str(next_lng))) else: log.debug("%s: Moving on with route" % str(self.name)) if self._current_index_of_route == 0: if self._round_started_time is not None: log.info("Round of route %s reached the first spot again. It took %s" % (str(self.name), str(self._get_round_finished_string()))) self._round_started_time = datetime.now() log.info("Round of route %s started at %s" % (str(self.name), str(self._round_started_time))) # continue as usual log.info("Moving on with location %s" % self._route[self._current_index_of_route]) next_lat = self._route[self._current_index_of_route]['lat'] next_lng = self._route[self._current_index_of_route]['lng'] self._current_index_of_route += 1 if self.init and self._current_index_of_route >= len(self._route): # we are done with init, let's calculate a new route log.warning("Init of %s done, it took %s, calculating new route..." % (str(self.name), self._get_round_finished_string())) self._manager_mutex.release() self.clear_coords() coords = self._get_coords_post_init() log.debug("Setting %s coords to as new points in route of %s" % (str(len(coords)), str(self.name))) self.add_coords_list(coords) log.debug("Route of %s is being calculated" % str(self.name)) self.recalc_route(self._max_radius, self._max_coords_within_radius, 1, True) self.init = False return self.get_next_location() elif self._current_index_of_route >= len(self._route): self._current_index_of_route = 0 self._last_round_prio = False log.info("%s done grabbing next coord, releasing lock and returning location: %s, %s" % (str(self.name), str(next_lat), str(next_lng))) self._manager_mutex.release() return Location(next_lat, next_lng)