mirror of
				https://github.com/liberatedsystems/Sideband_CE.git
				synced 2024-09-03 04:13:27 +02:00 
			
		
		
		
	Implemented background telemetry
This commit is contained in:
		
							parent
							
								
									ecf13e0041
								
							
						
					
					
						commit
						19cacd0e86
					
				| @ -10,7 +10,7 @@ source.exclude_patterns = app_storage/*,venv/*,Makefile,./Makefil*,requirements, | ||||
| 
 | ||||
| version.regex = __version__ = ['"](.*)['"] | ||||
| version.filename = %(source.dir)s/main.py | ||||
| android.numeric_version = 20231114 | ||||
| android.numeric_version = 20231203 | ||||
| 
 | ||||
| # Cryptography recipe is currently broken, using RNS-internal crypto for now | ||||
| requirements = kivy==2.2.1,libbz2,pillow,qrcode==7.3.1,usb4a,usbserial4a | ||||
| @ -25,7 +25,8 @@ android.presplash_color = #00000000 | ||||
| orientation = portrait | ||||
| fullscreen = 0 | ||||
| 
 | ||||
| android.permissions = INTERNET,POST_NOTIFICATIONS,WAKE_LOCK,FOREGROUND_SERVICE,CHANGE_WIFI_MULTICAST_STATE,BLUETOOTH_CONNECT,ACCESS_NETWORK_STATE,ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION,MANAGE_EXTERNAL_STORAGE | ||||
| android.permissions = INTERNET,POST_NOTIFICATIONS,WAKE_LOCK,FOREGROUND_SERVICE,CHANGE_WIFI_MULTICAST_STATE,BLUETOOTH_CONNECT,ACCESS_NETWORK_STATE,ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION,MANAGE_EXTERNAL_STORAGE,ACCESS_BACKGROUND_LOCATION | ||||
| 
 | ||||
| android.api = 30 | ||||
| android.minapi = 24 | ||||
| android.ndk = 25b | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| __debug_build__ = False | ||||
| __disable_shaders__ = False | ||||
| __version__ = "0.7.6" | ||||
| __version__ = "0.7.7" | ||||
| __variant__ = "beta" | ||||
| 
 | ||||
| import sys | ||||
|  | ||||
| @ -31,7 +31,6 @@ if RNS.vendor.platformutils.get_platform() == "android": | ||||
|     from android import python_act | ||||
|     android_api_version = autoclass('android.os.Build$VERSION').SDK_INT | ||||
|              | ||||
|     Context = autoclass('android.content.Context') | ||||
|     Intent = autoclass('android.content.Intent') | ||||
|     BitmapFactory = autoclass('android.graphics.BitmapFactory') | ||||
|     Icon = autoclass("android.graphics.drawable.Icon") | ||||
| @ -60,6 +59,7 @@ class SidebandService(): | ||||
|         0x0483: [0x5740], # ST CDC | ||||
|         0x2E8A: [0x0005, 0x000A], # Raspberry Pi Pico | ||||
|     } | ||||
|      | ||||
|     def android_notification(self, title="", content="", ticker="", group=None, context_id=None): | ||||
|         if android_api_version < 26: | ||||
|             return | ||||
| @ -121,12 +121,78 @@ class SidebandService(): | ||||
|             built_notification = notification.build() | ||||
|             self.notification_service.notify(0, built_notification) | ||||
| 
 | ||||
|     def check_permission(self, permission): | ||||
|         if RNS.vendor.platformutils.is_android(): | ||||
|             try: | ||||
|                 result = self.android_service.checkSelfPermission("android.permission."+permission) | ||||
|                 if result == 0: | ||||
|                     return True | ||||
| 
 | ||||
|             except Exception as e: | ||||
|                 RNS.log("Error while checking permission: "+str(e), RNS.LOG_ERROR) | ||||
|              | ||||
|             return False | ||||
|          | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|     def background_location_allowed(self): | ||||
|         if not RNS.vendor.platformutils.is_android(): | ||||
|             return False | ||||
| 
 | ||||
|         perms = ["ACCESS_FINE_LOCATION","ACCESS_COARSE_LOCATION","ACCESS_BACKGROUND_LOCATION"] | ||||
|         for perm in perms: | ||||
|             if not self.check_permission(perm): | ||||
|                 return False | ||||
| 
 | ||||
|         return True | ||||
| 
 | ||||
|     def android_location_callback(self, **kwargs): | ||||
|         self._raw_gps = kwargs | ||||
|         self._last_gps_update = time.time() | ||||
| 
 | ||||
|     def should_update_location(self): | ||||
|         if self.sideband.config["telemetry_enabled"] and self.sideband.config["telemetry_s_location"] and self.background_location_allowed(): | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|     def update_location_provider(self): | ||||
|         if RNS.vendor.platformutils.is_android(): | ||||
|             if self.should_update_location(): | ||||
|                 if not self._gps_started: | ||||
|                     RNS.log("Starting service location provider", RNS.LOG_DEBUG) | ||||
|                      | ||||
|                     if self.gps == None: | ||||
|                         from plyer import gps | ||||
|                         self.gps = gps | ||||
| 
 | ||||
|                     self.gps.configure(on_location=self.android_location_callback) | ||||
|                     self.gps.start(minTime=self._gps_stale_time, minDistance=self._gps_min_distance) | ||||
|                     self._gps_started = True | ||||
| 
 | ||||
|             else: | ||||
|                 if self._gps_started: | ||||
|                     RNS.log("Stopping service location provider", RNS.LOG_DEBUG) | ||||
|                     if self.gps != None: | ||||
|                         self.gps.stop() | ||||
|                     self._gps_started = False | ||||
|                     self._raw_gps = None | ||||
| 
 | ||||
|     def get_location(self): | ||||
|         return self._last_gps_update, self._raw_gps | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '') | ||||
|         self.app_dir = self.argument | ||||
|         self.multicast_lock = None | ||||
|         self.wake_lock = None | ||||
|         self.should_run = False | ||||
|         self.gps = None | ||||
|         self._gps_started = False | ||||
|         self._gps_stale_time = 299 | ||||
|         self._gps_min_distance = 25 | ||||
|         self._raw_gps = None | ||||
| 
 | ||||
|         self.android_service = None | ||||
|         self.app_context = None | ||||
| @ -149,9 +215,7 @@ class SidebandService(): | ||||
| 
 | ||||
|             self.discover_usb_devices() | ||||
|          | ||||
|         self.sideband = SidebandCore(self, is_service=True, android_app_dir=self.app_dir, verbose=__debug_build__) | ||||
|         self.sideband.service_context = self.android_service | ||||
|         self.sideband.owner_service = self | ||||
|         self.sideband = SidebandCore(self, is_service=True, android_app_dir=self.app_dir, verbose=__debug_build__, owner_service=self, service_context=self.android_service) | ||||
| 
 | ||||
|         if self.sideband.config["debug"]: | ||||
|             Logger.setLevel(LOG_LEVELS["debug"]) | ||||
| @ -161,6 +225,7 @@ class SidebandService(): | ||||
|          | ||||
|         if RNS.vendor.platformutils.is_android(): | ||||
|             RNS.log("Discovered USB devices: "+str(self.usb_devices), RNS.LOG_EXTREME) | ||||
|             self.update_location_provider() | ||||
| 
 | ||||
| 
 | ||||
|     def discover_usb_devices(self): | ||||
|  | ||||
| @ -90,6 +90,7 @@ class SidebandCore(): | ||||
|     PERIODIC_JOBS_INTERVAL = 60 | ||||
|     PERIODIC_SYNC_RETRY = 360 | ||||
|     TELEMETRY_INTERVAL = 60 | ||||
|     SERVICE_TELEMETRY_INTERVAL = 300 | ||||
| 
 | ||||
|     IF_CHANGE_ANNOUNCE_MIN_INTERVAL = 6    # In seconds | ||||
|     AUTO_ANNOUNCE_RANDOM_MIN        = 90   # In minutes | ||||
| @ -103,7 +104,7 @@ class SidebandCore(): | ||||
|         # stream logger | ||||
|         self.log_announce(destination_hash, app_data, dest_type=SidebandCore.aspect_filter) | ||||
| 
 | ||||
|     def __init__(self, owner_app, is_service=False, is_client=False, android_app_dir=None, verbose=False): | ||||
|     def __init__(self, owner_app, is_service=False, is_client=False, android_app_dir=None, verbose=False, owner_service=None, service_context=None): | ||||
|         self.is_service = is_service | ||||
|         self.is_client = is_client | ||||
|         self.db = None | ||||
| @ -132,6 +133,8 @@ class SidebandCore(): | ||||
|         self.state_lock = Lock() | ||||
|         self.rpc_connection = None | ||||
|         self.service_stopped = False | ||||
|         self.service_context = service_context | ||||
|         self.owner_service = owner_service | ||||
| 
 | ||||
|         self.app_dir       = plyer.storagepath.get_home_dir()+"/.config/sideband" | ||||
|         self.cache_dir     = self.app_dir+"/cache" | ||||
| @ -2244,6 +2247,23 @@ class SidebandCore(): | ||||
| 
 | ||||
|             threading.Thread(target=telemetry_job, daemon=True).start() | ||||
| 
 | ||||
|     def run_service_telemetry(self): | ||||
|         if not self.telemetry_running: | ||||
|             self.telemetry_running = True | ||||
|             def telemetry_job(): | ||||
|                 while self.telemetry_running: | ||||
|                     try: | ||||
|                         self.update_telemetry() | ||||
|                     except Exception as e: | ||||
|                         import traceback | ||||
|                         exception_info = "".join(traceback.TracebackException.from_exception(e).format()) | ||||
|                         RNS.log(f"An {str(type(e))} occurred while updating service telemetry: {str(e)}", RNS.LOG_ERROR) | ||||
|                         RNS.log(exception_info, RNS.LOG_ERROR) | ||||
| 
 | ||||
|                     time.sleep(SidebandCore.SERVICE_TELEMETRY_INTERVAL) | ||||
| 
 | ||||
|             threading.Thread(target=telemetry_job, daemon=True).start() | ||||
| 
 | ||||
|     def stop_telemetry(self): | ||||
|         self.telemetry_running = False | ||||
|         self.telemeter.stop_all() | ||||
| @ -2298,7 +2318,10 @@ class SidebandCore(): | ||||
|     def update_telemeter_config(self): | ||||
|         if self.config["telemetry_enabled"] == True: | ||||
|             if self.telemeter == None: | ||||
|                 if self.service_context == None: | ||||
|                     self.telemeter = Telemeter() | ||||
|                 else: | ||||
|                     self.telemeter = Telemeter(android_context=self.service_context, service=True, location_provider=self.owner_service) | ||||
| 
 | ||||
|             sensors = ["location", "information", "battery", "pressure", "temperature", "humidity", "magnetic_field", "ambient_light", "gravity", "angular_velocity", "acceleration", "proximity"] | ||||
|             for sensor in sensors: | ||||
| @ -2561,6 +2584,8 @@ class SidebandCore(): | ||||
|         if self.is_service or self.is_standalone: | ||||
|             while True: | ||||
|                 time.sleep(SidebandCore.PERIODIC_JOBS_INTERVAL) | ||||
|                 self.owner_service.update_location_provider() | ||||
| 
 | ||||
|                 if self.config["lxmf_periodic_sync"] == True: | ||||
|                     if self.getpersistent("lxmf.lastsync") == None: | ||||
|                         self.setpersistent("lxmf.lastsync", time.time()) | ||||
| @ -2660,6 +2685,8 @@ class SidebandCore(): | ||||
|         if self.is_standalone or self.is_client: | ||||
|             if self.config["telemetry_enabled"]: | ||||
|                 self.run_telemetry() | ||||
|         elif self.is_service: | ||||
|             self.run_service_telemetry() | ||||
| 
 | ||||
|     def __add_localinterface(self, delay=None): | ||||
|         self.interface_local_adding = True | ||||
|  | ||||
| @ -40,7 +40,7 @@ class Telemeter(): | ||||
|       RNS.log("An error occurred while unpacking telemetry. The contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
|       return None | ||||
| 
 | ||||
|   def __init__(self, from_packed=False): | ||||
|   def __init__(self, from_packed=False, android_context=None, service=False, location_provider=None): | ||||
|     self.sids = { | ||||
|       Sensor.SID_TIME: Time, | ||||
|       Sensor.SID_RECEIVED: Received, | ||||
| @ -80,10 +80,15 @@ class Telemeter(): | ||||
|     if not self.from_packed: | ||||
|       self.enable("time") | ||||
| 
 | ||||
|     self.location_provider = location_provider | ||||
|     self.android_context = android_context | ||||
|     self.service = service | ||||
| 
 | ||||
|   def synthesize(self, sensor): | ||||
|       if sensor in self.available: | ||||
|         if not sensor in self.sensors: | ||||
|           self.sensors[sensor] = self.sids[self.available[sensor]]() | ||||
|           self.sensors[sensor]._telemeter = self | ||||
|           self.sensors[sensor].active = True | ||||
|           self.sensors[sensor].synthesized = True | ||||
| 
 | ||||
| @ -92,6 +97,7 @@ class Telemeter(): | ||||
|       if sensor in self.available: | ||||
|         if not sensor in self.sensors: | ||||
|           self.sensors[sensor] = self.sids[self.available[sensor]]() | ||||
|           self.sensors[sensor]._telemeter = self | ||||
|         if not self.sensors[sensor].active: | ||||
|           self.sensors[sensor].start() | ||||
|    | ||||
| @ -150,6 +156,28 @@ class Telemeter(): | ||||
| 
 | ||||
|     return rendered | ||||
| 
 | ||||
|   def check_permission(self, permission): | ||||
|     if RNS.vendor.platformutils.is_android(): | ||||
|       if self.android_context != None: | ||||
|         try: | ||||
|             result = self.android_context.checkSelfPermission("android.permission."+permission) | ||||
|             if result == 0: | ||||
|                 return True | ||||
| 
 | ||||
|         except Exception as e: | ||||
|             RNS.log("Error while checking permission: "+str(e), RNS.LOG_ERROR) | ||||
|          | ||||
|         return False | ||||
|        | ||||
|       else: | ||||
|         from android.permissions import check_permission | ||||
|         return check_permission("android.permission."+permission) | ||||
| 
 | ||||
|     else: | ||||
|       return False | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class Sensor(): | ||||
|   SID_NONE             = 0x00 | ||||
|   SID_TIME             = 0x01 | ||||
| @ -169,6 +197,7 @@ class Sensor(): | ||||
|   SID_RECEIVED         = 0x10 | ||||
| 
 | ||||
|   def __init__(self, sid = None, stale_time = None): | ||||
|     self._telemeter = None | ||||
|     self._sid = sid or Sensor.SID_NONE | ||||
|     self._stale_time = stale_time | ||||
|     self._data = None | ||||
| @ -238,6 +267,13 @@ class Sensor(): | ||||
|   def render(self, relative_to=None): | ||||
|     return None | ||||
| 
 | ||||
|   def check_permission(self, permission): | ||||
|     if self._telemeter != None: | ||||
|       return self._telemeter.check_permission(permission) | ||||
|     else: | ||||
|       from android.permissions import check_permission | ||||
|       return check_permission("android.permission."+permission) | ||||
| 
 | ||||
| class Time(Sensor): | ||||
|   SID = Sensor.SID_TIME | ||||
|   STALE_TIME = 0.1 | ||||
| @ -587,6 +623,7 @@ class Location(Sensor): | ||||
|     self._last_update = None | ||||
|     self._min_distance = Location.MIN_DISTANCE | ||||
|     self._accuracy_target = Location.ACCURACY_TARGET | ||||
|     self._query_method = None | ||||
| 
 | ||||
|     self.latitude = None | ||||
|     self.longitude = None | ||||
| @ -619,11 +656,14 @@ class Location(Sensor): | ||||
| 
 | ||||
|   def setup_sensor(self): | ||||
|     if RNS.vendor.platformutils.is_android(): | ||||
|       from android.permissions import request_permissions, check_permission | ||||
| 
 | ||||
|       if check_permission("android.permission.ACCESS_COARSE_LOCATION") and check_permission("android.permission.ACCESS_FINE_LOCATION"): | ||||
|       if self._telemeter and self._telemeter.service: | ||||
|         self._location_provider = self._telemeter.location_provider | ||||
|       else: | ||||
|         if self.check_permission("ACCESS_COARSE_LOCATION") and self.check_permission("ACCESS_FINE_LOCATION"): | ||||
|           self.gps.configure(on_location=self.android_location_callback) | ||||
|           self.gps.start(minTime=self._stale_time, minDistance=self._min_distance) | ||||
|           self._location_provider = self | ||||
| 
 | ||||
|     self.update_data() | ||||
|      | ||||
| @ -669,6 +709,10 @@ class Location(Sensor): | ||||
|           } | ||||
| 
 | ||||
|       elif RNS.vendor.platformutils.is_android(): | ||||
|         if self._location_provider != None: | ||||
|           if self._location_provider != self: | ||||
|             self._last_update, self._raw = self._location_provider.get_location() | ||||
| 
 | ||||
|           if "lat" in self._raw: | ||||
|             self.latitude   = self._raw["lat"] | ||||
|           if "lon" in self._raw: | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user