Skip to main content

A python port of the com.rokid.cxr.client-m Java library.

Project description

com.rokid.cxr.client-m library for Python

A python port of the com.rokid.cxr.client-m Java library.

The idea is to allow you to use the CXR-M SDK on any device with bluetooth.

Library supports Python 3.7+ (confirmed using vermin), for as far as Bleak supports.

This repo is NOT an official Rokid Glasses repo. We're not associated with Rokid. This is just a personal project to port CXR-M to python, so it can be used on any platform, instead of only phones with android 10+

Info

The Rokid Glasses do have to be re-paired in order for this to connect.

Guide below should help you. If you were to run into issues after you completed all the steps, then you could make an issue if there isn't one yet for the problem you are facing. Opening issues of stuff that has already been answered will be closed without response.

Current Status

Currently as of v0.0.4a5, only the libcaps.so library is ported.

Other than that, also the utils.LogUtil, utils.ValueUtil, extend.callbacks, extend.infos, extend.listeners, extend.version and extend.sync have all been ported. Also extend.controllers.FileController is finished and working. You just need to have wifi already enabled for you to use it already, since I'm still working making the bluetooth connection more stable.

Also the extend.controllers.WifiController is 'finished'. It does a port scan on your network to find the glasses its webserver. The original Android/Java library uses WiFi Direct P2P, but I am, as of right now, unable to make that work crossplatform. To add to that: I am also not even able to just do it for Windows. And since a port scan does work on WiFi networks without a firewall blocking connections to other IP's on the network, I think this is the best for now. The only downside is that your glasses must have been connected to the network during a firmware upgrade, else it won't try to connect. The reason why Hi Rokid is able to connect to the glasses no matter what internet you're connected to or if you're not even connected to wifi, is because of WiFi direct, where the glasses make a wifi 'hotspot' which the phone connects to and then talks to the glasses.

I also added customview to the library which does NOT exist in the java SDK, but does allow you to make sure your CustomViews are valid JSON.

I already have more code, which connects to the glasses and actually is able to send stuff to the glasses, but it's still not fully perfect. I'm still decompiling java and c code and still developing the rest. Consider giving me my time to work it out. Anyways, as always God bless and peace out!

Setting up

Install this library using pip install pyrokid-cxr-clientm

Dependencies

When running the install command, python will automatically install the requirements. But that doesn't stop me being transparent about the dependencies, so here's the list and why its used:

  • Bleak: The main Bluetooth library, supports all platforms and is easy to work with, so that's why I'm using it.
  • pybluez: Secondary Bluetooth library, used when you're running on python <3.9, for the Rfcomm socket, which is built-in starting from python 3.9+
  • tzlocal: A library which allows me to get your machine's timezone name (like Europe/Amsterdam) to send with the setGlassTime() method
  • pycryptodome: A library for doing AES hashing, needed to do CxrApi.checkGlassesSn(), which will check if the clientSecret and license file are correct. (altho this part is also edited to continue regardless of it being correct)
  • requests: A library for performing a POST HTTP request for the extend.version.check_util.CheckUtil class. I could've used httplib, but requests is much easier to work with.
  • dataclasses_json: A library to make it easier to encode and decode dataclasses to and from JSON strings.
  • faster-whisper: For doing Speech to text
  • numpy: For doing stuff with arrays and shit. Mostly related to the speech to text.
  • soundfile: For doing stuff with ogg files
  • scipy: For resampling ogg files from 48k to 16k

If you see a warning about huggingface when running the code, you can safely ignore the warning.

API/Example

Here is an example code with comments to explain the API functions:

# Imports
from pyrokid_cxr_clientm import Caps
from pyrokid_cxr_clientm.utils import ValueUtil
from pyrokid_cxr_clientm.extend.callbacks import *
from pyrokid_cxr_clientm.extend.infos import *
from pyrokid_cxr_clientm.extend.listeners import *

# Decode bytes to a Caps object
bytes_variable = b'\x00\x00\x00\x99\x05\x05SSSuu$xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\x11MA:C0:AD:DR:E5:50Txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==\x01\x01'
caps = Caps.fromBytes(bytes_variable)
print(caps)
print('socketUuid:', caps.at(0).getString())
print('macAddress:', caps.at(1).getString())
print('rokidAccount:', caps.at(2).getString())
print('glassesType:', caps.at(3).getUInt32()) # 0-no display, 1-have display

# Encode Caps object to bytes
caps = Caps()
caps.writeUInt32(0x1004)
caps.writeUInt32(1)
caps.writeUInt32(5)
caps.write('TestDevice')
caps.writeUInt64(1765983621057)
data = caps.serialize()
print(data)

To download files from your device, when the glasses are already connected to wifi (since I've not added the bluetooth controller yet), you can use this snippet:

from pyrokid_cxr_clientm.utils import ValueUtil
from pyrokid_cxr_clientm.extend.controllers import FileController, WifiController
import os, logging

logging.basicConfig(level=logging.INFO)

savePath = 'media/'
os.makedirs(savePath, exist_ok=True) # Make the folder if it doesnt exist yet
types = [ValueUtil.CxrMediaType.PICTURE] # Select the type of media you want to download, you can do [ValueUtil.CxrMediaType.ALL] if you want all media types

class fileCallback(FileController.Callback):
	def onDownloadStart(self) -> None:
		print('Download Start')
	def onSingleFileDownloaded(self, fileName: str) -> None:
		print('Single File Downloaded', fileName)
	def onDownloadFailed(self) -> None:
		print('Download Failed!')
	def onDownloadFinished(self) -> None:
		print('Download Finished!')
		quit()

class wifiCallback(WifiController.Callback):
	def onStatusUpdate(self, cxrStatus: ValueUtil.CxrStatus, cxrWifiErrorCode: ValueUtil.CxrWifiErrorCode) -> None: pass
	def onAddress(self, address: str) -> None:
		FileController.getInstance().startDownload(0, savePath, types, None, address, fileCallback())
		# Now just wait, it is still running in the background!
		FileController.getInstance().i.t.join()

WifiController.getInstance().init(0, "", wifiCallback())

P.s. when downloading VIDEO files, you will also see .txt files show up. Those are used by the Hi Rokid app to do the post stabilisation


To upload apk's to the glasses to sideload the apk, you can use this snippet to wirelessly (without dev cable) do that. (Again wifi needs to be ON for this to work)

from pyrokid_cxr_clientm.utils import ValueUtil
from pyrokid_cxr_clientm.extend.callbacks import ApkStatusCallback
from pyrokid_cxr_clientm.extend.controllers import FileController, WifiController
import logging

logging.basicConfig(level=logging.INFO)
apkPath = 'org.fdroid.fdroid_1023050.apk' # path to the .apk on your computer

class apkStatusCallback(ApkStatusCallback):
	def onUploadApkSucceed(self) -> None:
		print('Upload Apk Succeed')
		quit()
	def onUploadApkFailed(self) -> None:
		print('Upload Apk Failed')
	def onInstallApkSucceed(self) -> None: pass # These ones won't trigger, cause you're not using Bluetooth!
	def onInstallApkFailed(self) -> None: pass
	def onUninstallApkSucceed(self) -> None: pass
	def onUninstallApkFailed(self) -> None: pass
	def onOpenAppSucceed(self) -> None: pass
	def onOpenAppFailed(self) -> None: pass

class wifiCallback(WifiController.Callback):
	def onStatusUpdate(self, cxrStatus: ValueUtil.CxrStatus, cxrWifiErrorCode: ValueUtil.CxrWifiErrorCode) -> None: pass
	def onAddress(self, address: str) -> None:
		FileController.getInstance().startUploadApk(apkPath, address, apkStatusCallback())
		# Now just wait, it is still running in the background!

		# You could do this to kinda let the thing still wait. Should be fine
		FileController.getInstance().r.t.join()

WifiController.getInstance().init(0, "", wifiCallback())

If everything went right, you should now see a new app at the very end of the apps screen.

Extra API Documentation

Extra API documentation can be found on the ReadTheDocs documentation.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyrokid_cxr_clientm-0.0.4a5.tar.gz (48.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl (70.1 kB view details)

Uploaded Python 3

File details

Details for the file pyrokid_cxr_clientm-0.0.4a5.tar.gz.

File metadata

  • Download URL: pyrokid_cxr_clientm-0.0.4a5.tar.gz
  • Upload date:
  • Size: 48.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyrokid_cxr_clientm-0.0.4a5.tar.gz
Algorithm Hash digest
SHA256 0401b51ce1149742c71036c413df47519e71703b427e3d3d4b73aed60105ee3b
MD5 47e334464c7a5147dd265e8e881cc57e
BLAKE2b-256 5bcbcaa16341c9c8d337fdc675ef7fac6b042e5c27d54ba15622c17162531bb9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyrokid_cxr_clientm-0.0.4a5.tar.gz:

Publisher: publish-pypi.yml on Miniontoby/pyrokid_cxr_clientm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl.

File metadata

File hashes

Hashes for pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl
Algorithm Hash digest
SHA256 6816ecc888e6e110c30dafce975d03c4f0b906fd5bb58a9595301c457b8dd4c8
MD5 831340fa97a24ab809e21c8e80e7f092
BLAKE2b-256 78036b8949680d2bbc50ed5dc991a4bea50a65dece8770ae06716228e3a14277

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl:

Publisher: publish-pypi.yml on Miniontoby/pyrokid_cxr_clientm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page