CometTextel — Python (thin FFI)
Thin ctypes binding to the same C ABI as the C SDK and CometTextel.NET (c_api.h).
This is not a second native library: it runtime-loads comettextel.dll / libcomettextel.so.
Covers PDU helpers and GsmModem (open / send / list / delete).
Hardware modem tests are optional; smoke tests run without a device.
Layout
sdk/python/
├── comettextel/ # package (ctypes + PDU + modem)
├── examples/
│ ├── pdu_example.py # encode / decode + self-check
│ └── modem_example.py # list / send / delete
├── tests/
│ ├── test_pdu.py
│ └── test_modem.py
└── README.md
Prerequisites
| Item | Detail |
|---|---|
| Python | 3.10+ (3.13 verified) |
| Native | C SDK shared library (comettextel.dll or libcomettextel.so) |
| Modem (optional) | AT modem in PDU mode (e.g. COM3, /dev/ttyUSB0) |
Download comettextel-c-sdk-* from CI Artifacts or a GitHub Release, or use a local CMake build.
Finding the library
Search order:
- Explicit path passed to
comettextel.pdu.load_library(...) - Environment variable
COMETTEXTEL_LIB(shared-library file or a directory containing it — including versioned Linux sonames such aslibcomettextel.so.1.3.0) - Wheel-embedded
_native/<platform>/(CI platform wheels) - Current working directory
- Nearby build / artifact folders (
build-c-sdk/Release,artifact/comettextel-c-sdk-*/…)
# Windows
$env:COMETTEXTEL_LIB = "D:\path\to\comettextel.dll"
# Linux
export COMETTEXTEL_LIB=/path/to/libcomettextel.so
Wheels
CI builds platform wheels that embed the matching C ABI shared library:
| Artifact | Tag |
|---|---|
comettextel-python-wheel-windows |
win_amd64 |
comettextel-python-wheel-linux |
linux_x86_64 |
Local pack (after a C SDK stage):
python sdk/python/scripts/stage_native.py --from artifact/comettextel-c-sdk-windows-x64
python -m pip install build
python -m build --wheel --outdir dist sdk/python
python sdk/python/scripts/stage_native.py --clean
pip install dist/comettextel-*.whl
Editable / source installs without a staged _native still need COMETTEXTEL_LIB or a nearby build.
PDU example
cd sdk\python
python examples\pdu_example.py
python examples\pdu_example.py 886912345678 "Hello" 886932000000
python examples\pdu_example.py 886912345678 "測試中文簡訊" 886932000000
Modem example
python examples\modem_example.py list COM3
python examples\modem_example.py send COM3 886932000000 886912345678 "Hello"
python examples\modem_example.py delete COM3 1
list rejoins complete concatenated SMS sets (concat_seq == 0 / Message.is_reassembled_concat).
Tests
cd sdk\python
pip install pytest
pytest -q
API sketch
from comettextel import DCS_UCS2, GsmModem, decode, encode_submit_segments
parts = encode_submit_segments("886912345678", "Hello", "886932000000", DCS_UCS2)
msg = decode(parts[0])
with GsmModem() as modem:
modem.open("COM3", 115200)
modem.send("886912345678", "Hello from Python", smsc="886932000000")
for m in modem.list():
print(m.index, m.peer_address, m.user_data, m.is_reassembled_concat)
All text at the native boundary is UTF-8. Do not reimplement PDU codecs in Python; if the C ABI changes, update this package only.
GSM 7-bit (DCS_GSM7)
Maps UTF-8 through GSM 03.38 (default alphabet + ESC extension). Examples: []{}\~^|€.
Unsupported glyphs (e.g. Chinese) raise CometTextelError / encode status — use DCS_UCS2.
Extension characters consume two septets; concat auto-split will not break an ESC pair.
from comettextel import DCS_GSM7, decode, decode_status_report, encode_submit
hex_pdu = encode_submit("886912345678", "Cost: 10€ [ok]", "886932000000", DCS_GSM7)
print(decode(hex_pdu).user_data)
Status reports can be decoded separately:
report = decode_status_report(
"00022A0C91889621436587215070418045232150704180452300"
)
print(report.message_reference, hex(report.tp_status), report.recipient_address)
api_version() reports the native C ABI feature version. A legacy DLL without
the version export is treated as version 1; Status Report decoding then raises
CometTextelError with Status.UNSUPPORTED while existing APIs remain usable.
Validity Period / Status Report
The default submit APIs omit TP-VP, allowing the SMSC to apply its default
validity period. To set a GSM relative TP-VP, pass an octet from 0 to 255;
0 means five minutes. request_status_report=True sets TP-SRR:
hex_pdu = encode_submit(
"886912345678", "OTP 123456", "886932000000", DCS_GSM7,
relative_validity_period=0x8F,
request_status_report=True,
)
The same keyword arguments are available on encode_submit_segments() and
GsmModem.send(). After requesting a report, call
modem.poll_status_report() (C ABI v3) to drain +CDS URCs.
modem.run_at_command("AT+CSQ\\r") (C ABI v3) runs generic AT queries with
URC demux during the wait. Older native
libraries raise Status.UNSUPPORTED for that method while other APIs remain usable.
See also
Metadata
Release files for comettextel 1.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| comettextel-1.7.1-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| comettextel-1.7.1-py3-none-manylinux_2_34_x86_64.whl | Python 3 | none | Linux glibc 2.34+ x86-64 | Details |
Total release size: 163.5 kB
Release files / comettextel-1.7.1-py3-none-win_amd64.whl
| Download URL | comettextel-1.7.1-py3-none-win_amd64.whl |
|---|---|
| Size | 67.0 kB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a4c8d19e1f32dd2dfb2a96de8ac44f47697431e4a23f0c30c6c221fff28b3607
|
|
BLAKE2b-256 checksum How to use checksums |
67bee657a6c0841585ad4eddd366385b108d9a2f956d1d11ee5d057233e2d69c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Release files / comettextel-1.7.1-py3-none-manylinux_2_34_x86_64.whl
| Download URL | comettextel-1.7.1-py3-none-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 96.5 kB |
| Tags | Linux glibc 2.34+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
8835bb610832a936c41633439f25347935ea18d79cd7b3f92428e8ced569a29d
|
|
BLAKE2b-256 checksum How to use checksums |
da887005cbce1e393f6ab915757a9df47f55ea34634322a368217e071ababb2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|