mirror of
https://github.com/liberatedsystems/openCom-Companion.git
synced 2024-11-22 13:30:36 +01: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.regex = __version__ = ['"](.*)['"]
|
||||||
version.filename = %(source.dir)s/main.py
|
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
|
# Cryptography recipe is currently broken, using RNS-internal crypto for now
|
||||||
requirements = kivy==2.2.1,libbz2,pillow,qrcode==7.3.1,usb4a,usbserial4a
|
requirements = kivy==2.2.1,libbz2,pillow,qrcode==7.3.1,usb4a,usbserial4a
|
||||||
@ -25,7 +25,8 @@ android.presplash_color = #00000000
|
|||||||
orientation = portrait
|
orientation = portrait
|
||||||
fullscreen = 0
|
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.api = 30
|
||||||
android.minapi = 24
|
android.minapi = 24
|
||||||
android.ndk = 25b
|
android.ndk = 25b
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
__debug_build__ = False
|
__debug_build__ = False
|
||||||
__disable_shaders__ = False
|
__disable_shaders__ = False
|
||||||
__version__ = "0.7.6"
|
__version__ = "0.7.7"
|
||||||
__variant__ = "beta"
|
__variant__ = "beta"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -31,7 +31,6 @@ if RNS.vendor.platformutils.get_platform() == "android":
|
|||||||
from android import python_act
|
from android import python_act
|
||||||
android_api_version = autoclass('android.os.Build$VERSION').SDK_INT
|
android_api_version = autoclass('android.os.Build$VERSION').SDK_INT
|
||||||
|
|
||||||
Context = autoclass('android.content.Context')
|
|
||||||
Intent = autoclass('android.content.Intent')
|
Intent = autoclass('android.content.Intent')
|
||||||
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
||||||
Icon = autoclass("android.graphics.drawable.Icon")
|
Icon = autoclass("android.graphics.drawable.Icon")
|
||||||
@ -60,6 +59,7 @@ class SidebandService():
|
|||||||
0x0483: [0x5740], # ST CDC
|
0x0483: [0x5740], # ST CDC
|
||||||
0x2E8A: [0x0005, 0x000A], # Raspberry Pi Pico
|
0x2E8A: [0x0005, 0x000A], # Raspberry Pi Pico
|
||||||
}
|
}
|
||||||
|
|
||||||
def android_notification(self, title="", content="", ticker="", group=None, context_id=None):
|
def android_notification(self, title="", content="", ticker="", group=None, context_id=None):
|
||||||
if android_api_version < 26:
|
if android_api_version < 26:
|
||||||
return
|
return
|
||||||
@ -121,12 +121,78 @@ class SidebandService():
|
|||||||
built_notification = notification.build()
|
built_notification = notification.build()
|
||||||
self.notification_service.notify(0, built_notification)
|
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):
|
def __init__(self):
|
||||||
self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '')
|
self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '')
|
||||||
self.app_dir = self.argument
|
self.app_dir = self.argument
|
||||||
self.multicast_lock = None
|
self.multicast_lock = None
|
||||||
self.wake_lock = None
|
self.wake_lock = None
|
||||||
self.should_run = False
|
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.android_service = None
|
||||||
self.app_context = None
|
self.app_context = None
|
||||||
@ -149,9 +215,7 @@ class SidebandService():
|
|||||||
|
|
||||||
self.discover_usb_devices()
|
self.discover_usb_devices()
|
||||||
|
|
||||||
self.sideband = SidebandCore(self, is_service=True, android_app_dir=self.app_dir, verbose=__debug_build__)
|
self.sideband = SidebandCore(self, is_service=True, android_app_dir=self.app_dir, verbose=__debug_build__, owner_service=self, service_context=self.android_service)
|
||||||
self.sideband.service_context = self.android_service
|
|
||||||
self.sideband.owner_service = self
|
|
||||||
|
|
||||||
if self.sideband.config["debug"]:
|
if self.sideband.config["debug"]:
|
||||||
Logger.setLevel(LOG_LEVELS["debug"])
|
Logger.setLevel(LOG_LEVELS["debug"])
|
||||||
@ -161,6 +225,7 @@ class SidebandService():
|
|||||||
|
|
||||||
if RNS.vendor.platformutils.is_android():
|
if RNS.vendor.platformutils.is_android():
|
||||||
RNS.log("Discovered USB devices: "+str(self.usb_devices), RNS.LOG_EXTREME)
|
RNS.log("Discovered USB devices: "+str(self.usb_devices), RNS.LOG_EXTREME)
|
||||||
|
self.update_location_provider()
|
||||||
|
|
||||||
|
|
||||||
def discover_usb_devices(self):
|
def discover_usb_devices(self):
|
||||||
|
@ -90,6 +90,7 @@ class SidebandCore():
|
|||||||
PERIODIC_JOBS_INTERVAL = 60
|
PERIODIC_JOBS_INTERVAL = 60
|
||||||
PERIODIC_SYNC_RETRY = 360
|
PERIODIC_SYNC_RETRY = 360
|
||||||
TELEMETRY_INTERVAL = 60
|
TELEMETRY_INTERVAL = 60
|
||||||
|
SERVICE_TELEMETRY_INTERVAL = 300
|
||||||
|
|
||||||
IF_CHANGE_ANNOUNCE_MIN_INTERVAL = 6 # In seconds
|
IF_CHANGE_ANNOUNCE_MIN_INTERVAL = 6 # In seconds
|
||||||
AUTO_ANNOUNCE_RANDOM_MIN = 90 # In minutes
|
AUTO_ANNOUNCE_RANDOM_MIN = 90 # In minutes
|
||||||
@ -103,7 +104,7 @@ class SidebandCore():
|
|||||||
# stream logger
|
# stream logger
|
||||||
self.log_announce(destination_hash, app_data, dest_type=SidebandCore.aspect_filter)
|
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_service = is_service
|
||||||
self.is_client = is_client
|
self.is_client = is_client
|
||||||
self.db = None
|
self.db = None
|
||||||
@ -132,6 +133,8 @@ class SidebandCore():
|
|||||||
self.state_lock = Lock()
|
self.state_lock = Lock()
|
||||||
self.rpc_connection = None
|
self.rpc_connection = None
|
||||||
self.service_stopped = False
|
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.app_dir = plyer.storagepath.get_home_dir()+"/.config/sideband"
|
||||||
self.cache_dir = self.app_dir+"/cache"
|
self.cache_dir = self.app_dir+"/cache"
|
||||||
@ -2244,6 +2247,23 @@ class SidebandCore():
|
|||||||
|
|
||||||
threading.Thread(target=telemetry_job, daemon=True).start()
|
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):
|
def stop_telemetry(self):
|
||||||
self.telemetry_running = False
|
self.telemetry_running = False
|
||||||
self.telemeter.stop_all()
|
self.telemeter.stop_all()
|
||||||
@ -2298,7 +2318,10 @@ class SidebandCore():
|
|||||||
def update_telemeter_config(self):
|
def update_telemeter_config(self):
|
||||||
if self.config["telemetry_enabled"] == True:
|
if self.config["telemetry_enabled"] == True:
|
||||||
if self.telemeter == None:
|
if self.telemeter == None:
|
||||||
|
if self.service_context == None:
|
||||||
self.telemeter = Telemeter()
|
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"]
|
sensors = ["location", "information", "battery", "pressure", "temperature", "humidity", "magnetic_field", "ambient_light", "gravity", "angular_velocity", "acceleration", "proximity"]
|
||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
@ -2561,6 +2584,8 @@ class SidebandCore():
|
|||||||
if self.is_service or self.is_standalone:
|
if self.is_service or self.is_standalone:
|
||||||
while True:
|
while True:
|
||||||
time.sleep(SidebandCore.PERIODIC_JOBS_INTERVAL)
|
time.sleep(SidebandCore.PERIODIC_JOBS_INTERVAL)
|
||||||
|
self.owner_service.update_location_provider()
|
||||||
|
|
||||||
if self.config["lxmf_periodic_sync"] == True:
|
if self.config["lxmf_periodic_sync"] == True:
|
||||||
if self.getpersistent("lxmf.lastsync") == None:
|
if self.getpersistent("lxmf.lastsync") == None:
|
||||||
self.setpersistent("lxmf.lastsync", time.time())
|
self.setpersistent("lxmf.lastsync", time.time())
|
||||||
@ -2660,6 +2685,8 @@ class SidebandCore():
|
|||||||
if self.is_standalone or self.is_client:
|
if self.is_standalone or self.is_client:
|
||||||
if self.config["telemetry_enabled"]:
|
if self.config["telemetry_enabled"]:
|
||||||
self.run_telemetry()
|
self.run_telemetry()
|
||||||
|
elif self.is_service:
|
||||||
|
self.run_service_telemetry()
|
||||||
|
|
||||||
def __add_localinterface(self, delay=None):
|
def __add_localinterface(self, delay=None):
|
||||||
self.interface_local_adding = True
|
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)
|
RNS.log("An error occurred while unpacking telemetry. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __init__(self, from_packed=False):
|
def __init__(self, from_packed=False, android_context=None, service=False, location_provider=None):
|
||||||
self.sids = {
|
self.sids = {
|
||||||
Sensor.SID_TIME: Time,
|
Sensor.SID_TIME: Time,
|
||||||
Sensor.SID_RECEIVED: Received,
|
Sensor.SID_RECEIVED: Received,
|
||||||
@ -80,10 +80,15 @@ class Telemeter():
|
|||||||
if not self.from_packed:
|
if not self.from_packed:
|
||||||
self.enable("time")
|
self.enable("time")
|
||||||
|
|
||||||
|
self.location_provider = location_provider
|
||||||
|
self.android_context = android_context
|
||||||
|
self.service = service
|
||||||
|
|
||||||
def synthesize(self, sensor):
|
def synthesize(self, sensor):
|
||||||
if sensor in self.available:
|
if sensor in self.available:
|
||||||
if not sensor in self.sensors:
|
if not sensor in self.sensors:
|
||||||
self.sensors[sensor] = self.sids[self.available[sensor]]()
|
self.sensors[sensor] = self.sids[self.available[sensor]]()
|
||||||
|
self.sensors[sensor]._telemeter = self
|
||||||
self.sensors[sensor].active = True
|
self.sensors[sensor].active = True
|
||||||
self.sensors[sensor].synthesized = True
|
self.sensors[sensor].synthesized = True
|
||||||
|
|
||||||
@ -92,6 +97,7 @@ class Telemeter():
|
|||||||
if sensor in self.available:
|
if sensor in self.available:
|
||||||
if not sensor in self.sensors:
|
if not sensor in self.sensors:
|
||||||
self.sensors[sensor] = self.sids[self.available[sensor]]()
|
self.sensors[sensor] = self.sids[self.available[sensor]]()
|
||||||
|
self.sensors[sensor]._telemeter = self
|
||||||
if not self.sensors[sensor].active:
|
if not self.sensors[sensor].active:
|
||||||
self.sensors[sensor].start()
|
self.sensors[sensor].start()
|
||||||
|
|
||||||
@ -150,6 +156,28 @@ class Telemeter():
|
|||||||
|
|
||||||
return rendered
|
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():
|
class Sensor():
|
||||||
SID_NONE = 0x00
|
SID_NONE = 0x00
|
||||||
SID_TIME = 0x01
|
SID_TIME = 0x01
|
||||||
@ -169,6 +197,7 @@ class Sensor():
|
|||||||
SID_RECEIVED = 0x10
|
SID_RECEIVED = 0x10
|
||||||
|
|
||||||
def __init__(self, sid = None, stale_time = None):
|
def __init__(self, sid = None, stale_time = None):
|
||||||
|
self._telemeter = None
|
||||||
self._sid = sid or Sensor.SID_NONE
|
self._sid = sid or Sensor.SID_NONE
|
||||||
self._stale_time = stale_time
|
self._stale_time = stale_time
|
||||||
self._data = None
|
self._data = None
|
||||||
@ -238,6 +267,13 @@ class Sensor():
|
|||||||
def render(self, relative_to=None):
|
def render(self, relative_to=None):
|
||||||
return 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):
|
class Time(Sensor):
|
||||||
SID = Sensor.SID_TIME
|
SID = Sensor.SID_TIME
|
||||||
STALE_TIME = 0.1
|
STALE_TIME = 0.1
|
||||||
@ -587,6 +623,7 @@ class Location(Sensor):
|
|||||||
self._last_update = None
|
self._last_update = None
|
||||||
self._min_distance = Location.MIN_DISTANCE
|
self._min_distance = Location.MIN_DISTANCE
|
||||||
self._accuracy_target = Location.ACCURACY_TARGET
|
self._accuracy_target = Location.ACCURACY_TARGET
|
||||||
|
self._query_method = None
|
||||||
|
|
||||||
self.latitude = None
|
self.latitude = None
|
||||||
self.longitude = None
|
self.longitude = None
|
||||||
@ -619,11 +656,14 @@ class Location(Sensor):
|
|||||||
|
|
||||||
def setup_sensor(self):
|
def setup_sensor(self):
|
||||||
if RNS.vendor.platformutils.is_android():
|
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.configure(on_location=self.android_location_callback)
|
||||||
self.gps.start(minTime=self._stale_time, minDistance=self._min_distance)
|
self.gps.start(minTime=self._stale_time, minDistance=self._min_distance)
|
||||||
|
self._location_provider = self
|
||||||
|
|
||||||
self.update_data()
|
self.update_data()
|
||||||
|
|
||||||
@ -669,6 +709,10 @@ class Location(Sensor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
elif RNS.vendor.platformutils.is_android():
|
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:
|
if "lat" in self._raw:
|
||||||
self.latitude = self._raw["lat"]
|
self.latitude = self._raw["lat"]
|
||||||
if "lon" in self._raw:
|
if "lon" in self._raw:
|
||||||
|
Loading…
Reference in New Issue
Block a user