└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # openSPOT HTTP API 2 | 3 | Note that this repository is always updated according to the beta openSPOT firmware releases. 4 | 5 | The HTTP API uses JSON queries and replies. 6 | 7 | All queries except gettok.cgi, ip.cgi and checkauth.cgi must include a valid JWT 8 | ([JSON Web Token](https://jwt.io)). 9 | The JWT should be included in the HTTP header as Authorization: Bearer. 10 | 11 | To acquire a JWT, your application must complete the login process. The JWT stays valid for 12 | 3600 seconds after the last valid query. If the supplied JWT is not valid, openSPOT responds 13 | with 403 Forbidden header. 14 | 15 | ## Login process 16 | 17 | - Request a token using *gettok.cgi*. 18 | - Concatenate the token and the password string. 19 | - Hash this using SHA256 to get the digest. 20 | - Call login.cgi with the token and the digest in the query. 21 | 22 | Example login process with example JSON queries: 23 | 24 | - GET **gettok.cgi** an empty query. Response: 25 | ```json 26 | { 27 | "token": "1f9a8b7c" 28 | } 29 | ``` 30 | 31 | - Our password is *"passw0rd"*. So we concatenate the token and the password, and hash it: 32 | ```bash 33 | sha256("1f9a8b7cpassw0rd") 34 | ``` 35 | This gives us the digest *"2c476e1191ac5d38f72d9b00aca1c1a64aebe991de8c2c4806e413016844e6be"* Should be lowercase only! 36 | 37 | - Now we POST **login.cgi** this JSON: 38 | ```json 39 | { 40 | "token": "1f9a8b7c", 41 | "digest": "2c476e1191ac5d38f72d9b00aca1c1a64aebe991de8c2c4806e413016844e6be" 42 | } 43 | ``` 44 | 45 | The reply will be: 46 | 47 | ```json 48 | { 49 | "hostname": "openspot", 50 | "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMjljODQwZSJ9.r3Oom8qVEAd1ceMMWibrMNsgu0DPgz-IG13MAzB-o5s" 51 | } 52 | ``` 53 | If the password is not matching, openSPOT will respond with a 401 Unauthorized header. 54 | 55 | - Now we are logged in and can call all API interfaces with the acquired JWT. 56 | 57 | ## API Endpoints 58 | 59 | ### User/Session Management 60 | * [`checkauth.cgi`](#checkauthcgi) - Checks the validity of the supplied JWT. 61 | * [`gettok.cgi`](#gettokcgi) - Returns the current session token 62 | * [`login.cgi`](#logincgi) - Logs in the user 63 | * [`logout.cgi`](#logoutcgi) - Logs out the user 64 | 65 | ### Device Management 66 | * [`info.cgi`](#infocgi) - Returns general device info (firmware versions, etc) 67 | * [`ip.cgi`](#ipcgi) - Returns the IP address of openSPOT 68 | * [`reboot.cgi`](#rebootcgi) - Reboot the openSPOT 69 | * [`status.cgi`](#statuscgi) - Returns openSPOT's current status 70 | 71 | ### Config Profile Management 72 | * [`config-export.cgi`](#config-exportcgi) - Export the currently active config profile settings 73 | * [`config-import.cgi`](#config-importcgi) - Import a config profile 74 | * [`cpsettings.cgi`](#cpsettingscgi) - Manage config profiles 75 | 76 | ### Other Settings 77 | * [`locationsettings.cgi`](#locationsettingscgi) - Manage the openSPOT's location 78 | * [`netsettings.cgi`](#netsettingscgi) - Manage network settings 79 | * [`passwordsettings.cgi`](#passwordsettingscgi) - Change openSPOT's password 80 | * [`spksettings.cgi`](#spksettingscgi) - Manage voice announcement settings 81 | 82 | ### Connector Management 83 | * [`connector.cgi`](#connectorcgi) - Manage openSPOT's active connector 84 | * [`connectorsettings.cgi`](#connectorsettingscgi) - Other settings for the connector 85 | 86 | ### Connector Settings 87 | * [`c4fmautocal.cgi`](#c4fmautocalcgi) - C4FM Auto-calibrations status 88 | * [`dcsxlxsettings.cgi`](#dcsxlxsettingscgi) - DCS/XLS connector settings 89 | * [`dmrautocal.cgi`](#dmrautocalcgi) - DMR auto-calibration status 90 | * [`dmrplussettings.cgi`](#dmrplussettingscgi) - DMRPlus connector settings 91 | * [`fcssettings.cgi`](#fcssettingscgi) - FCS connector settings 92 | * [`homebrewsettings.cgi`](#homebrewsettingscgi) - Homebrew connector settings 93 | * [`nullsettings.cgi`](#nullsettingscgi) - Null connector settings 94 | * [`refxrfsettings.cgi`](#refxrfsettingscgi) - REF/XRF connector settings 95 | * [`srfipconnclientsettings.cgi`](#srfipconnclientsettingscgi) - SharkRF IP Connector Client Setttings 96 | * [`srfipconnserversettings.cgi`](#srfipconnserversettingscgi) - SharkRF IP Connector Server Settings 97 | * [`status-srfipconnserver.cgi`](#status-srfipconnservercgi) - SharkRF IP Connector current status 98 | * [`ysfrefsettings.cgi`](#ysfrefsettingscgi) - YSFReflector connector settings 99 | 100 | ### Modem Management 101 | * [`modemcal.cgi`](#modemcalcgi) - Modem calibration settings 102 | * [`modemcwid.cgi`](#modemcwidcgi) - Modem CW ID settings 103 | * [`modemfreq.cgi`](#modemfreqcgi) - Modem TX/RX frequency & power settings 104 | * [`modemmode.cgi`](#modemmodecgi) - Current active modem settings 105 | * [`modemmodulation.cgi`](#modemmodulationcgi) - Active modem modulation mode 106 | * [`modemother.cgi`](#modemothercgi) - Other modem setings (call hang time, etc) 107 | * [`modempacket.cgi`](#modempacketcgi) - Modem packet settings 108 | * [`modemtdma.cgi`](#modemtdmacgi) - Modem TDMA settings 109 | 110 | ### Mode/Network-specific Settings 111 | * [`bmmsettings.cgi`](#bmmsettingscgi) - BrandMeister API settings 112 | * [`c4fmsettings.cgi`](#c4fmsettingscgi) - C4FM network settings 113 | * [`dmrsettings.cgi`](#dmrsettingscgi) - DMR settings 114 | * [`dstarsettings.cgi`](#dstarsettingscgi) - D-STAR settings 115 | * [`locksettings.cgi`](#locksettingscgi) - Callsign/CCS7 ID lock settings 116 | * [`quickcall.cgi`](#quickcallcgi) - Request a DMR quick-call 117 | * [`status-dmrsms.cgi`](#status-dmrsmscgi) - DMR SMS send status 118 | 119 | ---- 120 | 121 | ## User/Session Management 122 | 123 | ### checkauth.cgi 124 | 125 | Checks the validity of the supplied JWT. *success* is 1 if it's valid **and** 126 | the user has logged in previously. Also returns openSPOT's hostname and current 127 | IP address. *nopass* is 1 if openSPOT has no password set. 128 | 129 | Response: 130 | ```json 131 | { 132 | "success": 1, 133 | "nopass": 0, 134 | "hostname": "openspot", 135 | "ip_address": "192.168.3.99" 136 | } 137 | ``` 138 | 139 | ### gettok.cgi 140 | 141 | Doesn't take any parameters from a query. Returns the session token, which is 142 | a hexadecimal uint32_t (8 ASCII characters). 143 | 144 | Response: 145 | ```json 146 | { 147 | "token": "1f9a8b7c" 148 | } 149 | ``` 150 | 151 | ### login.cgi 152 | 153 | Logs in the user if the given token and digest is valid. Returns openSPOT's hostname 154 | and the JWT. 155 | 156 | Response: 157 | ```json 158 | { 159 | "hostname": "openspot", 160 | "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMjljODQwZSJ9.r3Oom8qVEAd1ceMMWibrMNsgu0DPgz-IG13MAzB-o5s" 161 | } 162 | ``` 163 | 164 | ### logout.cgi 165 | 166 | Logs out the user. 167 | 168 | Response: 169 | ```json 170 | {} 171 | ``` 172 | 173 | ## Device Management 174 | 175 | ### info.cgi 176 | 177 | Allows you to query (GET) general info about the device. 178 | *blver* is the bootloader version. *uid* is the device unique ID 179 | in hexadecimal. 180 | *uptime* is in seconds. *locked_to_country* is set to the country's 181 | ISO code if there's a lock active on the current device. 182 | 183 | Response: 184 | ```json 185 | { 186 | "hwver": "1.0", 187 | "locked_to_country": "", 188 | "swver": "0001", 189 | "subver": "433", 190 | "blver": "0001", 191 | "uptime": 123, 192 | "mac": "FE:28:00:00:00:FA", 193 | "uid": "abcdef" 194 | } 195 | ``` 196 | 197 | ### ip.cgi 198 | 199 | Returns the IP address of openSPOT. 200 | 201 | Response: 202 | ```json 203 | { 204 | "ip": "192.168.3.106" 205 | } 206 | ``` 207 | 208 | ### reboot.cgi 209 | 210 | Triggers a reboot. 211 | 212 | If *reset_config* is set to 1 in the query, it resets the default configuration after rebooting. 213 | If *bootloader* is 1, it reboots the unit to the bootloader. 214 | 215 | Query (optional): 216 | ```json 217 | { 218 | "reset_config": 1, 219 | "bootloader": 1 220 | } 221 | ``` 222 | Response: 223 | ```json 224 | {} 225 | ``` 226 | 227 | ### status.cgi 228 | 229 | Returns openSPOT's current status. 230 | 231 | *status* can be: 232 | - 0: Standby 233 | - 1: In call 234 | - 2: Connector not set 235 | - 3: Connector connecting 236 | - 4: Modem initializing 237 | - 5: Modem disconnected 238 | - 6: Modem HW/SW version mismatch 239 | - 7: Modem firmware upgrade in progress 240 | 241 | *rssi_tc0_values_dbm* and *rssi_tc1_values_dbm* contain RSSI values since 242 | the last call of *status.cgi*. If the current modem mode is non-TDMA, then 243 | ignore *rssi_tc1_values_dbm*. 244 | 245 | *dejitter_buf_tc0_pkts* and *dejitter_buf_tc1_pkts* contain dejitter buffer 246 | packet count values since the last call of *status.cgi*. If the current modem 247 | mode is non-TDMA, then ignore *dejitter_buf_tc1_pkts*. 248 | 249 | *ber_tc0_values* and *ber_tc1_values* contain the count of erroneous bits 250 | since the last call of *status.cgi*. If the current modem mode is non-TDMA, 251 | then ignore *ber_tc1_values*. 252 | 253 | The packet and byte UDP traffic counters are monotonically increasing 32 bit values. 254 | 255 | *callinfo* contains an array of call info structures. The first element of the 256 | structure is the destination callsign (or DMR ID as a string), the second element 257 | is the source callsign, and the third is the callinfo struct type. This is a 16-bit 258 | value, the meaning of the bits: 259 | 260 | - 0th bit (LSB): 0 - voice call, 1 - data call 261 | - 1st bit: 0 - call from net, 1 - call from modem/openSPOT 262 | - 2nd bit: 0 - group call, 1 - private call 263 | - 3rd bit: 0 - call end, 1 - call start 264 | - 4th bit: 1 - call started with late entry 265 | - 5th bit: 1 - call ended with timeout 266 | - 6th bit: 0 - TS1, 1 - TS2 267 | - 7th bit: 1 - received a talker alias 268 | - 8th bit: 1 - C4FM DN (VD) mode 1, 0 - C4FM DN (VD) mode 2 269 | - 9th bit: 1 - C4FM wide voice mode, 0 - C4FM digital narrow mode 270 | - 10th bit: 1 - DMR call 271 | - 11th bit: 1 - C4FM call 272 | - 12th bit: 1 - DSTAR call 273 | 274 | Other bits are currently unused. 275 | 276 | *connector* is the active connector ID (see connector.cgi's description for 277 | connector ID names). 278 | 279 | *primary* is 1 if the primary server is used by the current connector, and 280 | it's 0 if the backup server is used. 281 | 282 | *timeout_cp* is the config profile ID to switch on *timeout_cp_sec* timeout. 283 | *timeout_null_sec* is the null connector switch timeout. 284 | 285 | Response: 286 | ```json 287 | { 288 | "status": 0, 289 | "connector": 2, 290 | "timeout_cp": 0, 291 | "timeout_cp_sec": 0, 292 | "timeout_null_sec": 0, 293 | "rssi_tc0_values_dbm": [-60,-62,-65], 294 | "rssi_tc1_values_dbm": [-60,-62,-65], 295 | "dejitter_buf_tc0_pkts": [0, 1, 2], 296 | "dejitter_buf_tc1_pkts": [0, 1, 2], 297 | "ber_tc0_values": [0, 1, 2], 298 | "ber_tc1_values": [0, 1, 2], 299 | "invalid_seqnums": 5, 300 | "rx_pkts": 32, 301 | "rx_bytes": 14421, 302 | "tx_pkts": 32, 303 | "tx_bytes": 14421, 304 | "connected_to": "DCS001 A", 305 | "primary": 1, 306 | "callinfo": [["9","2161005",0], ["9","2161005",1032]] 307 | } 308 | ``` 309 | 310 | ## Config Profile Management 311 | 312 | ### config-export.cgi 313 | 314 | If you want to export the active config profile settings, you can POST 315 | a query to this CGI. You can request settings in chunks. The number of 316 | available chunks is in *chunk_count* (this can also be requested with a 317 | GET query). Each chunk is represented in string of hexadecimal character 318 | pairs. *config_size* is the count of valid config bytes in the file. 319 | The whole config's CRC is returned in *config_crc*. Note that *chunk* 320 | data in this example is truncated. 321 | 322 | Query (optional): 323 | ```json 324 | { 325 | "chunk_nr": 0 326 | } 327 | ``` 328 | Response: 329 | ```json 330 | { 331 | "config_size": 1458, 332 | "config_crc": "a9fd8832", 333 | "chunk_count": 3, 334 | "chunk_nr": 0, 335 | "chunk": "982443abcdef" 336 | } 337 | ``` 338 | 339 | ### config-import.cgi 340 | 341 | If you want to import the active config profile settings, you can POST 342 | a query to this CGI. 343 | 344 | *config_size* is the count of valid config bytes in the file. 345 | *chunk_size* is the length which this CGI waits *chunk* data in string 346 | of hexadecimal character pairs. 347 | *chunk_count* is the total number of *chunks* needed for a successful import. 348 | *active_cp_hostname* is the hostname of openSPOT. This is always returned 349 | because it may be changed after a successful import - in this case the caller 350 | knows on what address openSPOT will start listening on after the device 351 | reboots. Note that *chunk* data in this example is truncated. 352 | 353 | *status* can be the following: 354 | 355 | - 0: CONFIGAREA_IMPORT_STATUS_INITIALIZED 356 | - 1: CONFIGAREA_IMPORT_STATUS_NEED_MORE_CHUNKS 357 | - 2: CONFIGAREA_IMPORT_STATUS_SUCCESS 358 | - 3: CONFIGAREA_IMPORT_STATUS_STRUCT_VERSION_MISMATCH 359 | - 4: CONFIGAREA_IMPORT_STATUS_CRC_ERR 360 | - 5: CONFIGAREA_IMPORT_STATUS_INVALID_FILE 361 | - 6: CONFIGAREA_IMPORT_STATUS_FAIL 362 | 363 | *status* will always be 0 when calling this CGI without query parameters. 364 | 365 | Query (optional): 366 | ```json 367 | { 368 | "config_size": 1458, 369 | "config_crc": "a9fd8832", 370 | "chunk_nr": 0, 371 | "chunk": "982443abcdef" 372 | } 373 | ``` 374 | Response: 375 | ```json 376 | { 377 | "chunk_size": 1024, 378 | "chunk_count": 3, 379 | "active_cp_hostname": "openspot", 380 | "status": 0 381 | } 382 | ``` 383 | 384 | ### cpsettings.cgi 385 | 386 | Config profile settings query (GET)/change (POST). Returns currently 387 | active settings. 388 | *reboot* is 1 if the active config profile has been changed and openSPOT 389 | is rebooting. *active_cp_initialized* is 1 if the currently active config 390 | profile is initialized. The array *cp_names* contain each config profile's 391 | name. *timeoutchange_cp* is the profile number which should be activated 392 | after *rxtimeout_sec* seconds. 393 | 394 | Query (optional): 395 | ```json 396 | { 397 | "active_cp": 0, 398 | "timeoutchange_cp": 0, 399 | "rxtimeout_sec": 0, 400 | "active_cp_name": "default", 401 | "active_cp_copyto": 0 402 | } 403 | ``` 404 | Response: 405 | ```json 406 | { 407 | "reboot": 0, 408 | "active_cp": 0, 409 | "timeoutchange_cp": 0, 410 | "rxtimeout_sec": 0, 411 | "active_cp_hostname": "openspot", 412 | "active_cp_initialized": 1, 413 | "cp_names": ["default", "", "", "", ""] 414 | } 415 | ``` 416 | 417 | ## Other Settings 418 | 419 | ### locationsettings.cgi 420 | 421 | Location settings query (GET)/change (POST). Returns currently 422 | active settings. Country is the country code (2 chars) or the string "global". 423 | 424 | Query (optional): 425 | ```json 426 | { 427 | "country": "global", 428 | "latitude": "0.0", 429 | "longitude": "0.0", 430 | "height_agl": 0, 431 | "name": "" 432 | } 433 | ``` 434 | Response: 435 | ```json 436 | { 437 | "latitude": "0.0", 438 | "longitude": "0.0", 439 | "height_agl": 0, 440 | "name": "" 441 | } 442 | ``` 443 | 444 | ### netsettings.cgi 445 | 446 | Network settings query (GET)/change (POST). Returns currently active settings. 447 | 448 | *ip_config_mode* can be: 449 | - 0: DHCP 450 | - 1: DHCP with auto IP 451 | - 2: Auto IP 452 | - 3: Static IP 453 | 454 | Query (optional): 455 | ```json 456 | { 457 | "ip_config_mode": 0, 458 | "hostname": "openspot", 459 | "static_ip": "192.168.1.99", 460 | "static_mask": "255.255.255.0", 461 | "static_gw": "192.168.1.1", 462 | "static_dns1": "8.8.8.8", 463 | "static_dns2": "8.8.4.4", 464 | "usestaticdns": 1, 465 | "dejitter_queue_msec": 130 466 | } 467 | ``` 468 | Response: 469 | ```json 470 | { 471 | "ip_config_mode": 0, 472 | "hostname": "openspot", 473 | "static_ip": "192.168.1.99", 474 | "static_mask": "255.255.255.0", 475 | "static_gw": "192.168.1.1", 476 | "static_dns1": "8.8.8.8", 477 | "static_dns2": "8.8.4.4", 478 | "usestaticdns": 1, 479 | "dejitter_queue_msec": 130 480 | } 481 | ``` 482 | 483 | ### passwordsettings.cgi 484 | 485 | Allows you to change openSPOT's password. 486 | 487 | Query: 488 | ```json 489 | { 490 | "password": "openspot" 491 | } 492 | ``` 493 | Response: 494 | ```json 495 | {} 496 | ``` 497 | 498 | 499 | ### spksettings.cgi 500 | 501 | Voice announcement settings query (GET)/change (POST). Returns currently 502 | active settings. 503 | 504 | Query (optional): 505 | ```json 506 | { 507 | "enabled": 1, 508 | "shortbm": 0, 509 | "remote_only": 0, 510 | "host": "spk.sharkrf.com", 511 | "port": 65200, 512 | "src_dmr_id": 9998, 513 | "prof_dmr_id": 9000, 514 | "con_dmr_id": 9998, 515 | "ip_dmr_id": 9001 516 | } 517 | ``` 518 | Response: 519 | ```json 520 | { 521 | "enabled": 1, 522 | "shortbm": 0, 523 | "remote_only": 0, 524 | "host": "spk.sharkrf.com", 525 | "port": 65200, 526 | "src_dmr_id": 9998, 527 | "prof_dmr_id": 9000, 528 | "con_dmr_id": 9998, 529 | "ip_dmr_id": 9001 530 | } 531 | ``` 532 | 533 | ## Connector Management 534 | 535 | ### connector.cgi 536 | 537 | openSPOT's active connector query (GET)/change (POST). 538 | 539 | Valid connector IDs: 540 | 541 | - 0: No connector set. 542 | - 1: DMRplus 543 | - 2: Homebrew 544 | - 3: TS repeat 545 | - 4: DCS/XLX 546 | - 5: FCS 547 | - 6: SharkRF IP Connector Client 548 | - 7: SharkRF IP Connector Server 549 | - 8: DMR demodulation mode auto calibration 550 | - 9: REF/XRF 551 | - 10: YSFReflector 552 | 553 | Query (optional): 554 | ```json 555 | { 556 | "connector": 0 557 | } 558 | ``` 559 | Response: 560 | ```json 561 | { 562 | "connector": 0 563 | } 564 | ``` 565 | 566 | ### connectorsettings.cgi 567 | 568 | Connector other settings query (GET)/change (POST). Returns currently 569 | active settings. *rxtimeout_sec* is the change to null connector timeout. 570 | 571 | Query (optional): 572 | ```json 573 | { 574 | "rxtimeout_sec": 0 575 | } 576 | ``` 577 | Response: 578 | ```json 579 | { 580 | "rxtimeout_sec": 0 581 | } 582 | ``` 583 | 584 | ## Connector Settings 585 | 586 | ### c4fmautocal.cgi 587 | 588 | You can periodically query (GET) this CGI to get current C4FM 589 | demodulation mode auto calibration status. Also you can change 590 | this connector's modem RX/TX frequencies. When the frequencies 591 | are changed, the connector is restarted. 592 | 593 | State can be: 594 | 595 | - 0: idle 596 | - 1: calibrating 597 | - 2: finished, result available 598 | - 3: modem is not in C4FM half deviation mode 599 | 600 | Progress is in percent. Result is the auto calibrated demodulation 601 | mode (0 - A, 1 - B, 2 - C, etc.) 602 | 603 | Query (optional): 604 | ```json 605 | { 606 | "rx_freq": 436000000, 607 | "tx_freq": 436000000, 608 | } 609 | ``` 610 | Response: 611 | ```json 612 | { 613 | "rx_freq": 436000000, 614 | "tx_freq": 436000000, 615 | "state": 1, 616 | "progress": 56, 617 | "result": 2 618 | } 619 | ``` 620 | 621 | ### dcsxlxsettings.cgi 622 | 623 | DCS/XLX connector settings query (GET)/change (POST). Returns currently 624 | active settings. 625 | 626 | Query (optional): 627 | ```json 628 | { 629 | "rx_freq": 436000000, 630 | "tx_freq": 436000000, 631 | "server_host": "", 632 | "port": 12345, 633 | "ccs_port": 12345, 634 | "callsign": "", 635 | "local_module": "A", 636 | "reflector": "DCS025", 637 | "remote_module": "Z", 638 | "rx_timeout_sec": 30 639 | } 640 | ``` 641 | Response: 642 | ```json 643 | { 644 | "rx_freq": 436000000, 645 | "tx_freq": 436000000, 646 | "server_host": "", 647 | "port": 12345, 648 | "ccs_port": 12345, 649 | "callsign": "", 650 | "local_module": "A", 651 | "reflector": "DCS025", 652 | "remote_module": "Z", 653 | "rx_timeout_sec": 1 654 | } 655 | ``` 656 | 657 | ### dmrautocal.cgi 658 | 659 | You can periodically query (GET) this CGI to get current DMR 660 | demodulation mode auto calibration status. Also you can change 661 | this connector's modem RX/TX frequencies. When the frequencies 662 | are changed, the connector is restarted. 663 | 664 | State can be: 665 | 666 | - 0: idle 667 | - 1: calibrating 668 | - 2: finished, result available 669 | - 3: modem is not in DMR mode 670 | 671 | Progress is in percent. Result is the auto calibrated demodulation 672 | mode (0 - A, 1 - B, 2 - C, etc.) 673 | 674 | Query (optional): 675 | ```json 676 | { 677 | "rx_freq": 436000000, 678 | "tx_freq": 436000000, 679 | } 680 | ``` 681 | Response: 682 | ```json 683 | { 684 | "rx_freq": 436000000, 685 | "tx_freq": 436000000, 686 | "state": 1, 687 | "progress": 56, 688 | "result": 2 689 | } 690 | ``` 691 | 692 | ### dmrplussettings.cgi 693 | 694 | DMRplus connector settings query (GET)/change (POST). Returns currently 695 | active settings. 696 | 697 | Query (optional): 698 | ```json 699 | { 700 | "rx_freq": 436000000, 701 | "tx_freq": 436000000, 702 | "server_host": "", 703 | "port": 8880, 704 | "dmr_id": "", 705 | "reflector_id": 0, 706 | "keepalive_interval_sec": 1, 707 | "rx_timeout_sec": 10 708 | } 709 | ``` 710 | Response: 711 | ```json 712 | { 713 | "rx_freq": 436000000, 714 | "tx_freq": 436000000, 715 | "server_host": "", 716 | "port": 8880, 717 | "dmr_id": "", 718 | "reflector_id": 0, 719 | "keepalive_interval_sec": 1, 720 | "rx_timeout_sec": 10 721 | } 722 | ``` 723 | 724 | ### fcssettings.cgi 725 | 726 | FCS connector settings query (GET)/change (POST). Returns currently 727 | active settings. 728 | 729 | Query (optional): 730 | ```json 731 | { 732 | "server_host": "fcs001.xreflector.net", 733 | "rx_freq": 436000000, 734 | "tx_freq": 436000000, 735 | "port": 12345, 736 | "callsign": "", 737 | "ccs7_id": 2161005, 738 | "reflector": "FCS001", 739 | "room_number": 25, 740 | "keepalive_interval_sec": 1, 741 | "rx_timeout_sec": 30 742 | } 743 | ``` 744 | Response: 745 | ```json 746 | { 747 | "rx_freq": 436000000, 748 | "tx_freq": 436000000, 749 | "server_host": "fcs001.xreflector.net", 750 | "port": 12345, 751 | "callsign": "", 752 | "ccs7_id": 2161005, 753 | "reflector": "FCS001", 754 | "room_number": 25, 755 | "keepalive_interval_sec": 1, 756 | "rx_timeout_sec": 10 757 | } 758 | ``` 759 | 760 | ### homebrewsettings.cgi 761 | 762 | Homebrew connector settings query (GET)/change (POST). Returns currently 763 | active settings. 764 | 765 | Valid *autocon_calltype*, *c4fm_dstcalltype* and *reroute_calltype* values: 766 | 0 - group call, 1 - private call. 767 | 768 | For more information about the MMDVM options field, see 769 | [this](https://github.com/g4klx/MMDVMHost/blob/master/DMRplus_startup_options.md) description. 770 | 771 | Query (optional): 772 | ```json 773 | { 774 | "rx_freq": 436000000, 775 | "tx_freq": 436000000, 776 | "server_host": "", 777 | "port": 62030, 778 | "mmdvm_mode": 0, 779 | "mmdvm_options": "", 780 | "callsign": "", 781 | "password": "", 782 | "b_server_host": "", 783 | "b_port": 62030, 784 | "b_password": "", 785 | "b_toggle_timeout_sec": 60, 786 | "repeater_id": 901234, 787 | "autocon_id": 4771, 788 | "autocon_calltype": 0, 789 | "autocon_tdma_channel": 0, 790 | "autocon_interval_sec": 500, 791 | "autocon_discon": 0, 792 | "dmo_tdma_channel": 0, 793 | "c4fm_dstid": 9, 794 | "c4fm_dstcalltype": 0, 795 | "reroute_id": 9990, 796 | "reroute_calltype": 1, 797 | "keepalive_interval_sec": 5, 798 | "rx_timeout_sec": 30 799 | } 800 | ``` 801 | Response: 802 | ```json 803 | { 804 | "rx_freq": 436000000, 805 | "tx_freq": 436000000, 806 | "server_host": "", 807 | "port": 62030, 808 | "mmdvm_mode": 0, 809 | "mmdvm_options": "", 810 | "callsign": "", 811 | "password": "", 812 | "b_server_host": "", 813 | "b_port": 62030, 814 | "b_password": "", 815 | "b_toggle_timeout_sec": 60, 816 | "repeater_id": 901234, 817 | "autocon_id": 4771, 818 | "autocon_tdma_channel": 0, 819 | "autocon_interval_sec": 500, 820 | "autocon_discon": 0, 821 | "dmo_tdma_channel": 0, 822 | "c4fm_dstid": 9, 823 | "c4fm_dstcalltype": 0, 824 | "reroute_id": 9990, 825 | "reroute_calltype": 1, 826 | "keepalive_interval_sec": 5, 827 | "rx_timeout_sec": 30 828 | } 829 | ``` 830 | 831 | ### nullsettings.cgi 832 | 833 | Null connector settings query (GET)/change (POST). Returns currently 834 | active settings. 835 | 836 | Query (optional): 837 | ```json 838 | { 839 | "rx_freq": 436000000, 840 | "tx_freq": 436000000 841 | } 842 | ``` 843 | Response: 844 | ```json 845 | { 846 | "rx_freq": 436000000, 847 | "tx_freq": 436000000 848 | } 849 | ``` 850 | 851 | 852 | ### refxrfsettings.cgi 853 | 854 | REF/XRF connector settings query (GET)/change (POST). Returns currently 855 | active settings. 856 | 857 | *allow_g* is the "always allow module G to modem" setting. 858 | 859 | Query (optional): 860 | ```json 861 | { 862 | "rx_freq": 436000000, 863 | "tx_freq": 436000000, 864 | "server_host": "", 865 | "port": 12345, 866 | "ccs_port": 12345, 867 | "callsign": "", 868 | "local_module": "D", 869 | "reflector": "REF001", 870 | "remote_module": "C", 871 | "allow_g": 1, 872 | "rx_timeout_sec": 30 873 | } 874 | ``` 875 | Response: 876 | ```json 877 | { 878 | "rx_freq": 436000000, 879 | "tx_freq": 436000000, 880 | "server_host": "", 881 | "port": 12345, 882 | "ccs_port": 12345, 883 | "callsign": "", 884 | "local_module": "D", 885 | "reflector": "REF001", 886 | "remote_module": "C", 887 | "allow_g": 1, 888 | "rx_timeout_sec": 1 889 | } 890 | ``` 891 | 892 | ### srfipconnclientsettings.cgi 893 | 894 | SharkRF IP Connector Client settings query (GET)/change (POST). 895 | Returns currently active settings. 896 | 897 | Query (optional): 898 | ```json 899 | { 900 | "rx_freq": 436000000, 901 | "tx_freq": 436000000, 902 | "server_host": "192.168.3.120", 903 | "port": 65100, 904 | "id": 2161005, 905 | "password": "abcdefgh", 906 | "callsign": "", 907 | "keepalive_interval_sec": 5, 908 | "rx_timeout_sec": 30 909 | } 910 | ``` 911 | Response: 912 | ```json 913 | { 914 | "rx_freq": 436000000, 915 | "tx_freq": 436000000, 916 | "server_host": "192.168.3.120", 917 | "port": 65100, 918 | "id": 2161005, 919 | "password": "abcdefgh", 920 | "callsign": "", 921 | "keepalive_interval_sec": 5, 922 | "rx_timeout_sec": 30 923 | } 924 | ``` 925 | 926 | ### srfipconnserversettings.cgi 927 | 928 | SharkRF IP Connector Server settings query (GET)/change (POST). 929 | Returns currently active settings. 930 | 931 | Query (optional): 932 | ```json 933 | { 934 | "rx_freq": 436000000, 935 | "tx_freq": 436000000, 936 | "port": 65100, 937 | "password": "abcdefgh", 938 | "rx_timeout_sec": 30 939 | } 940 | ``` 941 | Response: 942 | ```json 943 | { 944 | "rx_freq": 436000000, 945 | "tx_freq": 436000000, 946 | "port": 65100, 947 | "password": "abcdefgh", 948 | "rx_timeout_sec": 30 949 | } 950 | ``` 951 | 952 | ### status-srfipconnserver.cgi 953 | 954 | Returns the SharkRF IP Connector Server's current status, if it's the 955 | active connector. Otherwise it'll return 400 Bad Request. 956 | 957 | *client_connected* is 1 if a client is connected. 958 | 959 | Response: 960 | ```json 961 | { 962 | "client_connected": 0, 963 | "client_id": 1234, 964 | "client_callsign": "" 965 | } 966 | ``` 967 | 968 | ### ysfrefsettings.cgi 969 | 970 | YSFReflector connector settings query (GET)/change (POST). Returns currently 971 | active settings. 972 | 973 | Query (optional): 974 | ```json 975 | { 976 | "server_host": "", 977 | "rx_freq": 436000000, 978 | "tx_freq": 436000000, 979 | "port": 42000, 980 | "callsign": "", 981 | "keepalive_interval_sec": 1, 982 | "rx_timeout_sec": 30 983 | } 984 | ``` 985 | Response: 986 | ```json 987 | { 988 | "rx_freq": 436000000, 989 | "tx_freq": 436000000, 990 | "server_host": "", 991 | "port": 42000, 992 | "callsign": "", 993 | "keepalive_interval_sec": 1, 994 | "rx_timeout_sec": 10 995 | } 996 | ``` 997 | 998 | ## Modem Management 999 | 1000 | ### modemcal.cgi 1001 | 1002 | Modem calibration settings query (GET)/change (POST). Returns currently 1003 | active settings. *modem_init_delay_ms* is the time needed for the modem 1004 | to calibrate and initialize. 1005 | 1006 | Query (optional): 1007 | ```json 1008 | { 1009 | "auto_calibration": 1, 1010 | "recalibrate_temp_diff_in_celsius": 10, 1011 | "recalibrate_rf_ic_temp_diff_in_celsius": 10, 1012 | "temp_read_interval_in_sec": 10, 1013 | "temp_read_delay_in_sec_after_sync_lost": 10, 1014 | "quick_calibrate_delay_in_sec_after_sync_lost": 10 1015 | } 1016 | ``` 1017 | Response: 1018 | ```json 1019 | { 1020 | "modem_init_delay_ms": 3500, 1021 | "auto_calibration": 1, 1022 | "recalibrate_temp_diff_in_celsius": 10, 1023 | "recalibrate_rf_ic_temp_diff_in_celsius": 10, 1024 | "temp_read_interval_in_sec": 10, 1025 | "temp_read_delay_in_sec_after_sync_lost": 10, 1026 | "quick_calibrate_delay_in_sec_after_sync_lost": 10 1027 | } 1028 | ``` 1029 | 1030 | ### modemcwid.cgi 1031 | 1032 | Modem CW ID settings query (GET)/change (POST). Returns currently 1033 | active settings. 1034 | 1035 | Query (optional): 1036 | ```json 1037 | { 1038 | "cwid": "HA2NON", 1039 | "wpm": 25, 1040 | "interval_sec": 600, 1041 | "delay_sec": 30 1042 | } 1043 | ``` 1044 | Response: 1045 | ```json 1046 | { 1047 | "cwid": "HA2NON", 1048 | "wpm": 25, 1049 | "interval_sec": 600, 1050 | "delay_sec": 30 1051 | } 1052 | ``` 1053 | 1054 | ### modemfreq.cgi 1055 | 1056 | If you want to change the current RX, TX frequency or TX power 1057 | without reinitializing the modem, you can POST a query to this CGI. 1058 | Returns currently active settings. *modem_init_delay_ms* is the time needed 1059 | for the modem to calibrate and initialize. 1060 | 1061 | DMR demodulation mode values: 0 - A, 1 - B, 2 - C etc. 1062 | 1063 | Query (optional): 1064 | ```json 1065 | { 1066 | "rx_frequency": 433450000, 1067 | "dmr_demodmode": 0, 1068 | "tx_frequency": 433450000, 1069 | "tx_power_percent": 100 1070 | } 1071 | ``` 1072 | Response: 1073 | ```json 1074 | { 1075 | "modem_init_delay_ms": 100, 1076 | "rx_frequency": 433450000, 1077 | "dmr_demodmode": 0, 1078 | "tx_frequency": 433450000, 1079 | "tx_power_percent": 100 1080 | } 1081 | ``` 1082 | 1083 | 1084 | ### modemmode.cgi 1085 | 1086 | Current modem mode query (GET)/change (POST). Returns currently 1087 | active settings. *modem_init_delay_ms* is the time needed for 1088 | the modem to calibrate and initialize. 1089 | 1090 | - *mode* can be: 1091 | - 0: Idle 1092 | - 1: Raw 1093 | - 2: DMR 1094 | - 3: D-STAR 1095 | - 4: C4FM 1096 | - 5: C4FM half deviation mode 1097 | 1098 | - *submode* can be: 1099 | - 0: No submode set 1100 | - 1: DMR Hotspot 1101 | - 2: DMR MS 1102 | - 3: DMR BS 1103 | 1104 | Query (optional): 1105 | ```json 1106 | { 1107 | "mode": 0, 1108 | "submode": 0 1109 | } 1110 | ``` 1111 | Response: 1112 | ```json 1113 | { 1114 | "modem_init_delay_ms": 3500, 1115 | "mode": 0, 1116 | "submode": 0 1117 | } 1118 | ``` 1119 | 1120 | ### modemmodulation.cgi 1121 | 1122 | Modem modulation mode query (GET)/change (POST). Returns currently 1123 | active settings. *modem_init_delay_ms* is the time needed for the 1124 | modem to calibrate and initialize. 1125 | 1126 | - *modulation_mode* can be: 1127 | - 0: 2FSK 1128 | - 1: 2FSK Raised Cosine 1129 | - 2: 4FSK 1130 | - 3: 4FSK Raised Cosine 1131 | 1132 | Query (optional): 1133 | ```json 1134 | { 1135 | "modulation_mode": 0, 1136 | "bitrate": 9600, 1137 | "inner_deviation_hz": 648 1138 | } 1139 | ``` 1140 | Response: 1141 | ```json 1142 | { 1143 | "modem_init_delay_ms": 3500, 1144 | "modulation_mode": 0, 1145 | "bitrate": 9600, 1146 | "inner_deviation_hz": 648 1147 | } 1148 | ``` 1149 | 1150 | ### modemother.cgi 1151 | 1152 | Other modem settings query (GET)/change (POST). Returns currently 1153 | active settings. *modem_init_delay_ms* is the time needed for the 1154 | modem to calibrate and initialize. 1155 | 1156 | *agc_auto* and *external_vco* fields are booleans. 1157 | 1158 | Query (optional): 1159 | ```json 1160 | { 1161 | "rssi_avg_sample_count": 5, 1162 | "bclo_dbm": -80, 1163 | "high_gain_low_linearity": 0, 1164 | "agc_auto": 0, 1165 | "agc_low_threshold_dbm": -50, 1166 | "agc_high_threshold_dbm": -80, 1167 | "external_vco": 0, 1168 | "call_hang_time_ms": 3000 1169 | } 1170 | ``` 1171 | Response: 1172 | ```json 1173 | { 1174 | "modem_init_delay_ms": 3500, 1175 | "rssi_avg_sample_count": 5, 1176 | "bclo_dbm": -80, 1177 | "high_gain_low_linearity": 0, 1178 | "agc_auto": 0, 1179 | "agc_low_threshold_dbm": -50, 1180 | "agc_high_threshold_dbm": -80, 1181 | "external_vco": 0, 1182 | "call_hang_time_ms": 3000 1183 | } 1184 | ``` 1185 | 1186 | ### modempacket.cgi 1187 | 1188 | Modem packet settings query (GET)/change (POST). Returns currently 1189 | active settings. *modem_init_delay_ms* is the time needed for the 1190 | modem to calibrate and initialize. 1191 | 1192 | Query (optional): 1193 | ```json 1194 | { 1195 | "packet_size_in_bits": 288, 1196 | "sync_word_length_in_bits": 24, 1197 | "sync_word_pos_in_packet_in_bits": 0, 1198 | "sync_word_count": 1, 1199 | "sync_word1": "4f5de8", 1200 | "sync_word2": "445566" 1201 | } 1202 | ``` 1203 | Response: 1204 | ```json 1205 | { 1206 | "modem_init_delay_ms": 3500, 1207 | "packet_size_in_bits": 288, 1208 | "sync_word_length_in_bits": 24, 1209 | "sync_word_pos_in_packet_in_bits": 0, 1210 | "sync_word_count": 1, 1211 | "sync_word1": "4f5de8", 1212 | "sync_word2": "445566" 1213 | } 1214 | ``` 1215 | 1216 | ### modemtdma.cgi 1217 | 1218 | Modem TDMA settings query (GET)/change (POST). Returns currently 1219 | active settings. *modem_init_delay_ms* is the time needed for the 1220 | modem to calibrate and initialize. 1221 | 1222 | Query (optional): 1223 | ```json 1224 | { 1225 | "tdma_enabled": 1, 1226 | "tdma_pit_calibration_wait_for_packets_num": 2, 1227 | "tdma_pit_calibration_compensation_multiplier": 1.2, 1228 | "tdma_needed_sync_frames_for_tdma_channel_be_valid": 1 1229 | } 1230 | ``` 1231 | Response: 1232 | ```json 1233 | { 1234 | "modem_init_delay_ms": 3500, 1235 | "tdma_enabled": 1, 1236 | "tdma_pit_calibration_wait_for_packets_num": 2, 1237 | "tdma_pit_calibration_compensation_multiplier": 1.2, 1238 | "tdma_needed_sync_frames_for_tdma_channel_be_valid": 1 1239 | } 1240 | ``` 1241 | 1242 | ## Mode/Network-specific Settings 1243 | 1244 | ### bmmsettings.cgi 1245 | 1246 | BrandMeister API settings query (GET)/change (POST). Returns currently 1247 | active settings. 1248 | 1249 | Query (optional): 1250 | ```json 1251 | { 1252 | "apikey": "abcdef" 1253 | } 1254 | ``` 1255 | Response: 1256 | ```json 1257 | { 1258 | "apikey": "abcdef" 1259 | } 1260 | ``` 1261 | 1262 | ### c4fmsettings.cgi 1263 | 1264 | General C4FM settings query (GET)/change (POST). Returns currently 1265 | active settings. *dmr_def_cs* is the default C4FM callsign for DMR calls. 1266 | 1267 | If *only_rx_with_sql_code_en* is 1, then the modem only processes C4FM 1268 | calls with SQL code *only_rx_with_sql_code*. 1269 | 1270 | If *force_sql_code_to_modem_en* is 1, all C4FM frames sent to the 1271 | modem will have SQL code *force_sql_code_to_modem* set. 1272 | 1273 | If *force_sql_code_to_net_en* is 1, all C4FM frames sent to the 1274 | network will have SQL code *force_sql_code_to_net* set. 1275 | 1276 | Query (optional): 1277 | ```json 1278 | { 1279 | "dtmf_automute_cmds": 1, 1280 | "dtmf_pcode": "*", 1281 | "dtmf_gcode": "#", 1282 | "transmit_rx_confirmation": 1, 1283 | "dmr_def_cs": "", 1284 | "only_rx_with_sql_code_en": 0, 1285 | "only_rx_with_sql_code": 123, 1286 | "force_sql_code_to_modem_en": 0, 1287 | "force_sql_code_to_modem": 123, 1288 | "force_sql_code_to_net_en": 0, 1289 | "force_sql_code_to_net": 123 1290 | } 1291 | ``` 1292 | Response: 1293 | ```json 1294 | { 1295 | "dtmf_automute_cmds": 1, 1296 | "dtmf_pcode": "*", 1297 | "dtmf_gcode": "#", 1298 | "transmit_rx_confirmation": 1, 1299 | "dmr_def_cs": "", 1300 | "only_rx_with_sql_code_en": 0, 1301 | "only_rx_with_sql_code": 123, 1302 | "force_sql_code_to_modem_en": 0, 1303 | "force_sql_code_to_modem": 123, 1304 | "force_sql_code_to_net_en": 0, 1305 | "force_sql_code_to_net": 123 1306 | } 1307 | ``` 1308 | 1309 | ### dmrsettings.cgi 1310 | 1311 | General DMR settings query (GET)/change (POST). Returns currently 1312 | active settings. 1313 | 1314 | If *no_inband* is set to 1, in-band DMR data like GPS pos. or talker alias 1315 | will not be sent to the modem. 1316 | 1317 | Query (optional): 1318 | ```json 1319 | { 1320 | "force_talker_alias": "abcd", 1321 | "no_inband": 0, 1322 | "cc": 1, 1323 | "echo_id": 9999, 1324 | "default_c4fm_id": 0, 1325 | "transmit_idle_in_idle_tx_tdma_channel": 1 1326 | } 1327 | ``` 1328 | Response: 1329 | ```json 1330 | { 1331 | "force_talker_alias": "abcd", 1332 | "no_inband": 0, 1333 | "cc": 1, 1334 | "echo_id": 9999, 1335 | "default_c4fm_id": 0, 1336 | "transmit_idle_in_idle_tx_tdma_channel": 1 1337 | } 1338 | ``` 1339 | 1340 | ### dstarsettings.cgi 1341 | 1342 | General D-STAR settings query (GET)/change (POST). Returns currently 1343 | active settings. 1344 | 1345 | Query (optional): 1346 | ```json 1347 | { 1348 | "echo_callsign": " E", 1349 | "transmit_rx_confirmation": 1 1350 | } 1351 | ``` 1352 | Response: 1353 | ```json 1354 | { 1355 | "echo_callsign": " E", 1356 | "transmit_rx_confirmation": 1 1357 | } 1358 | ``` 1359 | 1360 | 1361 | ### locksettings.cgi 1362 | 1363 | Callsign/CCS7 ID lock settings query (GET)/change (POST). Returns currently 1364 | active settings. 1365 | 1366 | Query (optional): 1367 | ```json 1368 | { 1369 | "id1": 2161005, 1370 | "callsign1": "HA2NON", 1371 | "id2": 2161006, 1372 | "callsign2": "HG1MA", 1373 | "id3": 0, 1374 | "callsign3": "" 1375 | } 1376 | ``` 1377 | Response: 1378 | ```json 1379 | { 1380 | "id1": 2161005, 1381 | "callsign1": "HA2NON", 1382 | "id2": 2161006, 1383 | "callsign2": "HG1MA", 1384 | "id3": 0, 1385 | "callsign3": "" 1386 | } 1387 | ``` 1388 | 1389 | ### quickcall.cgi 1390 | 1391 | If you want to request a quick DMR call, you can POST a query to this CGI. 1392 | 1393 | Valid *call_type* values: 0 - group call, 1 - private call. 1394 | 1395 | Query (optional): 1396 | ```json 1397 | { 1398 | "dst_id": 4000, 1399 | "call_type": 0, 1400 | "tdma_channel": 0 1401 | } 1402 | ``` 1403 | Response: 1404 | ```json 1405 | {} 1406 | ``` 1407 | 1408 | ### status-dmrsms.cgi 1409 | 1410 | Returns current status of DMR SMS sending, if the modem is in DMR mode. 1411 | Otherwise it returns 400 Bad Request. It also handles SMS sending. 1412 | 1413 | Call types: 0 - private, 1 - group. 1414 | Format IDs: 0 - ETSI, 1 - UDP, 2 - UDP/Chinese. See user manual for more info. 1415 | If a new message is received, *rx_msg_valid* is 1. 1416 | Setting a new *send_srcid* in the query overwrites the *default_srcid*. 1417 | If *send_to_modem* is 0, the SMS will be sent to the currently active connector. 1418 | If *intercept_net_msgs* is 1, then SMS messages coming from the network to 1419 | the *default_srcid* will be processed. 1420 | If *only_save* is 1, the SMS will not get sent, only the *send_srcid* and 1421 | *intercept_net* settings will be stored. 1422 | 1423 | Messages are in hexadecimal UTF16BE format. Example: "BEER" = "0042004500450052" 1424 | Max. message length which can be sent is currently 75 UTF16BE characters (150 1425 | hex char pairs). 1426 | 1427 | Query (optional): 1428 | ```json 1429 | { 1430 | "only_save": 0, 1431 | "intercept_net_msgs": 0, 1432 | "send_dstid": 2161005, 1433 | "send_calltype": 0, 1434 | "send_srcid": 9998, 1435 | "send_format": 0, 1436 | "send_tdma_channel": 0, 1437 | "send_to_modem": 0, 1438 | "send_msg": "0042004500450052" 1439 | } 1440 | ``` 1441 | 1442 | Response: 1443 | ```json 1444 | { 1445 | "default_srcid": 9998, 1446 | "intercept_net_msgs": 0, 1447 | "send_ongoing": 0, 1448 | "send_success": 1, 1449 | "send_fail": 0, 1450 | "rx_msg_valid": 0, 1451 | "rx_msg_srcid": 1234, 1452 | "rx_msg_dstid": 9998, 1453 | "rx_msg_calltype": 0, 1454 | "rx_msg_format": 0, 1455 | "rx_msg_from_modem": 0, 1456 | "rx_msg": "0042004500450052" 1457 | } 1458 | ``` 1459 | 1460 | --------------------------------------------------------------------------------