eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 7e59e40883f085175627bf566f3cfd64714abe3b
parent 7239e54166371a99dd81201b6e2462edd2277a6c
Author: Daniel Barlow <dan@telent.net>
Date:   Wed, 28 Jan 2026 01:08:44 +0000

cli client program

this is presently android.py minus the gui bits, but the plan is to
extract a module that can be used both from linux and from
termux-android

Diffstat:
Aclient/eculocate.py | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mshell.nix | 1+
2 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/client/eculocate.py b/client/eculocate.py @@ -0,0 +1,126 @@ +#!/data/data/com.termux/files/usr/bin/python + +# import termuxgui as tg +import time +import sys +import socket +import threading +import select +import datetime +from pathlib import Path +import os +from zeroconf import ServiceBrowser, ServiceListener, Zeroconf + +class ZListener(ServiceListener): + def __init__(self, client): + self.client = client; + + def update_service(self, zc: Zeroconf, type_: str, name: str) -> None: + print(f"Service {name} updated") + + def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None: + self.hosts[name] = 0 + print(f"Service {name} removed") + + def add_service(self, zc: Zeroconf, type_: str, name: str) -> None: + info = zc.get_service_info(type_, name) + print(f"Service {name} added, service info: {info}") + self.client.hosts[name] = None + self.client.host_addresses[name] = (socket.inet_ntoa(info.addresses[0]), info.port) + + +class Client(): + def __init__(self): + self.peer_hostname = None + self.peer_thread = None + self.bytes_recorded = 0 + + self.started = False + self.hosts = {} + self.host_addresses = {} + zeroconf = Zeroconf() + ServiceBrowser(zeroconf, "_keihin._udp.local.", ZListener(self)) + + def knows_service(self, servicename): + return not (not (self.host_addresses.get(servicename, False))) + + def output_pathname(self): + dir = os.getenv("ECULOCATE_STORAGE") + if dir: + dir = Path(dir) + else: + dir = Path("/storage") / "emulated" / "0" / "eculocate" + dir.mkdir(0o777, False, True) + name = f"{int(time.time())}.raw" + return dir / name + + def recording_thread_main(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + addr = self.host_addresses[self.peer_hostname] + print(self.peer_hostname) + print(addr) + sock.connect(addr) + sock.setblocking(0) + interval = 500 + + self.bytes_recorded = 0 + + with open(self.output_pathname(), "wb") as outf: + while self.started: + print("sending subscribe") + b = bytes([interval >> 8, interval & 0xff, 0x54, 0x11, 0, 25] ) + sock.send(b) + timeout = time.time() + 60 + while self.started and time.time() < timeout: + ready = select.select([sock], [], [], timeout - time.time()) + if ready[0]: + data = sock.recv(4000) + self.bytes_recorded = self.bytes_recorded + len(data) + outf.write(data) + outf.flush() + sock.close() + print("recording thread terminated") + + def choose_service_name(self, hostname): + if hostname == None: + self.started = False + self.peer_hostname = hostname + + def start_recording(self, start_or_stop): + if start_or_stop and self.peer_hostname != None: + self.started = True + print("starting record") + peer_thread = threading.Thread(target=self.recording_thread_main, daemon = True) + peer_thread.start() + else: + print("stopping record") + self.started = False + + + +# ./eculocate "service name" 60 # connect to service name, record for 60s + +# discover zeroconf until we have the requested service name + +name = sys.argv[1] +fqname = f"{name}._keihin._udp.local." + +client = Client() + +timeout = int(sys.argv[2]) +exists = False + +while not exists: + time.sleep(2) + exists = client.knows_service(fqname) +client.choose_service_name(fqname) + +print("record") +client.start_recording(True) +time.sleep(timeout) +client.start_recording(False) +print("fin") + +# register session +# start to record to stdout +# stop after requested time or 15s diff --git a/shell.nix b/shell.nix @@ -6,6 +6,7 @@ ]; python = (pkgs.python3.withPackages (python-pkgs: [ python-pkgs.pynacl + python-pkgs.zeroconf ])); in pkgs.mkShell rec {