Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

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.

Release files for pyrokid-cxr-clientm 0.0.4a5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyrokid-cxr-clientm 0.0.4a5
File Size Uploaded
pyrokid_cxr_clientm-0.0.4a5.tar.gz 48.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyrokid-cxr-clientm 0.0.4a5
File Interpreter ABI Platform
pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl Python 3 none any Details

Total release size: 118.3 kB

Release files / pyrokid_cxr_clientm-0.0.4a5.tar.gz

Download URL pyrokid_cxr_clientm-0.0.4a5.tar.gz
Size 48.3 kB
Tags Source
SHA-256 checksum
How to use checksums
0401b51ce1149742c71036c413df47519e71703b427e3d3d4b73aed60105ee3b
BLAKE2b-256 checksum
How to use checksums
5bcbcaa16341c9c8d337fdc675ef7fac6b042e5c27d54ba15622c17162531bb9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 24, 2026.

Transparency log

Release files / pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl

Download URL pyrokid_cxr_clientm-0.0.4a5-py3-none-any.whl
Size 70.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6816ecc888e6e110c30dafce975d03c4f0b906fd5bb58a9595301c457b8dd4c8
BLAKE2b-256 checksum
How to use checksums
78036b8949680d2bbc50ed5dc991a4bea50a65dece8770ae06716228e3a14277
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 24, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page