cellular: remove unused glue

This commit is contained in:
Pavel Machek
2026-03-09 11:38:44 +01:00
parent 85823fc58c
commit d6ffabdb4b
@@ -6,16 +6,8 @@ import sys
import json
"""
Librem 5, phosh, python. Give me code to read current battery level.
(and more)
Lets make it class Phone, one method would be reading battery information, one would be reading operator name / signal strength, one would be getting wifi enabled/disabled / AP name.
Can you also get silent mode, pending notifications, and gps coordinates on request?
run this with sudo to work around permission problems
sudo apt install python3-pydbus
sudo mmcli --list-modems
@@ -33,149 +25,6 @@ class Phone:
def init_sess(self):
self.sess = pydbus.SessionBus()
# --- Battery ---
def get_battery_info(self):
upower = self.bus.get("org.freedesktop.UPower")
for dev_path in upower.EnumerateDevices():
if self.verbose: print("dev_path is", dev_path)
dev = self.bus.get(".UPower", dev_path)
if dev.Type == 2: # battery
return {
"percentage": dev.Percentage,
"state": dev.State,
"charging": dev.State == 1,
"time_to_empty": dev.TimeToEmpty, # seconds, 0 if unknown
"time_to_full": dev.TimeToFull, # seconds, 0 if unknown
}
return None
# --- Vibration ---
# https://github.com/agx/feedbackd/blob/main/examples/example.py
def set_vibration(self, enable: bool):
# Connect to GSettings backend (org.gnome.SettingsDaemon, commonly)
dconf = self.sess.get("org.sigxcpu.Feedback", "/org/sigxcpu/Feedback")
# Use the standard Properties interface
iface = dconf["org.sigxcpu.Feedback.Haptic"]
# Example pattern: list of (duration, strength)
pattern = [
(3.0, 1),
(1.0, 200),
(0.0, 50),
(0.5, 300),
]
iface.Vibrate("org.foo.app", pattern)
print(dir(iface))
# --- Feedback: silent/full/... ---
# broken
def set_feedback_theme(self, value):
# Connect to GSettings backend (org.gnome.SettingsDaemon, commonly)
dconf = self.bus.get("org.gnome.SettingsDaemon", "/org/gnome/SettingsDaemon/Dbus")
# Use the standard Properties interface
iface = dconf["org.freedesktop.DBus.Properties"]
# Set the key (schema, key, value)
# GVariant format: value must match the expected type, here 's' = string
value = Variant("s", "custom")
iface.Set("org.sigxcpu.feedbackd", "theme", value)
# --- Mobile network ---
# Works as root
def get_mobile_info(self):
loc = None
mm = self.bus.get("org.freedesktop.ModemManager1")
for modem_path in mm.GetManagedObjects():
modem = self.bus.get(".ModemManager1", modem_path)
print("modem ", modem)
operator = getattr(modem, "OperatorName", None)
print("Operator code:", getattr(modem, "OperatorCode", None)) # 0..11 according to MMState
print("State:", getattr(modem, "State", None)) # 0..11 according to MMState
print("Access Technology:", getattr(modem, "AccessTechnologies", None))
print("Model:", getattr(modem, "Model", None))
print("Manufacturer:", getattr(modem, "Manufacturer", None))
print("Revision:", getattr(modem, "Revision", None))
print("Equipment Identifier (IMEI):", getattr(modem, "EquipmentIdentifier", None))
print("Signal (gsm):", getattr(modem, "Gsm", None))
print("Signal (umts):", getattr(modem, "Umts", None))
print("Signal (lte):", getattr(modem, "Lte", None))
print("Signal:", getattr(modem, "SignalQuality", None))
print("RegistrationState:", getattr(modem, "RegistrationState", None))
# Hallucination?
lac = getattr(modem, "LocationAreaCode", None)
cid = getattr(modem, "CellId", None)
tac = getattr(modem, "TrackingAreaCode", None)
print("Lac...:", lac, cid, tac)
loc = getattr(modem, "Location", None)
print("Location:", loc)
v = modem.Setup(0x027, False)
print("Location setup? ", v)
v = modem.GetLocation()
# This has 1) network info and 4) nmea
print(v)
# Fails with no signal; but has even timing-advance info (I guess only when transmitting)
# It also seems to have neighbouring cells!
"""
Field Meaning Example
operator-id MCC+MNC, identifies mobile operator 23003
serving Whether device is currently connected to this cell True
physical-ci LTE Physical Cell ID (PCI) 12
ci LTE Cell Identity XXXXXX
tac Tracking Area Code XXXX
earfcn LTE frequency channel XXXX
cell-type Cell type code (macro/micro/etc.) 5
rsrp Signal strength (dBm) -122.7
rsrq Signal quality (dB) -17.0
"""
try:
v = modem.GetCellInfo()
except:
v = {}
print(v)
if False:
simple = self.bus.get(".ModemManager1.Modem.Modem3gpp", modem_path)
print(simple)
if False:
# --- Signal ---
try:
modem3gpp = modem.Modem3gpp
if modem3gpp:
print("3GPP Operator Code:", getattr(modem3gpp, "OperatorCode", None))
print("Signal Quality:", getattr(modem3gpp, "SignalQuality", None)) # (percent, valid)
print("Registration State:", getattr(modem3gpp, "RegistrationState", None))
except Exception:
print("No 3gpp?")
# Pokud je LTE/other, ModemManager má ještě Modem4g nebo ModemSignal
try:
signal = modem.Signal
if signal:
# SignalQuality může být tuple (percent, valid)
print("SignalQuality (Signal interface):", getattr(signal, "SignalQuality", None))
except Exception:
print("No signal?")
signal = None
if False:
try:
signal = modem.Signal.Get()["rssi"]
except Exception as e:
return {"error": str(e)}
return {"operator": operator, "signal_strength": signal}
return loc
def get_mobile_loc(self):
loc = None
mm = self.bus.get("org.freedesktop.ModemManager1")
@@ -286,132 +135,6 @@ class Phone:
return { 'result' : 'setenable failed' }
return { 'result': 'ok' }
# --- WiFi ---
def get_wifi_info(self):
nm = self.bus.get("org.freedesktop.NetworkManager")
wifi_enabled = nm.WirelessEnabled
active_ssid = None
for conn_path in nm.ActiveConnections:
ac = self.bus.get(".NetworkManager", conn_path)
if ac.Type == "802-11-wireless":
# Step 1: get the settings connection path
settings_path = ac.Connection
# Step 2: fetch the settings object
sc = self.bus.get(".NetworkManager", settings_path)
settings = sc.GetSettings()
ssid = settings["802-11-wireless"]["ssid"]
if isinstance(ssid, (bytes, bytearray)):
ssid = ssid.decode("utf-8", errors="ignore")
else:
ssid = ''.join(chr(c) for c in ssid)
return {"enabled": nm.WirelessEnabled, "ssid": ssid}
return {"enabled": wifi_enabled, "ssid": active_ssid}
# --- Silent mode / Do Not Disturb ---
# broken
def get_silent_mode(self):
try:
portal = self.bus.get("org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop")
return portal.Settings.Read("org.freedesktop.appearance",
"sound-theme-enabled") == 0
except Exception as e:
return {"error": str(e)}
# --- Pending notifications ---
# broken
def get_notifications(self):
try:
notif = self.bus.get("org.freedesktop.Notifications")
# org.freedesktop.Notifications has no standard "list" API,
# Phosh implements its own.
# In phosh, you can query /org/gnome/Notifications for backlog.
phosh_notif = self.bus.get("org.gnome.Shell",
"/org/gnome/Shell/Notifications")
return phosh_notif.ListNotifications()
except Exception as e:
return {"error": str(e)}
# --- GPS coordinates ---
# Needs permissions from .desktop
def get_location(self):
try:
geoclue = self.bus.get("org.freedesktop.GeoClue2",
"/org/freedesktop/GeoClue2/Manager")
# Step 1: get a client object path
client_path = geoclue.GetClient()
client = self.bus.get("org.freedesktop.GeoClue2", client_path)
# Step 2: set required properties
client.DesktopId = "phone.py"
client.RequestedAccuracyLevel = 3 # 3 = city-level accuracy
client.Start() # start location updates
# Step 3: read location
loc_path = client.Location
location = self.bus.get("org.freedesktop.GeoClue2", loc_path)
return {
"latitude": location.Latitude,
"longitude": location.Longitude,
"accuracy": location.Accuracy,
}
except Exception as e:
return {"error": str(e)}
# --- Hardware sensors (accelerometer, gyroscope, light, proximity) ---
def get_hardware_sensors(self):
try:
obj = self.bus.get("net.hadess.SensorProxy", "/net/hadess/SensorProxy")
# obj exposes multiple interfaces; access the one we need
sensor_proxy = obj["net.hadess.SensorProxy"]
# Enable accelerometer
sensor_proxy.ClaimAccelerometer()
sensor_proxy.ClaimLight()
sensor_proxy.ClaimProximity()
# Give it a small delay to start updating
time.sleep(0.5)
sensors = {}
#print(dir(sensor_proxy))
print('tilt -- tells you phone position -- ', sensor_proxy.AccelerometerTilt)
print('orient -- orientation for screen rotation -- ', sensor_proxy.AccelerometerOrientation)
# Ambient light
if sensor_proxy.HasAmbientLight:
sensors['ambient_light'] = {
'lux': sensor_proxy.LightLevel
}
# Proximity
if sensor_proxy.HasProximity:
sensors['proximity'] = {
'near': sensor_proxy.ProximityNear
}
return sensors
except Exception as e:
return {"error": str(e)}
# --- Screen lock ---
def get_screen_lock(self):
# This one complains
#screensaver = self.sess.get("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver")
screensaver = self.sess.get("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver")
print(dir(screensaver))
#screensaver.SetActive(True)
return { "Locked": screensaver.GetActive() }
# bus = SystemBus()
# login1 = bus.get("org.freedesktop.login1", "/org/freedesktop/login1")
# login1.Suspend(False) # False = interactive, True = force
# login1.Hibernate(False)
phone = Phone()
def handle_cmd(v, a):
@@ -442,31 +165,3 @@ def handle_cmd(v, a):
if len(sys.argv) > 1:
handle_cmd(sys.argv[1], sys.argv)
def full():
phone.init_sess()
print("Battery:", phone.get_battery_info())
phone.set_vibration(True)
# print("Mobile:", phone.get_mobile_info())
print("WiFi:", phone.get_wifi_info())
# print("Silent mode:", phone.get_silent_mode())
# print("Notifications:", phone.get_notifications())
print("Location:", phone.get_location())
print("Hardware sensors:", phone.get_hardware_sensors())
print("Screen lock:", phone.get_screen_lock())
phone.set_vibration(False)
# full, quiet, silent
# phone.set_feedback_theme("full")
def as_root():
print("Battery:", phone.get_battery_info())
print("Mobile:", phone.get_mobile_info())
print("WiFi:", phone.get_wifi_info())
# print("Silent mode:", phone.get_silent_mode())
# print("Notifications:", phone.get_notifications())
# print("Location:", phone.get_location())
print("Hardware sensors:", phone.get_hardware_sensors())
# full, quiet, silent
# phone.set_feedback_theme("full")
#full()
as_root()