Initial commit: FieldLogger MAUI app with Maglink BLE support

Added Maglink RTK GNSS receiver integration with correct BLE UUIDs and device name filtering (ML-* prefix).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
brentperteet
2026-07-06 13:46:50 -05:00
commit b602b762c9
79 changed files with 5807 additions and 0 deletions

181
doc/AT_Commands_Guide_EN.md Normal file
View File

@@ -0,0 +1,181 @@
# AT Commands User Guide
This document provides detailed usage instructions for the main AT commands supported by the H11 device.
## 1. AT+DEV_INIT_STA=GET
**Function**: Query device initialization status
**Command Format**:
```
AT+DEV_INIT_STA=GET
```
**Response Example**:
```
AT+DEV_INIT_STA=GET,4G,<4G_link>,<SIM_ready>,<NTRIP_flag>,<CSQ>,<data_back>,<upload_size>,<NTRIP_size>,GNSS,<status>,<reserved>,star,<SNR45>,<SNR48>,<SNR50>,<visible_stars>
OK
```
**Parameter Explanation**:
- `<4G_link>`: 4G network connection status (0=disconnected, 1=connected)
- `<SIM_ready>`: SIM card ready status (0=not ready, 1=ready)
- `<NTRIP_flag>`: NTRIP connection status (0=disconnected, 1=connected)
- `<CSQ>`: Signal quality (0-31, higher is better)
- `<data_back>`: Data upload status (0=idle, 1=uploading)
- `<upload_size>`: Upload queue size (bytes)
- `<NTRIP_size>`: NTRIP data queue size (bytes)
- `<status>`: GNSS module status
- `<SNR45>`, `<SNR48>`, `<SNR50>`: Number of satellites with SNR > 45/48/50 dB
- `<visible_stars>`: Total number of visible satellites
**Use Cases**:
- Check device module initialization status after startup
- Diagnose device connectivity and module status
- Monitor network and GNSS module status
---
## 2. AT+NEMATIME=SET
**Function**: Set NMEA output frequency
**Command Format**:
```
AT+NEMATIME=SET,<frequency>
```
**Parameters**:
- `<frequency>`: Output frequency in Hz (supported values: 1, 2, 5, 10)
**Response Example**:
```
AT+NEMATIME=SET
OK
```
**Error Response**:
```
AT+NEMATIME=SET
ERROR
```
**Use Cases**:
- Configure GNSS position data output rate
- Adjust positioning data update frequency based on application requirements
- Balance between update rate and power consumption
---
## 3. AT+NEMATIME=GET
**Function**: Query current NMEA output frequency
**Command Format**:
```
AT+NEMATIME=GET
```
**Response Example**:
```
AT+NEMATIME=GET,<frequency>
OK
```
**Parameter Explanation**:
- `<frequency>`: Current NMEA output frequency in Hz
**Use Cases**:
- Verify the current NMEA output frequency configuration
- Ensure frequency configuration has taken effect
- Troubleshoot positioning data update issues
---
## 4. AT+RTCMBASEPOS=GET
**Function**: Query base station position and distance from RTCM data source
**Command Format**:
```
AT+RTCMBASEPOS=GET
```
**Response Example** (when RTCM data is available):
```
AT+RTCMBASEPOS=GET,<latitude>,<longitude>,<altitude>,<distance>
OK
```
**Response Example** (when RTCM data is not available):
```
AT+RTCMBASEPOS=GET,0.0,0.0,0.0,0.0
OK
```
**Parameter Explanation**:
- `<latitude>`: Base station latitude in degrees (positive=North, negative=South)
- `<longitude>`: Base station longitude in degrees (positive=East, negative=West)
- `<altitude>`: Base station altitude/elevation in meters
- `<distance>`: Distance from device to base station in meters
**Use Cases**:
- Obtain current base station position information in RTK mode
- Monitor distance to reference station
- Assess differential positioning quality
- Verify RTK connection status
---
## Command Usage Examples
### Query device initialization status
```
→ AT+DEV_INIT_STA=GET
← AT+DEV_INIT_STA=GET,4G,1,1,1,25,0,0,1024,GNSS,1,0,star,8,5,2,12
← OK
```
### Set NMEA frequency to 1Hz
```
→ AT+NEMATIME=SET,1
← AT+NEMATIME=SET
← OK
```
### Query current NMEA frequency
```
→ AT+NEMATIME=GET
← AT+NEMATIME=GET,1
← OK
```
### Query base station position and distance
```
→ AT+RTCMBASEPOS=GET
← AT+RTCMBASEPOS=GET,31.135370,121.287729,22.467,1234.56
← OK
```
---
## Important Notes
1. **Command Format**: All AT commands start with "AT" and end with "\r\n"
2. **Case Insensitive**: Commands are case-insensitive
3. **Response Timeout**: Recommended timeout for each command is 5 seconds
4. **Response Format**: Successful execution returns "OK", failure returns "ERROR"
5. **RTCM Base Station Info**: Base station position is only available after receiving valid RTCM 1005/1006 messages
6. **Frequency Setting**: Device may need restart for frequency changes to take effect
7. **Line Ending**: Use CR+LF (\r\n) as line terminator
8. **Serial Parameters**: Default baud rate is 115200 bps
---
## Related Information
- **NMEA**: National Marine Electronics Association protocol, widely used in GPS/GNSS devices
- **RTCM**: Radio Technical Commission for Maritime Services, data format for differential positioning
- **RTK**: Real-Time Kinematic positioning technology
- **CSQ**: Signal Quality indicator (0-31, where 31 is excellent)
- **SNR**: Signal-to-Noise Ratio measured in dB

View File

@@ -0,0 +1,544 @@
# AT Commands Reference Guide
## Overview
This document provides detailed information about AT commands for controlling the H11hw GNSS RTK device via Bluetooth. All commands follow the format `AT+COMMAND=ACTION` where ACTION is either `SET` or `GET`.
**Response Format:**
- Success: `AT+COMMAND=ACTION\r\nOK\r\n`
- Error: `AT+COMMAND=ACTION\r\nERROR\r\n`
---
## 1. APN Configuration
Configure the APN (Access Point Name) for cellular network connection.
### AT+APN=SET
**Description:** Set APN parameters for 4G/LTE network connection.
**Format:**
```
AT+APN=SET,<flag>,<apn>,<username>,<password>\r\n
```
**Parameters:**
- `flag`: Enable/disable custom APN
- `0` = Use default APN (automatic)
- `1` = Use custom APN
- `apn`: APN name (string, max 64 chars)
- `username`: APN username (string, max 32 chars, optional)
- `password`: APN password (string, max 32 chars, optional)
**Examples:**
```
AT+APN=SET,0\r\n
AT+APN=SET,1,internet.v6.telekom,telekom,tm\r\n
AT+APN=SET,1,cmnet\r\n
```
**Response:**
```
AT+APN=SET
OK
```
### AT+APN=GET
**Description:** Query current APN configuration.
**Format:**
```
AT+APN=GET\r\n
```
**Response:**
```
AT+APN=GET,<flag>,<apn>,<username>,<password>
OK
```
**Example:**
```
AT+APN=GET,1,internet.v6.telekom,telekom,tm
OK
```
---
## 2. OLED Display Rotation
Control the OLED screen orientation.
### AT+OLEDROTATE=SET
**Description:** Set OLED display rotation angle.
**Format:**
```
AT+OLEDROTATE=SET,<angle>\r\n
```
**Parameters:**
- `angle`: Rotation angle in degrees
- `0` = Normal (0°)
- `1` = Rotated 180°
**Examples:**
```
AT+OLEDROTATE=SET,0\r\n
AT+OLEDROTATE=SET,1\r\n
```
**Response:**
```
AT+OLEDROTATE=SET
OK
```
### AT+OLEDROTATE=GET
**Description:** Query current OLED rotation setting.
**Format:**
```
AT+OLEDROTATE=GET\r\n
```
**Response:**
```
AT+OLEDROTATE=GET,<angle>
OK
```
---
## 3. Bluetooth Output Configuration
Configure which NMEA sentences and custom messages are output via Bluetooth.
### AT+BT_OUT=SET
**Description:** Configure Bluetooth data output format and content.
**Format:**
```
AT+BT_OUT=SET,<type>,<json>,<gnpos>,<gndev>,<gga>,<gst>,<rmc>,<vtg>,<gsv>,<gsa>\r\n
```
**Parameters:**
- `type`: Output mode
- `0` = Standard mode (output all raw GNSS data)
- `1` = Custom mode (selective output based on following parameters)
- `json`: Output JSON format position data (0=disable, 1=enable)
- `gnpos`: Output custom GNPOS sentence (0=disable, 1=enable)
- `gndev`: Output custom GNDEV sentence (0=disable, 1=enable)
- `gga`: Output NMEA GGA sentence (0=disable, 1=enable)
- `gst`: Output NMEA GST sentence (0=disable, 1=enable)
- `rmc`: Output NMEA RMC sentence (0=disable, 1=enable)
- `vtg`: Output NMEA VTG sentence (0=disable, 1=enable)
- `gsv`: Output NMEA GSV sentence (0=disable, 1=enable)
- `gsa`: Output NMEA GSA sentence (0=disable, 1=enable)
**Examples:**
```
AT+BT_OUT=SET,0\r\n
AT+BT_OUT=SET,1,1,1,1,1,1,1,1,1,1\r\n
AT+BT_OUT=SET,1,0,1,1,1,0,0,0,0,0\r\n
AT+BT_OUT=SET,1,,,,1,1,1,1\r\n
```
**Notes:**
- Empty parameters retain previous values
- When `type=0`, all other parameters are ignored
- When `type=1`, you can selectively enable/disable each output
**Response:**
```
AT+BT_OUT=SET
OK
```
### AT+BT_OUT=GET
**Description:** Query current Bluetooth output configuration.
**Format:**
```
AT+BT_OUT=GET\r\n
```
**Response:**
```
AT+BT_OUT=GET,<type>,<json>,<gnpos>,<gndev>,<gga>,<gst>,<rmc>,<vtg>,<gsv>,<gsa>
OK
```
---
## 4. Data Upload Configuration
Configure network data upload parameters (TCP/HTTP/MQTT).
### AT+UPLOADDATA_PARM=SET
**Description:** Set data upload server parameters.
**Format:**
```
AT+UPLOADDATA_PARM=SET,<enable>,<server>,<port>\r\n
```
**Parameters:**
- `enable`: Enable/disable data upload
- `0` = Disable
- `1` = Enable
- `server`: Server address (IP or domain name, max 128 chars)
- `port`: Server port number (1-65535)
**Examples:**
```
AT+UPLOADDATA_PARM=SET,0\r\n
AT+UPLOADDATA_PARM=SET,1,192.168.0.1,2202\r\n
AT+UPLOADDATA_PARM=SET,1,data.example.com,8080\r\n
```
**Response:**
```
AT+UPLOADDATA_PARM=SET
OK
```
### AT+UPLOADDATA_PARM=GET
**Description:** Query data upload server configuration.
**Format:**
```
AT+UPLOADDATA_PARM=GET\r\n
```
**Response:**
```
AT+UPLOADDATA_PARM=GET,<enable>,<server>,<port>
OK
```
---
## 5. Data Upload Type Configuration
Configure upload protocol and authentication.
### AT+UPLOADDATA_TYPE=SET
**Description:** Set upload protocol type and credentials.
**Format:**
```
AT+UPLOADDATA_TYPE=SET,<type>,USERNAME,<username>,PASSWORD,<password>\r\n
```
**Parameters:**
- `type`: Upload protocol type
- `0` = TCP
- `1` = HTTP
- `2` = MQTT
- `username`: Authentication username (required for MQTT)
- `password`: Authentication password (required for MQTT)
**Examples:**
```
AT+UPLOADDATA_TYPE=SET,0\r\n
AT+UPLOADDATA_TYPE=SET,1\r\n
AT+UPLOADDATA_TYPE=SET,2,USERNAME,user11,PASSWORD,password11\r\n
```
**Response:**
```
AT+UPLOADDATA_TYPE=SET
OK
```
### AT+UPLOADDATA_TYPE=GET
**Description:** Query upload protocol configuration.
**Format:**
```
AT+UPLOADDATA_TYPE=GET\r\n
```
**Response:**
```
AT+UPLOADDATA_TYPE=GET,<type>,<username>,<password>
OK
```
---
## 6. Rover Mode Configuration
Configure NTRIP client parameters for RTK rover mode.
### AT+ROVER_PARM=SET
**Description:** Set NTRIP/CORS server parameters for receiving RTK corrections.
**Format:**
```
AT+ROVER_PARM=SET,<enable>,<server>,<port>,<mountpoint>,<username>,<password>\r\n
```
**Parameters:**
- `enable`: Enable/disable NTRIP client
- `0` = Disable
- `1` = Enable
- `server`: NTRIP server address (IP or domain name)
- `port`: NTRIP server port (typically 2101 or 2102)
- `mountpoint`: NTRIP mountpoint name
- `username`: NTRIP authentication username
- `password`: NTRIP authentication password
**Examples:**
```
AT+ROVER_PARM=SET,0\r\n
AT+ROVER_PARM=SET,1,211.144.118.5,2102,RTCM32,username,password\r\n
AT+ROVER_PARM=SET,1,sh.mijiatech.cn,2102,22C018,zd,zd\r\n
```
**Response:**
```
AT+ROVER_PARM=SET
OK
```
### AT+ROVER_PARM=GET
**Description:** Query NTRIP client configuration.
**Format:**
```
AT+ROVER_PARM=GET\r\n
```
**Response:**
```
AT+ROVER_PARM=GET,<enable>,<server>,<port>,<mountpoint>,<username>,<password>
OK
```
---
## 7. Base Station Mode Configuration
Configure base station parameters for outputting RTK corrections.
### AT+BASE_PARM=SET
**Description:** Set base station mode parameters.
**Format (Mode 0 - Disable):**
```
AT+BASE_PARM=SET,0\r\n
```
**Format (Mode 1 - TCP Server):**
```
AT+BASE_PARM=SET,1,<server>,<port>\r\n
```
**Format (Mode 2 - NTRIP Caster):**
```
AT+BASE_PARM=SET,2,<server>,<port>,<mountpoint>,<username>,<password>\r\n
```
**Parameters:**
- Mode `0`: Disable base station mode
- Mode `1`: TCP server mode
- `server`: Server address to send RTCM data
- `port`: Server port
- Mode `2`: NTRIP caster mode
- `server`: NTRIP caster address
- `port`: NTRIP caster port
- `mountpoint`: Mountpoint name
- `username`: Authentication username
- `password`: Authentication password
**Examples:**
```
AT+BASE_PARM=SET,0\r\n
AT+BASE_PARM=SET,1,192.168.1.100,2102\r\n
AT+BASE_PARM=SET,2,sh.mijiatech.cn,2102,RTCM32-1,zd,zd\r\n
```
**Response:**
```
AT+BASE_PARM=SET
OK
```
### AT+BASE_PARM=GET
**Description:** Query base station configuration.
**Format:**
```
AT+BASE_PARM=GET\r\n
```
**Response (Mode 0):**
```
AT+BASE_PARM=GET,0
OK
```
**Response (Mode 1):**
```
AT+BASE_PARM=GET,1,<server>,<port>
OK
```
**Response (Mode 2):**
```
AT+BASE_PARM=GET,2,<server>,<port>,<mountpoint>,<username>,<password>
OK
```
---
## 8. GNSS Mode Configuration
Configure device operating mode (Rover/Base/Static).
### AT+GNSS_MODE=SET
**Description:** Set GNSS operating mode.
**Format:**
```
AT+GNSS_MODE=SET,<mode>\r\n
```
**Parameters:**
- `mode`: Operating mode
- `0` = Rover mode (mobile RTK positioning)
- `1` = Base station mode (output RTK corrections)
- `2` = Static mode (stationary positioning)
**Examples:**
```
AT+GNSS_MODE=SET,0\r\n
AT+GNSS_MODE=SET,1\r\n
AT+GNSS_MODE=SET,2\r\n
```
**Response:**
```
AT+GNSS_MODE=SET
OK
```
**Notes:**
- Changing mode may require device restart
- Base mode requires fixed position configuration
- Rover mode requires NTRIP configuration for RTK
### AT+GNSS_MODE=GET
**Description:** Query current GNSS operating mode.
**Format:**
```
AT+GNSS_MODE=GET\r\n
```
**Response:**
```
AT+GNSS_MODE=GET,<mode>
OK
```
**Example:**
```
AT+GNSS_MODE=GET,0
OK
```
---
## Command Summary Table
| Command | SET | GET | Description |
|---------|-----|-----|-------------|
| AT+APN | ✓ | ✓ | Configure cellular APN |
| AT+OLEDROTATE | ✓ | ✓ | Set display rotation |
| AT+BT_OUT | ✓ | ✓ | Configure Bluetooth output |
| AT+UPLOADDATA_PARM | ✓ | ✓ | Set upload server |
| AT+UPLOADDATA_TYPE | ✓ | ✓ | Set upload protocol |
| AT+ROVER_PARM | ✓ | ✓ | Configure NTRIP client |
| AT+BASE_PARM | ✓ | ✓ | Configure base station |
| AT+GNSS_MODE | ✓ | ✓ | Set operating mode |
---
## Common Usage Scenarios
### Scenario 1: Configure Rover Mode for RTK Positioning
```
AT+GNSS_MODE=SET,0\r\n
AT+ROVER_PARM=SET,1,rtk.server.com,2101,MOUNT01,user,pass\r\n
AT+BT_OUT=SET,1,0,1,1,1,1,0,0,0,0\r\n
```
### Scenario 2: Configure Base Station Mode
```
AT+GNSS_MODE=SET,1\r\n
AT+BASE_PARM=SET,2,caster.server.com,2101,BASE01,user,pass\r\n
```
### Scenario 3: Enable All NMEA Output via Bluetooth
```
AT+BT_OUT=SET,1,0,1,1,1,1,1,1,1,1\r\n
```
### Scenario 4: Configure Custom APN
```
AT+APN=SET,1,internet,username,password\r\n
```
---
## Error Handling
**Common Error Responses:**
- `ERROR` - Invalid command format or parameters
- No response - Command timeout (check Bluetooth connection)
**Troubleshooting:**
1. Ensure commands end with `\r\n`
2. Check parameter count and format
3. Verify Bluetooth connection is active
4. Wait for response before sending next command
---
## Notes
- All commands are case-sensitive
- Commands must end with `\r\n` (carriage return + line feed)
- String parameters should not contain commas
- Empty parameters in SET commands retain previous values
- Configuration changes are saved to flash memory automatically
- Some changes may require device restart to take effect
---
**Document Version:** 1.0
**Firmware Version:** 1.2.37
**Last Updated:** 2026-05-07

View File

@@ -0,0 +1,122 @@
# MQTT Data Upload Configuration via AT Commands
## Overview
Configure device data upload functionality using `AT+UPLOADDATA_PARM` and `AT+UPLOADDATA_TYPE` commands. Configuration is saved to Flash and persists across power cycles.
---
## Configuration Steps
### Step 1: Set Server Address and Upload Frequency
**Command:** `AT+UPLOADDATA_PARM=SET`
**Format:**
```
AT+UPLOADDATA_PARM=SET,<freq>,<ip>,<port>\r\n
```
**Parameters:**
| Parameter | Description | Values |
|-----------|-------------|--------|
| freq | Upload frequency | 0=OFF, 1=1s, 2=2s, 5=5s, 10=10s, 255=Follow GGA rate |
| ip | Server address | IP or domain name, max 99 bytes |
| port | Server port | 1~65535 |
**Example:**
```
AT+UPLOADDATA_PARM=SET,1,mqtt.example.com,1883
```
**Response:**
```
OK
```
---
### Step 2: Set Protocol Type to MQTT and Configure Authentication
**Command:** `AT+UPLOADDATA_TYPE=SET`
**Format:**
```
AT+UPLOADDATA_TYPE=SET,2,USERNAME,<user>,PASSWORD,<password>,CLIENTID,<clientid>,TOPIC,<topic>\r\n
```
**Parameters:**
| Parameter | Description | Max Length |
|-----------|-------------|------------|
| type | Protocol type, use `2` for MQTT | — |
| USERNAME | MQTT username | 63 bytes |
| PASSWORD | MQTT password | 63 bytes |
| CLIENTID | MQTT client ID | 63 bytes |
| TOPIC | Publish topic | 63 bytes |
**Example:**
```
AT+UPLOADDATA_TYPE=SET,2,USERNAME,myuser,PASSWORD,mypass,CLIENTID,device001,TOPIC,/gnss/data
```
**Response:**
```
OK
```
---
## Query Current Configuration
### Query Server Parameters
```
AT+UPLOADDATA_PARM=GET\r\n
```
**Response Format:**
```
AT+UPLOADDATA_PARM=GET,<freq>,<ip>,<port>
OK
```
### Query Protocol Type and MQTT Parameters
```
AT+UPLOADDATA_TYPE=GET\r\n
```
**Response Format (MQTT):**
```
AT+UPLOADDATA_TYPE=GET,2,USERNAME,<user>,PASSWORD,<pass>,CLIENTID,<id>,TOPIC,<topic>,SUBTOPIC,<subtopic>
OK
```
---
## Protocol Type Reference
| type | Protocol | Description |
|------|----------|-------------|
| 0 | TCP | Raw TCP connection, no additional parameters |
| 1 | HTTP | HTTP POST upload, requires USERNAME/PASSWORD |
| 2 | MQTT | MQTT publish, requires USERNAME/PASSWORD/CLIENTID/TOPIC |
| 3 | JT808 | JT808 protocol |
---
## Complete Configuration Example
```
# 1. Set server address with 1-second upload interval
AT+UPLOADDATA_PARM=SET,1,mqtt.example.com,1883
# 2. Set MQTT protocol and authentication
AT+UPLOADDATA_TYPE=SET,2,USERNAME,myuser,PASSWORD,mypass,CLIENTID,device001,TOPIC,/gnss/data
# 3. Verify configuration
AT+UPLOADDATA_PARM=GET
AT+UPLOADDATA_TYPE=GET
```

View File

@@ -0,0 +1,542 @@
# Custom NMEA Sentences Reference
## Overview
This document describes the custom NMEA-format sentences (GNPOS and GNDEV) output by the H11hw GNSS RTK device. These proprietary sentences provide comprehensive positioning data and device information in a standardized NMEA format.
**NMEA Format Structure:**
```
$<sentence>*<checksum>\r\n
```
- `$` - Start delimiter
- `<sentence>` - Sentence identifier and data fields (comma-separated)
- `*` - Checksum delimiter
- `<checksum>` - Two-digit hexadecimal XOR checksum
- `\r\n` - End delimiter (CR+LF)
---
## 1. GNPOS - Position Data Sentence
### Description
The GNPOS sentence provides comprehensive real-time positioning information including coordinates, accuracy metrics, satellite status, and system information.
### Output Frequency
- **Default:** Every 800ms (1.25 Hz)
- **Configurable:** Via `AT+BT_OUT=SET` command
### Format
```
$GNPOS,<lat>,<lon>,<alt>,<altCorr>,<status>,<hdop>,<hrms>,<vrms>,<satUsed>,<satView>,<speed>,<heading>,<battV>,<battPct>,<ntripFlag>,<rtcmSize>,<age>,<timestamp>,<tiltAngle>*<checksum>\r\n
```
### Field Definitions
| Field | Index | Type | Unit | Description | Example |
|-------|-------|------|------|-------------|---------|
| Sentence ID | 0 | String | - | Fixed identifier | GNPOS |
| lat | 1 | Float | degrees | Latitude (signed, 9 decimals) | 31.140518542 |
| lon | 2 | Float | degrees | Longitude (signed, 9 decimals) | 121.284018564 |
| alt | 3 | Float | meters | Altitude above sea level (3 decimals) | 45.123 |
| altCorr | 4 | Float | meters | Corrected altitude (3 decimals) | 45.456 |
| status | 5 | Integer | - | Positioning status (see table below) | 4 |
| hdop | 6 | Float | - | Horizontal Dilution of Precision (2 decimals) | 0.85 |
| hrms | 7 | Float | meters | Horizontal RMS error (3 decimals) | 0.012 |
| vrms | 8 | Float | meters | Vertical RMS error (3 decimals) | 0.018 |
| satUsed | 9 | Integer | - | Number of satellites used in solution | 18 |
| satView | 10 | Integer | - | Number of satellites visible | 24 |
| speed | 11 | Float | km/h | Ground speed (3 decimals) | 12.345 |
| heading | 12 | Float | degrees | Heading/course over ground (2 decimals) | 135.67 |
| battV | 13 | Float | volts | Battery voltage (2 decimals) | 4.15 |
| battPct | 14 | Integer | % | Battery percentage (0-100) | 85 |
| ntripFlag | 15 | Integer | - | NTRIP connection status (0=disconnected, 1=connected) | 1 |
| rtcmSize | 16 | Integer | bytes | RTCM data size received | 1024 |
| age | 17 | Float | seconds | Differential correction age (1 decimal) | 1.2 |
| timestamp | 18 | Integer | seconds | System timestamp (Unix time) | 1714953600 |
| tiltAngle | 19 | Float | degrees | Device tilt angle (1 decimal) | 2.5 |
### Positioning Status Values
| Value | Status | Description |
|-------|--------|-------------|
| 0 | No Fix | No valid position |
| 1 | Single Point | Autonomous GPS/GNSS positioning |
| 2 | DGPS | Differential GPS (SBAS corrected) |
| 4 | RTK Fixed | RTK fixed solution (cm-level accuracy) |
| 5 | RTK Float | RTK float solution (dm-level accuracy) |
### Example Output
```
$GNPOS,31.140518542,121.284018564,45.123,45.456,4,0.85,0.012,0.018,18,24,12.345,135.67,4.15,85,1,1024,1.2,1714953600,2.5*5A\r\n
```
### Parsing Example (Python)
```python
def parse_gnpos(sentence):
# Remove $, checksum, and whitespace
data = sentence.strip().split('*')[0].lstrip('$')
fields = data.split(',')
if fields[0] != 'GNPOS' or len(fields) != 20:
return None
return {
'latitude': float(fields[1]),
'longitude': float(fields[2]),
'altitude': float(fields[3]),
'altitude_corrected': float(fields[4]),
'status': int(fields[5]),
'hdop': float(fields[6]),
'hrms': float(fields[7]),
'vrms': float(fields[8]),
'satellites_used': int(fields[9]),
'satellites_visible': int(fields[10]),
'speed_kmh': float(fields[11]),
'heading': float(fields[12]),
'battery_voltage': float(fields[13]),
'battery_percent': int(fields[14]),
'ntrip_connected': bool(int(fields[15])),
'rtcm_size': int(fields[16]),
'correction_age': float(fields[17]),
'timestamp': int(fields[18]),
'tilt_angle': float(fields[19])
}
```
### Parsing Example (C)
```c
typedef struct {
double latitude;
double longitude;
float altitude;
float altitude_corrected;
int status;
float hdop;
float hrms;
float vrms;
int satellites_used;
int satellites_visible;
float speed_kmh;
float heading;
float battery_voltage;
int battery_percent;
int ntrip_connected;
int rtcm_size;
float correction_age;
long long timestamp;
float tilt_angle;
} gnpos_data_t;
int parse_gnpos(const char* sentence, gnpos_data_t* data) {
if (strncmp(sentence, "$GNPOS,", 7) != 0) {
return -1;
}
int result = sscanf(sentence,
"$GNPOS,%lf,%lf,%f,%f,%d,%f,%f,%f,%d,%d,%f,%f,%f,%d,%d,%d,%f,%lld,%f*",
&data->latitude,
&data->longitude,
&data->altitude,
&data->altitude_corrected,
&data->status,
&data->hdop,
&data->hrms,
&data->vrms,
&data->satellites_used,
&data->satellites_visible,
&data->speed_kmh,
&data->heading,
&data->battery_voltage,
&data->battery_percent,
&data->ntrip_connected,
&data->rtcm_size,
&data->correction_age,
&data->timestamp,
&data->tilt_angle
);
return (result == 19) ? 0 : -1;
}
```
---
## 2. GNDEV - Device Information Sentence
### Description
The GNDEV sentence provides device identification and cellular module information. This sentence is useful for device management, inventory tracking, and remote diagnostics.
### Output Frequency
- **Bluetooth disconnected:** Every 5 seconds
- **Bluetooth connected (first 10 seconds):** Every 800ms (fast sync)
- **Bluetooth connected (after 10 seconds):** Every 5 seconds
### Format
```
$GNDEV,<sn>,<pcb_version>,<fw_version>,<imei>,<imsi>,<iccid>*<checksum>\r\n
```
### Field Definitions
| Field | Index | Type | Length | Description | Example |
|-------|-------|------|--------|-------------|---------|
| Sentence ID | 0 | String | - | Fixed identifier | GNDEV |
| sn | 1 | String | Variable | Device serial number (unique ID) | H11-20240507-001 |
| pcb_version | 2 | String | Variable | PCB hardware version | V1.2 |
| fw_version | 3 | String | Variable | Firmware version (x.x.x format) | 1.2.37 |
| imei | 4 | String | 15 | 4G module IMEI (International Mobile Equipment Identity) | 866123456789012 |
| imsi | 5 | String | 15 | SIM card IMSI (International Mobile Subscriber Identity) | 460012345678901 |
| iccid | 6 | String | 20 | SIM card ICCID (Integrated Circuit Card ID) | 89860123456789012345 |
### Example Output
```
$GNDEV,H11-20240507-001,V1.2,1.2.37,866123456789012,460012345678901,89860123456789012345*3F\r\n
```
### Parsing Example (Python)
```python
def parse_gndev(sentence):
# Remove $, checksum, and whitespace
data = sentence.strip().split('*')[0].lstrip('$')
fields = data.split(',')
if fields[0] != 'GNDEV' or len(fields) != 7:
return None
return {
'serial_number': fields[1],
'pcb_version': fields[2],
'firmware_version': fields[3],
'imei': fields[4],
'imsi': fields[5],
'iccid': fields[6]
}
```
### Parsing Example (C)
```c
typedef struct {
char serial_number[32];
char pcb_version[16];
char firmware_version[16];
char imei[16];
char imsi[16];
char iccid[32];
} gndev_data_t;
int parse_gndev(const char* sentence, gndev_data_t* data) {
if (strncmp(sentence, "$GNDEV,", 7) != 0) {
return -1;
}
int result = sscanf(sentence,
"$GNDEV,%31[^,],%15[^,],%15[^,],%15[^,],%15[^,],%31[^*]*",
data->serial_number,
data->pcb_version,
data->firmware_version,
data->imei,
data->imsi,
data->iccid
);
return (result == 6) ? 0 : -1;
}
```
---
## 3. Checksum Calculation
### Algorithm
The checksum is calculated as the XOR of all characters between `$` and `*` (exclusive).
### Example (C)
```c
uint8_t calculate_nmea_checksum(const char* sentence) {
uint8_t checksum = 0;
const char* ptr = sentence;
// Skip '$' if present
if (*ptr == '$') ptr++;
// XOR all characters until '*' or end
while (*ptr && *ptr != '*') {
checksum ^= *ptr;
ptr++;
}
return checksum;
}
// Verify checksum
int verify_nmea_checksum(const char* sentence) {
const char* asterisk = strchr(sentence, '*');
if (!asterisk) return 0;
uint8_t calculated = calculate_nmea_checksum(sentence);
uint8_t received = 0;
sscanf(asterisk + 1, "%02X", &received);
return (calculated == received);
}
```
### Example (Python)
```python
def calculate_nmea_checksum(sentence):
# Remove $ and everything after *
data = sentence.lstrip('$').split('*')[0]
checksum = 0
for char in data:
checksum ^= ord(char)
return checksum
def verify_nmea_checksum(sentence):
if '*' not in sentence:
return False
data, checksum_str = sentence.split('*')
calculated = calculate_nmea_checksum(data)
received = int(checksum_str[:2], 16)
return calculated == received
```
---
## 4. Integration Guide
### Enabling Custom Sentences
Use the `AT+BT_OUT=SET` command to enable GNPOS and GNDEV output:
```
AT+BT_OUT=SET,1,0,1,1,0,0,0,0,0,0\r\n
```
This enables:
- Custom mode (`type=1`)
- GNPOS sentence (`gnpos=1`)
- GNDEV sentence (`gndev=1`)
- Disables JSON and standard NMEA sentences
### Complete Data Stream Example
```
$GNDEV,H11-20240507-001,V1.2,1.2.37,866123456789012,460012345678901,89860123456789012345*3F\r\n
$GNPOS,31.140518542,121.284018564,45.123,45.456,4,0.85,0.012,0.018,18,24,12.345,135.67,4.15,85,1,1024,1.2,1714953600,2.5*5A\r\n
$GNPOS,31.140518543,121.284018565,45.124,45.457,4,0.85,0.012,0.018,18,24,12.346,135.68,4.15,85,1,1024,1.2,1714953601,2.5*5B\r\n
$GNPOS,31.140518544,121.284018566,45.125,45.458,4,0.85,0.012,0.018,18,24,12.347,135.69,4.15,85,1,1024,1.2,1714953602,2.5*5C\r\n
$GNDEV,H11-20240507-001,V1.2,1.2.37,866123456789012,460012345678901,89860123456789012345*3F\r\n
```
### Bluetooth Receiver Implementation
```python
import serial
import time
class H11RTKReceiver:
def __init__(self, port, baudrate=115200):
self.serial = serial.Serial(port, baudrate, timeout=1)
self.gnpos_callback = None
self.gndev_callback = None
def set_gnpos_callback(self, callback):
self.gnpos_callback = callback
def set_gndev_callback(self, callback):
self.gndev_callback = callback
def read_loop(self):
buffer = ""
while True:
data = self.serial.read(256).decode('utf-8', errors='ignore')
buffer += data
while '\n' in buffer:
line, buffer = buffer.split('\n', 1)
line = line.strip()
if line.startswith('$GNPOS,'):
if verify_nmea_checksum(line):
gnpos_data = parse_gnpos(line)
if self.gnpos_callback and gnpos_data:
self.gnpos_callback(gnpos_data)
elif line.startswith('$GNDEV,'):
if verify_nmea_checksum(line):
gndev_data = parse_gndev(line)
if self.gndev_callback and gndev_data:
self.gndev_callback(gndev_data)
# Usage example
def on_position_update(data):
print(f"Position: {data['latitude']:.9f}, {data['longitude']:.9f}")
print(f"Status: {data['status']}, Satellites: {data['satellites_used']}")
print(f"Accuracy: H={data['hrms']:.3f}m, V={data['vrms']:.3f}m")
def on_device_info(data):
print(f"Device: {data['serial_number']}")
print(f"Firmware: {data['firmware_version']}")
print(f"IMEI: {data['imei']}")
receiver = H11RTKReceiver('/dev/rfcomm0')
receiver.set_gnpos_callback(on_position_update)
receiver.set_gndev_callback(on_device_info)
receiver.read_loop()
```
---
## 5. Data Quality Indicators
### RTK Solution Quality
| Status | HRMS Range | VRMS Range | Typical Accuracy |
|--------|------------|------------|------------------|
| RTK Fixed (4) | < 0.02m | < 0.03m | 1-2 cm horizontal, 2-3 cm vertical |
| RTK Float (5) | 0.1-0.5m | 0.2-1.0m | 10-50 cm horizontal, 20-100 cm vertical |
| DGPS (2) | 0.5-2.0m | 1.0-3.0m | 0.5-2 m horizontal, 1-3 m vertical |
| Single (1) | 2.0-10.0m | 3.0-15.0m | 2-10 m horizontal, 3-15 m vertical |
### HDOP Quality Assessment
| HDOP Value | Quality | Description |
|------------|---------|-------------|
| < 1.0 | Excellent | Ideal satellite geometry |
| 1.0 - 2.0 | Good | Acceptable for RTK |
| 2.0 - 5.0 | Moderate | Usable but degraded |
| > 5.0 | Poor | Unreliable positioning |
### Correction Age Guidelines
| Age (seconds) | RTK Quality | Recommendation |
|---------------|-------------|----------------|
| < 3.0 | Excellent | Optimal RTK performance |
| 3.0 - 10.0 | Good | Acceptable for most applications |
| 10.0 - 30.0 | Degraded | Consider reconnecting |
| > 30.0 | Poor | RTK solution unreliable |
---
## 6. Troubleshooting
### No GNPOS/GNDEV Output
**Possible Causes:**
1. Bluetooth output not configured
2. Custom mode disabled
3. Bluetooth connection lost
**Solutions:**
```
AT+BT_OUT=GET\r\n # Check current configuration
AT+BT_OUT=SET,1,0,1,1,0,0,0,0,0,0\r\n # Enable custom sentences
```
### Invalid Checksum
**Possible Causes:**
1. Data corruption during transmission
2. Bluetooth interference
3. Buffer overflow
**Solutions:**
- Verify checksum calculation algorithm
- Check Bluetooth signal strength
- Increase receive buffer size
### Incorrect Data Values
**Possible Causes:**
1. GNSS not initialized
2. No satellite fix
3. Antenna disconnected
**Solutions:**
- Check `status` field (should be > 0)
- Verify `satView` and `satUsed` (should be > 4)
- Check antenna connection
---
## 7. Best Practices
### Data Processing
1. **Always verify checksums** before parsing data
2. **Check positioning status** before using coordinates
3. **Monitor correction age** for RTK applications
4. **Validate satellite count** (minimum 4 for 3D fix)
5. **Check HDOP values** for solution quality
### Performance Optimization
1. **Buffer management:** Use circular buffers for continuous data streams
2. **Parsing efficiency:** Pre-compile regex patterns or use fixed-format parsing
3. **Callback design:** Keep callbacks lightweight, defer heavy processing
4. **Error handling:** Implement timeout and retry mechanisms
### Application Design
1. **Position filtering:** Apply Kalman filtering for smooth trajectories
2. **Status monitoring:** Track RTK solution quality over time
3. **Battery management:** Monitor voltage and percentage for low-power warnings
4. **Connection health:** Track NTRIP status and correction age
---
## Appendix A: Complete Message Examples
### RTK Fixed Solution (High Quality)
```
$GNPOS,31.140518542,121.284018564,45.123,45.456,4,0.85,0.012,0.018,18,24,0.000,0.00,4.15,85,1,1024,1.2,1714953600,0.5*XX\r\n
```
- Status: 4 (RTK Fixed)
- HRMS: 0.012m (1.2cm horizontal accuracy)
- VRMS: 0.018m (1.8cm vertical accuracy)
- 18 satellites used, 24 visible
- NTRIP connected, 1.2s correction age
### RTK Float Solution (Medium Quality)
```
$GNPOS,31.140518542,121.284018564,45.123,45.456,5,1.20,0.250,0.450,15,22,5.234,45.30,4.10,80,1,1024,3.5,1714953600,1.2*XX\r\n
```
- Status: 5 (RTK Float)
- HRMS: 0.250m (25cm horizontal accuracy)
- VRMS: 0.450m (45cm vertical accuracy)
- 15 satellites used, 22 visible
- NTRIP connected, 3.5s correction age
### Single Point Solution (Low Quality)
```
$GNPOS,31.140518542,121.284018564,45.123,45.456,1,2.50,3.500,5.200,8,15,12.345,135.67,3.95,65,0,0,0.0,1714953600,2.5*XX\r\n
```
- Status: 1 (Single Point)
- HRMS: 3.500m (3.5m horizontal accuracy)
- VRMS: 5.200m (5.2m vertical accuracy)
- 8 satellites used, 15 visible
- NTRIP disconnected
---
**Document Version:** 1.0
**Firmware Version:** 1.2.37
**Last Updated:** 2026-05-07