Skip to content

Repository files navigation

CometTextel

Tiny, Elegant, and Practical — A Modern C++ Library for GSM SMS over Serial.

CometTextel is a concise, lightweight C++ library for sending and receiving short messages through a GSM modem. It provides a clean serial abstraction, GSM 03.40 PDU encode/decode, and AT-command helpers — built with C++23 and CMake, ready as a shared or static library.

GitHub C++ CMake CI Status

First-time integration: doc/getting-started.md (download Artifact / Release → include & link).

Features

  • Cross-Platform Serial Layer: Unified SerialPort API with Win32 and POSIX backends.
  • GSM PDU Codec: 7-bit, 8-bit, and UCS-2 encode/decode without MFC or legacy globals.
  • Modem Helpers: Initialize, send (AT+CMGS), list (AT+CMGL), and delete (AT+CMGD) in PDU mode.
  • Modern C++23: RAII handles, std::error_code, std::span, and clear public headers under include/comettextel/.
  • Shared & Static: Build comettextel as a DLL/shared library and/or a static archive from one CMake tree.
  • Doxygen-Ready: English API comments with author metadata for generated documentation.

Limitations

  • Single-segment SMS only — concatenated SMS is not reassembled / split for send.
  • UDH on receive: when TP-UDHI is set, the header is skipped so user_data is payload text only (Message::has_udh == true); segments are still not joined.
  • Per-segment payload caps (encode rejects longer input with EncodeFailure):
    • GSM 7-bit: ≤ 160 septets
    • 8-bit / UCS-2: ≤ 140 octets
  • GSM 7-bit path treats input bytes as septets; it does not validate the full GSM 03.38 alphabet / escape table.

Environment

  • Windows 10/11, Linux, or macOS
  • CMake 3.28 above (recommend)
  • A C++23 compiler (MSVC 19.4x+, GCC 14+, or Clang 18+)
  • A GSM modem / USB dongle that speaks AT commands in PDU mode

How to Build

Building requires CMake and a C++23 toolchain. Tested under Windows 11 with MSVC.

cmake -S . -B build -A x64
cmake --build build --config Release

Optional flags:

Option Default Description
COMETTEXTEL_BUILD_SHARED ON Build the shared library
COMETTEXTEL_BUILD_STATIC ON Build the static library
COMETTEXTEL_BUILD_EXAMPLES ON Build example programs
COMETTEXTEL_BUILD_TESTS ON Build unit tests
COMETTEXTEL_BUILD_DOCS OFF Generate Doxygen docs
COMETTEXTEL_BUILD_C_API ON Build stable C ABI (c_api.h) for P/Invoke / NuGet

Artifacts (Release):

  • Windows: build/Release/comettextel.dll, build/Release/comettextel_static.lib
  • Unix: libcomettextel.so / libcomettextel.a
  • Example: build/examples/Release/comettextel_*_example.exe

Run unit tests:

cmake --build build --config Release
ctest --test-dir build -C Release --output-on-failure

Continuous Integration

GitHub Actions (.github/workflows/ci.yml) runs on every push and pull request to main:

  • Windows (MSVC x64): configure, build, run CTest, upload comettextel-windows-x64
    (bin/comettextel.dll, import/static libs, headers)
  • Windows C SDK: upload comettextel-c-sdk-windows-x64 (c_api.h + DLL/libs + examples/c_api_example.c)
  • Windows .NET: PDU smoke tests (CometTextel.NET.Tests, including UCS-2 Chinese), then pack/upload CometTextel.NET-nupkg
  • Linux (GCC 14): configure, build, run CTest, upload comettextel-linux-x64
    (libcomettextel.so*, libcomettextel.a, headers)
  • Linux C SDK: upload comettextel-c-sdk-linux-x64

Download build packages from the workflow Artifacts tab (retained 14 days).

For a step-by-step “download → include → link” walkthrough, see doc/getting-started.md.

C SDK (optional)

Stable C ABI: include/comettextel/c_api.h.
Sample: examples/c_api_example.c (built as comettextel_c_api_example when COMETTEXTEL_BUILD_EXAMPLES=ON and COMETTEXTEL_BUILD_C_API=ON).

# After build (Release):
comettextel_c_api_example pdu 886912345678 "Hello" 886932000000

CI / Release also publish focused C SDK artifacts (comettextel-c-sdk-*) with only c_api.h, shared/static libs, and the example source — see sdk/c/README.md.

.NET NuGet (optional)

A separate C# wrapper lives under nuget/CometTextel.NET (style similar to ThinBasic.NET):

cd nuget/CometTextel.NET
.\pack.ps1

This builds comettextel.dll with the C ABI and produces CometTextel.NET.*.nupkg. See that folder’s README for Install-Package / Quick start.

Install & find_package

cmake -S . -B build -A x64 -DCOMETTEXTEL_BUILD_EXAMPLES=OFF
cmake --build build --config Release
cmake --install build --config Release --prefix ./prefix

Consumer project:

find_package(comettextel 1.0 REQUIRED CONFIG)
target_link_libraries(app PRIVATE comettextel::comettextel)
# or explicitly:
# target_link_libraries(app PRIVATE comettextel::shared)
# target_link_libraries(app PRIVATE comettextel::static)

Set CMAKE_PREFIX_PATH to the install prefix if needed.

Releases

Push a version tag to publish a GitHub Release with binaries:

git tag v1.0.0
git push origin v1.0.0

The Release workflow (.github/workflows/release.yml) builds, tests, and attaches:

  • comettextel-<version>-windows-x64.zip
  • comettextel-<version>-linux-x64.tar.gz
  • comettextel-<version>-c-sdk-windows-x64.zip
  • comettextel-<version>-c-sdk-linux-x64.tar.gz

API Example

#include "comettextel/comettextel.hpp"

#include <iostream>

int main()
{
    comettextel::GsmModem modem;
    comettextel::SerialConfig config;
    config.baud_rate = 115200;

    if (const auto ec = modem.open_and_init("COM3", config); ec) {
        std::cerr << "open/init failed: " << ec.message() << '\n';
        return 1;
    }

    comettextel::Message message;
    message.service_center = "886932000000";
    message.peer_address = "886912345678";
    message.coding = comettextel::DataCoding::Ucs2;
    message.user_data = "Hello from CometTextel";

    if (const auto ec = modem.send_message(message); ec) {
        std::cerr << "send failed: " << ec.message() << '\n';
        return 2;
    }

    return 0;
}

Examples

Send one UCS-2 SMS:

comettextel_send_example COM3 886932000000 886912345678 "Hello"

List stored messages (summary):

comettextel_list_example COM3

Read the inbox (full text; optional wait for +CMTI):

comettextel_receive_example COM3
comettextel_receive_example COM3 15

Delete one stored message by index:

comettextel_delete_example COM3 1

Layout

comettextel/
├── cmake/                 # Compiler options, Doxygen, package config
├── doc/                   # User guides
├── examples/              # Sample programs (+ c_api_example.c)
├── include/comettextel/   # Public headers (+ c_api.h)
├── nuget/CometTextel.NET/ # Optional .NET NuGet wrapper (P/Invoke)
├── scripts/               # CI helpers (e.g. stage_c_sdk)
├── sdk/c/                 # C SDK package README template
├── src/                   # Library sources
│   └── serial/            # Win32 / POSIX backends
├── tests/                 # Unit tests (CTest)
└── CMakeLists.txt

History

  • 2014: Original Win32 COMM / GSM PDU code written as a Visual C++ project.
  • 2026: Rewritten as a modern C++23 CMake library with cross-platform serial support and renamed to CometTextel.

Credits

  • Original COM port and PDU routines inspired by classic GSM modem programming samples.

License

Copyright (c) 2026 Ji-Feng Tsai.
Code released under the MIT license.

TODO

  • Concatenated SMS / UDH (multi-part encode & reassembly)
  • Longer modem async I/O / thread-safe serial

Donation

If this library helps you reduce time to coding, you can give me a cup of coffee :)

paypal

Paypal Me

About

CometTextel — A Modern C++ Library for GSM SMS over Serial

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages