SMS Gateway - Kompletni dokumentace

Modul SMS Gateway nahrazuje Odoo IAP pro odesilani SMS. Misto cloudove sluzby pouziva fyzicke Android telefony jako SMS brany. Kazdy telefon se sparuje s Odoo pomoci QR kodu a automaticky odesilajici SMS z fronty.

Obsah

1. Architektura systemu

┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐ │ Odoo Server │ │ SMS Gateway App │ │ Prijemce SMS │ │ │ │ (Android telefon) │ │ │ │ mailing.mailing │────▶│ │────▶│ +420 777... │ │ sms.sms │ │ DirectSms (nativni) │ │ │ │ sms.gateway.phone│◀───│ Heartbeat │ │ Klikne na link │ │ │ │ SMS Queue Polling │ │ │ │ │ link.tracker │◀────│ Inbound SMS (STOP) │ │ ▼ │ │ phone.blacklist │ │ │ │ /r/ABC/s/42 │ └─────────────────┘ └──────────────────────┘ └─────────────────┘ │ │ │ ┌──────────────────────┐ │ └──────────────│ Link Tracker │◀──────────────┘ │ /r/{code}/s/{sms_id}│ │ UTM tracking │ │ Click counting │ └──────────────────────┘

Komponenty

Komponenta Popis
sms_gateway Odoo modul - spravuje telefony, frontu, API endpointy
sms-gateway-app React Native (Expo) aplikace pro Android
sms.gateway.phone Model reprezentujici jeden registrovany telefon
sms.sms Rozsireny o gateway_phone_id a gateway_state

2. Instalace Odoo modulu

Predpoklady

Postup

  1. Nainstalujte Python zavislost:
    pip install qrcode[pil]
  2. Zkopirujte modul sms_gateway do adresare Odoo addons:
    cp -r extra/sms/sms_modules/sms_gateway /path/to/odoo/addons/
  3. Restartujte Odoo server a aktualizujte seznam modulu
  4. Nainstalujte modul SMS Gateway pres Aplikace
Dulezite: Modul sms_gateway je vzajemne exkluzivni s sms_httpsms. Pokud pouzivate sms_httpsms, odinstalujte ho pred instalaci sms_gateway.

3. Instalace mobilni aplikace

Stazeni APK (doporuceno)

Stahnete nejnovejsi release APK z GitHub Releases. Na telefonu otevrete stazeny .apk soubor a povolte instalaci z neznamych zdroju.

Poznamka: Aplikace neni na Google Play. Pouziva opravneni SEND_SMS a READ_SMS, ktera vyzaduji specialni review. Sideloading APK z GitHub Releases je zamysleny zpusob distribuce.

Predpoklady (build ze zdrojaku)

Build aplikace

cd sms-gateway-app

# Instalace zavislosti
npm install

# Prebuild nativniho projektu (nutne pro nativni moduly)
npx expo prebuild

# Spusteni na pripojenem telefonu
npx expo run:android

# NEBO build release APK pres EAS
eas build --profile production-apk --platform android

Upload jako GitHub Release

gh release create v1.x.x ./build/*.apk \
  --repo Varyshop/sms-gateway-app \
  --title "v1.x.x" \
  --notes "Release notes"

Pozadovana opravneni Android

Opravneni Ucel
SEND_SMS Odesilani SMS bez otevreni aplikace
RECEIVE_SMS Cteni prichozich SMS (detekce STOP)
READ_PHONE_STATE Cteni cisel SIM karet
READ_PHONE_NUMBERS Cteni telefonniho cisla
CAMERA Skenovani QR kodu

4. Nastaveni modulu v Odoo

Vytvoreni gateway telefonu

  1. Prejdete do Email Marketing > SMS Gateway > Gateway Phones
  2. Kliknete Novy
  3. Vyplnte:
    Pole Popis Priklad
    Name Nazev telefonu Telefon 1 - O2
    Phone Number Hlavni cislo (mezinarodni format) +420777123456
    Phone Number 2 Druhe cislo (dual SIM, volitelne) +420608987654
    Daily Limit Max SMS za den 500
    SMS per Minute Max SMS za minutu (rate limit) 100
    Heartbeat Timeout Po kolika minutach bez heartbeatu = offline 5
  4. Kliknete Generate API Key - vygeneruje se API klic a QR kod
Tip: Muzete registrovat vice telefonu. System automaticky rozdeluje zatez (least-loaded algoritmus).

5. Parovani telefonu

  1. V Odoo otevrete formular gateway telefonu a ujistete se, ze je vygenerovany QR kod
  2. Na Android telefonu otevrete aplikaci SMS Gateway
  3. Prejdete na tab Nastaveni
  4. Kliknete Naskenovat QR kod
  5. Nasmerujte kameru na QR kod zobrazeny v Odoo
  6. Aplikace se automaticky spoji se serverem a zacne posilat heartbeaty

QR kod obsahuje

{
    "type": "sms_gateway",
    "url": "https://vas-odoo-server.cz",
    "api_key": "nahodny_bezpecnostni_token"
}
Overeni: Po sparovani by se mel stav telefonu v Odoo zmenit na Online. Pokud ne, zkontrolujte sitove pripojeni a cas heartbeat timeout.

6. Nastaveni SMS kampane

Vytvoreni kampane

  1. Prejdete do Email Marketing > SMS Marketing
  2. Kliknete Novy
  3. Nastavte:

Priklad SMS textu

Ahoj {{ object.name }}! Mate 20% slevu na vse.
Nakupte na https://www.example.cz/akce
STOP pro odhlaseni
Automaticka nahrada: Modul automaticky nahradi vsechny URL v SMS za kratke trackovaci odkazy (napr. https://vas-server.cz/r/ABC123/s/42). Puvodni odhlasovaci odkazy se nahradi textem STOP pro odhlaseni.

Filtrovani prijemcu

Pouzijte Odoo domain filtr pro vyber prijemcu:

Priklad filtru Popis
[("category_id", "in", [10])] Kontakty s kategorii ID 10
[("country_id.code", "=", "CZ")] Ceske kontakty
[("customer_rank", ">", 0)] Pouze zakazniky
[("opt_out", "=", False)] Pouze ti, co se neodhlasili

7. Filtrovani domeny pro telefony

Kazdy gateway telefon muze mit nastaven Partner Domain Filter. Tento filtr urcuje, ktere SMS se budou prirazovat danemu telefonu na zaklade partnera prijemce.

Jak to funguje

  1. Kdyz sms.sms._send() prirazuje SMS do fronty, hleda dostupne telefony
  2. Pro kazdy telefon s nastavenym domain_filter se overi, zda partner prijemce odpovida filtru
  3. Telefon bez filtru prijima SMS pro vsechny partnery
  4. Telefon s filtrem prijima pouze SMS kde partner odpovida domene

Priklady pouziti

Scenar Domain Filter Vysvetleni
Telefon pro VIP zakazniky [("category_id", "in", [10])] Pouze zakaznici s kategorii "VIP" (ID 10)
Telefon pro Prahu [("state_id.name", "=", "Praha")] Pouze zakaznici z Prahy
Telefon pro vsechny (prazdne) Prijima SMS pro vsechny partnery
Telefon pro firmy [("is_company", "=", True)] Pouze firmy, ne fyzicke osoby
Pozor: Pokud zadny telefon neodpovida filtru pro daneho partnera, SMS se oznaci jako chyba (failure_type='sms_server'). Doporucujeme mit alespon jeden telefon bez filtru jako fallback.

8. Spusteni odeslani

Automaticke odeslani (kampan)

  1. Vytvorte a nastavte kampan (viz sekce 6)
  2. Kliknete Send nebo Schedule
  3. Odoo vytvori sms.sms zaznamy ve stavu outgoing
  4. Cron job (SMS: SMS Queue Manager) pickuje outgoing SMS
  5. _send() priradi kazde SMS gateway telefonu a zmeni stav na pending
  6. Mobilni aplikace si vyzvedne pending SMS pres API
  7. Aplikace odesle SMS a potvrdi stav (sent/error)

Manualni odeslani (Force Create SMS Queue)

Pokud se SMS nevytvorily automaticky:

  1. Otevrete kampan
  2. Kliknete Force Create SMS Queue
  3. System vytvori SMS zaznamy pro vsechny zbyvajici prijemce

Pauzovani kampane

Kampan lze pozastavit bez zruseni:

  1. Otevrete kampan v rezimu Sending
  2. Prepnete prepinac Paused na aktivni
  3. SMS ve fronte se nebudou odesilat, ale zustanou prirazeny
  4. Pro obnoveni vypnete prepinac Paused
Stavy SMS: outgoing ──▶ pending (prirazeno telefonu) ──▶ processing (telefon vyzvedl) │ ├──▶ sending (telefon odesila) │ │ │ ├──▶ sent (uspesne odeslano) ✓ │ └──▶ error (chyba odeslani) ✗ │ └──▶ error (chyba odeslani) ✗ Pokud je kampan pauzovana: outgoing ──▶ (preskoceno, zustava outgoing)

9. Jak funguji odkazy a tracking

Automaticka konverze odkazu

Vsechny URL v SMS tele jsou automaticky prevadeny na kratke trackovaci odkazy:

Faze Priklad
Puvodni text Nakupte na https://www.example.cz/akce
Po konverzi Nakupte na https://vas-server.cz/r/ABC123
Po prirazeni SMS ID Nakupte na https://vas-server.cz/r/ABC123/s/42

Jak tracking funguje

  1. Vytvoreni odkazu: Odoo vytvori link.tracker zaznam s kratky kodem a UTM parametry
  2. Pridani SMS ID: Ke kazdemu odkazu se prida /s/{sms_id} pro identifikaci konkretniho prijemce
  3. Kliknuti prijemce: Prijemce klikne na link ve SMS zprave
  4. Server zaznamenava:
  5. Presmerovani: Server presmeruje na puvodni URL s UTM parametry:
    https://www.example.cz/akce?utm_campaign=Q1_2025&utm_medium=sms&utm_source=kampan

UTM parametry

Automaticky pridavane pri presmerovani:

Parametr Hodnota Zdroj
utm_campaign Nazev kampane mailing.mailing.campaign_id
utm_medium "sms" mailing.mailing.medium_id
utm_source Nazev zdroje mailing.mailing.source_id
Google Analytics: Diky UTM parametrum muzete sledovat navstevnost z SMS kampani primo v Google Analytics (Acquisition > Campaigns).

10. Odhlaseni a blacklist (GDPR)

Jak funguje odhlaseni

System podporuje dva zpusoby odhlaseni z SMS kampani:

Zpusob 1: STOP zprava (doporuceny)

  1. Na konci kazde SMS je text: STOP pro odhlaseni
  2. Prijemce odpovi SMS zpravou obsahujici slovo STOP
  3. Mobilni aplikace detekuje prihozeni SMS se slovem STOP
  4. Aplikace posle informaci na Odoo endpoint /sms-gateway/inbound
  5. Odoo prida cislo prijemce na phone.blacklist
  6. Vsechny budouci kampane automaticky preskoci blacklistovana cisla

Zpusob 2: Webovy odkaz (standardni Odoo)

Odoo standardne generuje odhlasovaci URL ve formatu /sms/{mailing_id}/{trace_code}. Nas modul tyto URL nahrazuje textem "STOP pro odhlaseni", protoze:

GDPR povinnost: Podle GDPR musi byt kazda marketingova SMS zprava opatrena moznosti odhlaseni. Modul automaticky pridava "STOP pro odhlaseni" na konec zpravy. Neodstranujte tuto informaci!

Blacklist model

Odoo pouziva model phone.blacklist z modulu phone_validation:

Kde najit blacklist

SMS Marketing > Configuration > Phone Blacklist

11. Statistiky a vykon kampane

Sledovane metriky

Metrika Popis Jak se meri
Sent Pocet uspesne odeslanych SMS sms.sms ve stavu sent
Delivered Dorucene SMS = sent + opened + replied
Clicked Prijemci co klikli na odkaz mailing.trace s links_click_datetime
Click Rate Procento kliknuti (unikatni kliknuti / celkem odeslano) × 100
Bounced Neplatna cisla mailing.trace ve stavu bounce
Failed Chyba odeslani mailing.trace ve stavu error

Kde najit statistiky

  1. Prehled kampane: Otevrete kampan - v zahlavi jsou pocitadla Sent/Clicked/Bounced
  2. Detailni statistiky: Kliknete na pocitadlo pro zobrazeni seznamu zaznamu
  3. Link Tracker: Email Marketing > Link Tracker - prehled vsech trackovanych odkazu s poctem kliknuti
  4. Gateway telefony: SMS Gateway > Gateway Phones - sent_today, sent_total, pending, error pocitadla

Link Tracker - detailni analyza

Kazdy odkaz v SMS ma vlastni link.tracker zaznam:

12. Limity a rate limiting

Typy limitu

Limit Kde se nastavuje Popis
Daily Limit sms.gateway.phone Max SMS za den na telefon. Pocitadlo sent_today se resetuje o pulnoci.
SMS per Minute sms.gateway.phone Max SMS za minutu. Aplikace pocita delay mezi SMS: 60000 / rate_limit ms.
Android SMS limit OS Android Android standardne omezuje na ~30 SMS za 30 minut. Muze byt zmenen v nastaveni.

Jak funguje rate limiting

  1. Server nastavuje rate_limit na kazdem gateway telefonu (napr. 100 SMS/min)
  2. Mobilni aplikace ziska rate_limit z heartbeat odpovedi
  3. Mezi kazdou SMS aplikace pocka 60000 / rate_limit milisekund
  4. Pokud telefon dosahne daily_limit, neni mu prirazena zadna dalsi SMS
Android omezeni: Na nekterych Android zarizeni je hardwarovy limit ~30 SMS za 30 minut. Pro vetsi objemy doporucujeme pouzit vice telefonu nebo zmenit nastaveni ADB:
adb shell settings put global sms_outgoing_check_max_count 10000

13. Dual SIM podpora

System podporuje telefony s dvema SIM kartami:

Poznamka: Ne vsechny Android telefony umoznuji vyber SIM slotu pro odchozi SMS programove. Na nekterych zarizeni se pouzije vychozi SIM karta.

14. API reference

Vsechny endpointy vyzaduji hlavicku X-API-Key s platnym API klicem gateway telefonu.

POST /sms-gateway/heartbeat

Odeslani heartbeatu a ziskani stavu fronty.

// Request
{
    "phone_numbers": ["+420777123456", "+420608987654"],
    "battery_level": 85,
    "signal_strength": -70
}

// Response
{
    "success": true,
    "pending_count": {"+420777123456": 12, "+420608987654": 5},
    "rate_limit": 100
}

POST /sms-gateway/pending

Ziskani SMS cekajicich na odeslani.

// Request
{"phone_numbers": ["+420777123456"], "limit": 20}

// Response
{
    "success": true,
    "sms_list": [
        {
            "id": 123,
            "phone_number": "+420999888777",
            "message": "Text SMS zpravy...",
            "uuid": "abc-123-def",
            "gateway_phone_number": "+420777123456"
        }
    ]
}

POST /sms-gateway/confirm/{sms_id}

Potvrzeni stavu odeslani SMS.

// Request - uspech
{"status": "sent"}

// Request - chyba
{"status": "error", "error_message": "Permission denied"}

// Request - probihajici
{"status": "sending"}

// Response
{"success": true}

POST /sms-gateway/inbound

Nahlaseni prichozi SMS (pro STOP detekci). Zprava se ulozi do modelu sms.gateway.inbound a pokud obsahuje STOP, cislo se prida na blacklist.

// Request
{
    "from_number": "+420999888777",
    "message": "STOP",
    "to_number": "+420777123456"
}

// Response
{
    "success": true,
    "blacklisted": true,
    "partner_found": true
}

POST /sms-gateway/inbound-batch

Hromadne nahlaseni vice prichozich SMS najednou. Od v1.2.0 aplikace posila vsechny prijate SMS (nejen STOP) na server. Server provadi deduplikaci podle kombinace from_number + to_number + message + received_at, takze opakovane odeslani stejnych zprav (napr. pri rescan inboxu) nevytvori duplicity.

// Request
{
    "messages": [
        {
            "from_number": "+420999888777",
            "message": "STOP",
            "to_number": "+420777123456",
            "received_at": "2026-03-22T10:30:00Z"
        },
        {
            "from_number": "+420111222333",
            "message": "Dekuji za informaci",
            "to_number": "+420777123456",
            "received_at": "2026-03-22T11:15:00Z"
        }
    ]
}

// Response
{
    "success": true,
    "processed": 2,
    "duplicates_skipped": 0
}
Chatter integrace: Kazda prichozi SMS se automaticky zapise do chatteru partnera v Odoo jako formatovana HTML poznamka (blockquote s textem zpravy). Pokud zprava obsahuje STOP, prida se vizualni stitek STOP.

Model: sms.gateway.inbound

Vsechny prichozi SMS se ukladaji do modelu sms.gateway.inbound:

Pole Typ Popis
from_number Char Cislo odeslatele (E.164)
to_number Char Cislo gateway telefonu, na ktere SMS prisla
message Text Obsah SMS zpravy
received_at Datetime Cas prijmu zpravy na telefonu
partner_id Many2one Nalezeny partner podle cisla odeslatele (muze byt prazdne)
is_stop Boolean Zda zprava obsahuje klicove slovo STOP
is_blacklisted Boolean Zda je cislo odeslatele na blacklistu
gateway_phone_id Many2one Odkaz na sms.gateway.phone

POST /sms-gateway/stats

Statistiky gateway telefonu.

// Response
{
    "success": true,
    "phones": [
        {
            "id": 1,
            "name": "Telefon 1 - O2",
            "phone_number": "+420777123456",
            "phone_number_2": null,
            "state": "online",
            "sent_today": 142,
            "daily_limit": 500,
            "sent_total": 4582,
            "pending_count": 23,
            "rate_limit": 100
        }
    ]
}

POST /sms-gateway/register-fcm

Registrace FCM tokenu pro push notifikace. Telefon posle svuj FCM token po sparovani nebo kdyz se token obnovi.

// Request
{
    "fcm_token": "dK3xP9...dlouhy_firebase_token"
}

// Response - uspech
{
    "success": true,
    "message": "FCM token registered"
}

// Response - FCM neni povoleno
{
    "success": true,
    "message": "FCM not enabled, token ignored"
}

POST /sms-gateway/confirm-batch

Hromadne potvrzeni stavu vice SMS najednou. Efektivnejsi nez jednotlive /confirm/{sms_id} volani.

// Request
{
    "results": [
        {"sms_id": 123, "status": "sent"},
        {"sms_id": 124, "status": "sent"},
        {"sms_id": 125, "status": "error", "error_message": "Number unreachable"}
    ]
}

// Response
{
    "success": true,
    "processed": 3
}

14b. Marketing modely (segmenty a sablony)

Od verze v18.0.2.2.0 modul obsahuje modely pro SMS marketing primo z mobilni aplikace. Admin definuje segmenty a sablony v Odoo, operator je pouziva z appky bez pristupu do backendu.

Model: sms.marketing.segment

Definuje skupinu prijemcu (napr. „Neobjednali 3 mesice“).

PoleTypPopis
nameCharNazev segmentu (prekladatelny)
codeChar, uniqueSlug (no_order_3m, one_order_only, new_customers_30d)
domain_filterCharDeklarativni Odoo domena, napr. [("country_id.code", "=", "CZ")]. Pokud je nastavena, pouzije se misto code-based logiky.
sequenceIntegerPoradi v seznamu
activeBooleanAktivni/neaktivni
descriptionTextPopis zobrazeny v appce

Vychozi segmenty (data)

CodeNazevLogika
no_order_3mNeobjednali 3 mesiceSQL: partneri s objednavkou, ale zadnou za 90 dni
one_order_onlyJedina objednavkaSQL: partneri s presne 1 potvrzenou objednavkou
new_customers_30dNovi zakaznici (30 dni)Domain: [("create_date", ">=", today - 30d)]

Klicove metody

MetodaPopis
_get_domain() Vrati zakladni Odoo domain segmentu. Pouzije domain_filter nebo dispatchuje na _domain_{code}().
_get_full_domain(phone, exclude_contacted_days) Single source of truth — sklada kompletni domain: segment + blacklist + phone filter + exclusion kontaktovanych.
_get_storable_domain(phone, exclude_contacted_days) Vraci domain vhodnou pro ulozeni do mailing_domain. Deklarativni segmenty se ulozi jako citelna domena; SQL segmenty se pre-resolvi na ('id', 'in', [...]).
_resolve_recipient_ids(phone, exclude_days, limit) Resolvi domain na seznam partner ID. Pouziva se pro pocty a preview.
_get_recipient_count(phone, exclude_days) Spocita pocet odpovidajicich partneru.
_get_exclusion_domain(days) Vrati domain leaf vylucujici partnery kontaktovane v poslednich N dnech (SQL na mailing_trace).
Domain compositing: Vsechny endpointy (filters, preview, create) deleguji na segment model. Phone domain_filter se automaticky pridava v _get_full_domain(), takze domena telefonu a segmentu se vzdy kombinuji.

Model: sms.marketing.template

SMS sablona prirazena ke gateway telefonu.

PoleTypPopis
nameCharNazev sablony
bodyTextText SMS (muze obsahovat {{object.name}})
phone_idMany2one → sms.gateway.phonePrirazeny telefon
segment_idsMany2many → sms.marketing.segmentPovolene segmenty
default_limitInteger (100)Vychozi navrh poctu prijemcu
max_limitInteger (500)Hard cap na pocet prijemcu
exclude_contacted_daysInteger (0)Vyloucit partnery kontaktovane v poslednich N dnech

Nova pole na mailing.mailing

PoleTypPopis
gateway_phone_forced_idMany2one → sms.gateway.phoneVynuceny telefon pro vsechny SMS v kampani
recipient_limitIntegerMax pocet prijemcu
marketing_template_idMany2one → sms.marketing.templateZpetny odkaz na sablonu
created_from_appBooleanVytvoreno z mobilni appky
pausedBooleanPozastavena kampan (neodesila se, ale SMS jsou ve fronte)

14c. Campaign API (mobilni appka)

Endpointy pro mobilni appku umoznujici vytvorit a sledovat SMS kampane bez pristupu do Odoo backendu. Vsechny endpointy: POST, auth pres X-API-Key, JSON body/response.

POST /sms-gateway/campaign/templates

Vrati sablony prirazene k telefonu identifikovanemu API klicem.

// Response
{
    "success": true,
    "templates": [
        {
            "id": 1,
            "name": "Akce tento tyden",
            "body": "Ahoj {{object.name}}! Mate slevu 20%...",
            "segments": [
                {"id": 1, "name": "Neobjednali 3 mesice", "code": "no_order_3m"},
                {"id": 2, "name": "Jedina objednavka", "code": "one_order_only"}
            ],
            "default_limit": 100,
            "max_limit": 500,
            "exclude_contacted_days": 14
        }
    ]
}

POST /sms-gateway/campaign/filters

Pro kazdý segment spocita pocet odpovidajicich prijemcu (vcetne phone domain filtru a exclusion).

// Request
{"template_id": 1}

// Response
{
    "success": true,
    "filters": [
        {
            "id": 1,
            "code": "no_order_3m",
            "name": "Neobjednali 3 mesice",
            "description": "Partneri s objednavkou ale zadnou za 90 dni",
            "recipient_count": 342
        }
    ]
}

POST /sms-gateway/campaign/preview

Nahled kampane — pocet prijemcu a renderovany text s ukázkovym partnerem.

// Request
{"template_id": 1, "segment_id": 1, "limit": 200}

// Response
{
    "success": true,
    "recipient_count": 200,
    "preview_text": "Ahoj Jan Novak! Mate slevu 20%...",
    "template_name": "Akce tento tyden",
    "segment_name": "Neobjednali 3 mesice"
}

POST /sms-gateway/campaign/create

Vytvori mailing.mailing s plnym trackingem. Prijima volitelny custom_body (uprava textu z appky) a send_now prepinac.

// Request
{
    "template_id": 1,
    "segment_id": 1,
    "limit": 200,
    "custom_body": "Upraveny text SMS...",
    "send_now": true
}

// Response
{
    "success": true,
    "campaign_id": 42,
    "recipient_count": 200,
    "state": "sending"
}
send_now: Pokud send_now=false, kampan se vytvori ve stavu in_queue s paused=true. SMS jsou ve fronte, ale neodesílají se dokud operator nestiskne „Odeslat ihned“ v appce (endpoint assign-sim).
Domain storage: Pro segmenty s deklarativnim domain_filter se do mailing_domain ulozi citelna domena (napr. [("country_id.code", "=", "CZ"), ...]). Pro SQL segmenty se pre-resolvi na kompaktni [("id", "in", [1, 2, 3, ...])].

POST /sms-gateway/campaign/assign-sim

Priradi gateway telefon a SIM k SMS v kampani. Pouziva stejnou logiku jako akce „Send via Gateway“ v Odoo.

// Request — jedina SIM (nebo auto-prirazeni bez SIM cisla)
{
    "campaign_id": 42,
    "mode": "single",
    "sim_number": "+420777123456"
}

// Request — rozdeleni mezi vice SIM
{
    "campaign_id": 42,
    "mode": "split",
    "sim_numbers": ["+420777123456", "+420608987654"]
}

// Response
{
    "success": true,
    "assigned": 200,
    "message": "Assigned 200 SMS to phone"
}
Co assign-sim dela:

POST /sms-gateway/campaign/list

Seznam kampani vytvorených z appky pro dany telefon.

// Response
{
    "success": true,
    "campaigns": [
        {
            "id": 42,
            "name": "Akce tento tyden - 04.04.2026 10:30",
            "state": "done",
            "date_created": "2026-04-04 10:30:00",
            "total": 200,
            "sent": 195,
            "pending": 0,
            "error": 5,
            "clicked": 42,
            "total_clicks": 67,
            "order_count": 8,
            "revenue": 12400.0,
            "optout": 3
        }
    ]
}

POST /sms-gateway/campaign/status/{mailing_id}

Detail kampane s marketingovymi statistikami.

// Response
{
    "success": true,
    "id": 42,
    "name": "Akce tento tyden - 04.04.2026 10:30",
    "state": "done",
    "total": 200,
    "sent": 195,
    "pending": 0,
    "error": 5,
    "clicked": 42,
    "total_clicks": 67,
    "order_count": 8,
    "revenue": 12400.0,
    "optout": 3,
    "created_at": "2026-04-04 10:30:00"
}

Vysvetleni statistik

PolePopisZdroj
clickedUnikatni prijemci co kliklimailing.trace s links_click_datetime
total_clicksCelkovy pocet kliknuti (vcetne opakovanych)link.tracker.click pres UTM campaign
order_countPocet objednavek z kampanesale.order s campaign_id = UTM kampan
revenueCelkovy prijem z objednavekSoucet amount_total z matchujicich objednavek
optoutPocet odhlasenych (STOP)mailing.trace ve stavu cancel

15. Reseni problemu

Problem Pricina Reseni
Telefon je stale Offline Heartbeat nedochazi na server
  • Zkontrolujte sitove pripojeni telefonu
  • Overte spravnost API klice (znovu naskenujte QR)
  • Zkontrolujte URL serveru (musi byt HTTPS)
  • Zvyste heartbeat_timeout na gateway telefonu
SMS se neodesilaji Aplikace nema opravneni SEND_SMS Otevre nastaveni Android > Aplikace > SMS Gateway > Opravneni > povolit SMS
SMS ve fronte ale zadny telefon neprijima Zadny telefon neodpovida domain_filter Zkontrolujte domain_filter na gateway telefonech. Alespon jeden by mel byt bez filtru.
Vsechny SMS maji stav error Zadny gateway telefon neni online Ujistete se ze aplikace bezi, je sparovana a posila heartbeaty
Daily limit dosazeny prilis brzo Pocitadlo sent_today Zvyste daily_limit nebo pridejte dalsi telefony. Reset je o pulnoci (cron).
Android blokuje SMS po 30 zpravach Hardwarovy limit Androidu Pouzijte ADB prikaz: adb shell settings put global sms_outgoing_check_max_count 10000
STOP neprida cislo na blacklist Aplikace nema opravneni RECEIVE_SMS Povolte opravneni RECEIVE_SMS v nastaveni Android
Odkazy v SMS nefunguji Spatna konfigurace web.base.url V Odoo nastavte spravne System Parameters > web.base.url (musi byt verejne dostupne)
Kampan se neoznaci jako Done Nektera SMS stale pending Zkontrolujte, ze vsechny SMS jsou ve stavu sent nebo error. Mozna je kampan pauzovana.
SMS se neodesilaji pri zamknute obrazovce Android ukonci aplikaci kvuli optimalizaci baterie
  • Vypnete Battery Optimization pro SMS Gateway (Nastaveni > Aplikace > SMS Gateway > Baterie > Neomezovat)
  • Na MIUI/HarmonyOS: pridejte do Autostart a zakaste DuraSpeed / Battery saver
  • Overete, ze AlarmManager ma opravneni SCHEDULE_EXACT_ALARM
STOP SMS chybi v blacklistu InboundSmsWorker selhal nebo neni sit
  • Zkontrolujte, ze WorkManager ma pristup k siti (Nastaveni > Datove pripojeni)
  • Overete opravneni RECEIVE_SMS
  • V logu aplikace hledejte chyby InboundSmsWorker
  • Zkontrolujte, ze endpoint /sms-gateway/inbound je dostupny z telefonu
  • Pouzijte tlacitko Znovu prohledat prijate SMS v Nastaveni > Sluzba pro retroaktivni odeslani vsech prijatych SMS za poslednich 30 dni
Prichozi SMS nedochazeji na server InboundSmsWorker pouzival spatnou autentifikaci (Authorization: Bearer misto X-API-Key)
  • Fix v1.2.0: InboundSmsWorker nyni pouziva spravne hlavicku X-API-Key (stejne jako ostatni endpointy)
  • Aktualizujte aplikaci na v1.2.0+
  • Po aktualizaci pouzijte Znovu prohledat prijate SMS pro odeslani chybejicich zprav z minulosti
FCM push nedochazi FCM neni spravne nakonfigurovano
  • Overete sms_gateway.fcm_enabled = True v System Parameters
  • Zkontrolujte, ze sms_gateway.fcm_credentials_json nebo sms_gateway.fcm_credentials_path je nastaveno
  • Overete instalaci: pip list | grep firebase-admin
  • Zkontrolujte, ze telefon ma platny FCM token (endpoint /sms-gateway/register-fcm)

Diagnosticke prikazy (curl)

# Test heartbeat
curl -X POST https://vas-server.cz/sms-gateway/heartbeat \
  -H "Content-Type: application/json" \
  -H "X-API-Key: VAS_API_KLIC" \
  -d '{"phone_numbers": ["+420777123456"]}'

# Overeni pending SMS
curl -X POST https://vas-server.cz/sms-gateway/pending \
  -H "Content-Type: application/json" \
  -H "X-API-Key: VAS_API_KLIC" \
  -d '{"phone_numbers": ["+420777123456"], "limit": 5}'

# Test inbound STOP
curl -X POST https://vas-server.cz/sms-gateway/inbound \
  -H "Content-Type: application/json" \
  -H "X-API-Key: VAS_API_KLIC" \
  -d '{"from_number": "+420999888777", "message": "STOP", "to_number": "+420777123456"}'

16. FCM Push Notifications

Od verze v18.0.2.0.0 modul podporuje Firebase Cloud Messaging (FCM) pro okamzite probuzeni telefonu pri novych SMS ve fronte. Misto cekani na dalsi polling interval telefon obdrzi push notifikaci a okamzite si vyzvedne cekajici SMS.

Architektura

Odoo Server Google FCM Android App │ │ │ │ 1. Nova SMS ve fronte │ │ │──────────────────────────────▶ │ │ send_fcm_wake() │ │ │ (data message) │ 2. Push notification │ │ │───────────────────────────▶│ │ │ │ 3. FcmMessageHandler │ │ │ probudi aplikaci │ 4. GET /sms-gateway/pending │ │ │◀──────────────────────────────────────────────────────────│ │ 5. SMS data │ │ │──────────────────────────────────────────────────────────▶│ │ │ │ 6. Odesle SMS

Konfigurace na strane Odoo

System Parameter Typ Popis
sms_gateway.fcm_enabled Boolean Zapne/vypne FCM push notifikace. Vychozi: False
sms_gateway.fcm_credentials_json Text (JSON) Inline obsah Firebase service account JSON souboru. Ma prednost pred fcm_credentials_path.
sms_gateway.fcm_credentials_path Text (cesta) Absolutni cesta k Firebase service account JSON souboru na serveru. Pouzije se pokud fcm_credentials_json neni nastaven.

Python zavislost

pip install firebase-admin

Knihovna firebase-admin je automaticky nainstalovana pri instalaci modulu (deklarovana v external_dependencies manifestu). Pokud instalace selze (napr. chybi systemove knihovny), FCM funkce se ticha deaktivuje a telefony pokracuji v polling rezimu.

Implementace: tools/fcm_service.py

Hlavni funkce send_fcm_wake(phone) odesle FCM data message na registrovany telefon. Data message (na rozdil od notification message) probudi aplikaci i na pozadi bez zobrazeni notifikace uzivateli.

# Format FCM data message
{
    "type": "sms_pending",
    "phone_id": "7",
    "timestamp": "1710751200"
}
Pole Popis
type Vzdy "sms_pending" — aplikace podle typu rozhodne akci
phone_id ID zaznamu sms.gateway.phone v Odoo
timestamp Unix timestamp odeslani — pro deduplication na strane aplikace

Zpetna kompatibilita

Bezpecny upgrade: Telefony bez registrovaneho FCM tokenu (pole fcm_token na sms.gateway.phone) pokracuji v polling rezimu bez jakekoliv zmeny chovani. FCM je ciste aditivni vylepseni — zadny existujici telefon neprestane fungovat.

17. Pozadi a spolehlivost (Android)

Android agresivne omezuje pozadi aplikaci kvuli uspore baterie. Tato sekce dokumentuje strategie pouzite v SMS Gateway aplikaci pro spolehlivy provoz i pri zamknute obrazovce a Doze rezimu.

AlarmManager vs ScheduledExecutorService

Pro pravidelny polling (heartbeat + vyzvedavani SMS) aplikace pouziva AlarmManager s presnym budenim namisto ScheduledExecutorService nebo Handler.postDelayed().

Pristup Chovani v Doze MIUI/HarmonyOS
ScheduledExecutorService Zastaven po ~1 min v Doze Agresivne ukoncen
Handler.postDelayed Zastaven po ~1 min v Doze Agresivne ukoncen
AlarmManager.setExactAndAllowWhileIdle Probudi zarizeni z Doze Funguje i na MIUI (s vyjimkou baterie)
Opravneni: Od Android 12 (API 31) je nutne opravneni SCHEDULE_EXACT_ALARM nebo USE_EXACT_ALARM. Aplikace o nej zada automaticky pri prvnim spusteni.

WorkManager pro prichozi SMS

Zpracovani prichozich SMS (detekce STOP) pouziva WorkManager (InboundSmsWorker) namisto primych HTTP volani z BroadcastReceiveru. Duvody:

WakeLock strategie

Aplikace pouziva PowerManager.WakeLock na dvou mistech pro zabraneni uspaní CPU behem kritickych operaci:

Komponenta WakeLock tag Trvani Ucel
FcmMessageHandler sms-gateway:fcm-wake Max 60 sekund Drzi CPU vzhuru behem poll + odeslani SMS po FCM wake
SmsBroadcastReceiver sms-gateway:inbound-sms Max 30 sekund Drzi CPU behem zpracovani prichozi SMS a enqueue do WorkManager

IMPORTANCE_HIGH notifikacni kanal

Foreground service notifikace pouziva kanal s IMPORTANCE_HIGH. To zajistuje, ze Android nezabije sluzbu ani pri nedostatku pameti. Uzivatel vidi trvalou notifikaci ve stavovem radku (pozadavek Androidu pro foreground service).

Vyjimka z optimalizace baterie

Pri prvnim spusteni aplikace zada uzivatele o vyjimku z optimalizace baterie (REQUEST_IGNORE_BATTERY_OPTIMIZATIONS). Bez teto vyjimky muze Android:

Kontrola: V aplikaci v sekci Nastaveni je indikator stavu optimalizace baterie. Pokud sviti cervene, uzivatel musi rucne pridat vyjimku.

Rescan Inbox (nativni metoda)

Aplikace od v1.2.0 obsahuje nativni metodu SmsModule.rescanInbox(days), ktera precte SMS inbox za poslednich N dni (vychozi: 30) a vsechny nalezene zpravy odesle na server pres endpoint /sms-gateway/inbound-batch.

Tato funkce je dostupna uzivateli pres tlacitko Znovu prohledat prijate SMS v Nastaveni > Sluzba. Server provadi deduplikaci, takze je bezpecne spustit rescan opakavane.

// React Native volani
import { NativeModules } from 'react-native';
const messages = await NativeModules.SmsModule.rescanInbox(30);
// messages: Array<{from: string, body: string, date: number}>

// Nasledne se zpravy odeslou pres inbound-batch endpoint

WRITE_SECURE_SETTINGS opravneni

Pro zvyseni nativniho Android limitu na pocet odchozich SMS je potreba udelit aplikaci opravneni WRITE_SECURE_SETTINGS. Toto opravneni nelze udelit z GUI telefonu — vyzaduje ADB pripojeni:

# Primo pres ADB
adb shell pm grant com.varyshop.smsgatewayapp android.permission.WRITE_SECURE_SETTINGS

# Nebo pri buildu ze zdrojaku
yarn grant-permission
Bez tohoto opravneni Android muze blokovat odesilani po prekroceni nativniho limitu (~30 SMS za 30 minut). S opravnenim aplikace automaticky zvysi limit.

Heartbeat safety net

I s FCM muze dojit k situaci, kdy push notifikace nedorazi (napr. docasny vypadek Google sluzeb). Proto aplikace udrzuje heartbeat safety net:

  1. Kazdy heartbeat vraci pending_count pro kazde cislo
  2. Pokud pending_count > 0, aplikace okamzite spusti poll cyklus
  3. Heartbeat interval je typicky 60 sekund — maximalni zpozdeni pri vypadku FCM je tedy 1 minuta
  4. Tento mechanismus funguje nezavisle na FCM a zajistuje doruceni i bez push notifikaci
FCM push (okamzite) ──▶ Poll + Send │ │ (pokud FCM selze) │ Heartbeat (60s) ──▶ pending_count > 0? ──▶ Poll + Send │ └── pending_count == 0 ──▶ Zadna akce
V případě jakýchkoli dotazů nebo potřebné pomoci s nastavením kontaktujte info@varyshop.eu nebo přímo vývojáře info@michalvarys.eu

18. Changelog

v18.0.2.2.0 / App v1.3.0 (2026-04-04)

v18.0.2.1.0 / App v1.2.0


SMS Gateway v18.0.2.2.0 • VaryShop • 2026