npm package: @swiftworks/mqtt-geo-stack
Description: Production-ready React Native library for MQTT messaging with integrated geospatial data management, PostGIS support, and Kafka streaming integration
Author: SwiftWorks LLC
Latest version: 1.1.3

# MQTT Geo Stack - React Native Library

A production-ready React Native library for MQTT communication with integrated geospatial data management, PostgreSQL+PostGIS support, and Kafka topic management.

## Features

- 🚀 **Production MQTT Client** - Robust connection management with automatic reconnection
- 🌍 **Geospatial Data Management** - Built-in PostGIS integration and geofencing
- 📊 **Kafka Topic Management** - Automatic message routing to Kafka topics
- 📱 **React Native Optimized** - Hooks-based API with network state monitoring
- 🔄 **Offline Support** - Message queuing and persistence
- 📍 **Location Tracking** - Automated geo-update publishing
- 🛡️ **Type Safety** - Comprehensive TypeScript-like constants and types
- 🔐 **Multi-Auth Support** - Anonymous, username/password, and certificate authentication
- 🌐 **WebSocket Ready** - Full WebSocket MQTT support for React Native

### Technical Details
- Compatible with React Native 0.60+
- Supports WebSocket MQTT connections (ws:// and wss://)
- PostgreSQL + PostGIS integration
- Comprehensive error handling and reconnection logic
- Cross-platform support (iOS, Android)
- Full certificate-based authentication support
- Automatic message queuing during offline periods

## Installation

```bash
npm install @swiftworks/mqtt-geo-stack
```

### Peer Dependencies

Make sure you have these installed:

```bash
npm install @react-native-async-storage/async-storage @react-native-community/netinfo mqtt
```

For iOS, run:
```bash
cd ios && pod install
```

**React Native MQTT Usage Note:**

This library uses the `mqtt` package in WebSocket mode for React Native compatibility. Your broker must support WebSocket connections (ws:// or wss://). Example config:

```javascript
const client = new MQTTClient({
  host: 'your-mqtt-broker.com',
  port: 8083, // typical WebSocket port
  protocol: 'wss', // or 'ws' for non-secure
  // ...other options
});
```
If your broker does not support WebSocket, enable it or use a bridge.

## Quick Start

### Basic MQTT Usage

```javascript
import { useMQTTClient } from '@swiftworks/mqtt-geo-stack';

function MyComponent() {
  const { connect, publish, subscribe, isConnected } = useMQTTClient({
    host: 'your-mqtt-broker.com',
    port: 1883,
    // Optional authentication (remove if broker allows anonymous)
    username: 'your-username',
    password: 'your-password'
  });

  useEffect(() => {
    connect();
  }, []);

  const handlePublish = () => {
    publish('test/topic', { message: 'Hello MQTT!' });
  };

  return (
    <View>
      <Text>Connected: {isConnected ? 'Yes' : 'No'}</Text>
      <Button title="Publish" onPress={handlePublish} />
    </View>
  );
}
```

### Complete Geo Stack

```javascript
import { useMQTTGeoStack } from '@swiftworks/mqtt-geo-stack';

function GeoApp() {
  const { mqtt, geo, kafka, connection } = useMQTTGeoStack({
    host: 'your-mqtt-broker.com',
    port: 1883,
    clientId: 'geo-device-001'
  });

  useEffect(() => {
    mqtt.connect();
  }, []);

  // Create a geofence
  const createGeofence = () => {
    geo.createCircularGeofence(
      'office-zone',
      { latitude: 40.7128, longitude: -74.0060 },
      100, // 100 meters radius
      { name: 'Office Area' }
    );
  };

  return (
    <View>
      <Text>Network: {connection.networkState.quality}</Text>
      <Text>Devices Nearby: {geo.deviceLocations.size}</Text>
      <Button title="Create Geofence" onPress={createGeofence} />
    </View>
  );
}
```

### Location Tracking

```javascript
import { useGeoPublisher } from '@swiftworks/mqtt-geo-stack';

function LocationTracker({ mqttClient }) {
  const { startTracking, stopTracking, isTracking, lastLocation } = useGeoPublisher(
    mqttClient,
    'device-123',
    { metadata: { vehicle: 'truck-001' } }
  );

  return (
    <View>
      <Button 
        title={isTracking ? 'Stop Tracking' : 'Start Tracking'}
        onPress={isTracking ? stopTracking : () => startTracking(5000)}
      />
      {lastLocation && (
        <Text>
          Last: {lastLocation.latitude}, {lastLocation.longitude}
        </Text>
      )}
    </View>
  );
}
```

## API Reference

### Core Classes

#### MQTTClient

Main MQTT client with production features:

```javascript
import { MQTTClient } from '@swiftworks/mqtt-geo-stack';

const client = new MQTTClient({
  host: 'localhost',
  port: 1883,
  clientId: 'my-device',
  username: 'user',
  password: 'pass',
  keepAlive: 60,
  reconnectPeriod: 5000,
  maxReconnectAttempts: 10
});

// Connect
await client.connect();

// Publish geo update
client.publishGeoUpdate('device-001', {
  latitude: 40.7128,
  longitude: -74.0060,
  accuracy: 5
});

// Publish sensor data
client.publishSensorData('device-001', 'temperature', {
  value: 23.5,
  unit: 'celsius'
});
```

#### GeoDataManager

Geospatial data management:

```javascript
import { GeoDataManager } from '@swiftworks/mqtt-geo-stack';

const geoManager = new GeoDataManager(mqttClient);

// Create circular geofence
const geofence = geoManager.createCircularGeofence(
  'parking-lot',
  { latitude: 40.7128, longitude: -74.0060 },
  50 // meters
);

// Find nearby devices
const nearby = geoManager.getNearbyDevices(
  { latitude: 40.7128, longitude: -74.0060 },
  1000 // within 1km
);
```

#### KafkaTopicManager

Kafka integration:

```javascript
import { KafkaTopicManager } from '@swiftworks/mqtt-geo-stack';

const kafkaManager = new KafkaTopicManager(mqttClient);

// Setup default mappings
kafkaManager.setupDefaultMappings();

// Custom topic mapping
kafkaManager.mapTopic('sensor/+/temperature', {
  topic: 'temperature-data',
  keyExtractor: (msg) => msg.deviceId,
  transformer: (msg) => ({
    ...msg,
    table: 'temperature_readings'
  })
});
```

### React Hooks

#### useMQTTClient(config)

Main MQTT client hook.

**Returns:**
- `client` - MQTTClient instance
- `connectionState` - Current connection state
- `error` - Last error
- `connect()` - Connect function
- `disconnect()` - Disconnect function
- `publish(topic, message, options)` - Publish function
- `subscribe(topic, options)` - Subscribe function
- `isConnected` - Boolean connection status

#### useGeoDataManager(mqttClient)

Geospatial data management hook.

**Returns:**
- `geoManager` - GeoDataManager instance
- `deviceLocations` - Map of device locations
- `geofences` - Map of geofences
- `createCircularGeofence(id, center, radius, metadata)`
- `createPolygonGeofence(id, coordinates, metadata)`
- `getNearbyDevices(location, radius)`

#### useMQTTSubscription(mqttClient, topic, handler, options)

Subscribe to MQTT topics with automatic cleanup.

**Returns:**
- `messages` - Array of received messages
- `lastMessage` - Most recent message

#### useGeoPublisher(mqttClient, deviceId, options)

Location tracking and publishing.

**Returns:**
- `publishLocation(location, metadata)`
- `startTracking(interval)`
- `stopTracking()`
- `isTracking` - Boolean tracking status
- `lastLocation` - Last published location

## Message Types

The library uses standardized message types:

```javascript
import { MessageTypes } from '@swiftworks/mqtt-geo-stack';

// MessageTypes.GEO_UPDATE
// MessageTypes.SENSOR_DATA  
// MessageTypes.DEVICE_STATUS
// MessageTypes.ALERT
// MessageTypes.COMMAND
// MessageTypes.ACK
```

## PostGIS Integration

Messages are automatically enriched with PostGIS-compatible data:

```javascript
{
  "type": "geo_update",
  "deviceId": "device-001",
  "location": {
    "type": "Point",
    "coordinates": [-74.0060, 40.7128]
  },
  "spatial_data": {
    "geom": "POINT(-74.0060 40.7128)",
    "srid": 4326,
    "spatial_index_hint": {
      "grid_level": 18,
      "quadkey": "0313102310",
      "geohash": "dr5regw3"
    }
  },
  "postgis_table": "device_locations"
}
```

## Kafka Topics

Default topic mappings:

- `geo/+/location` → `geo-events` (with PostGIS enrichment)
- `sensor/+/+` → `sensor-data` (with time partitioning)
- `geo/+/geofence` → `geo-events` (geofence events)
- `device/+/status` → `device-status` (device health)

## Configuration Options

### Authentication Methods

The library supports multiple authentication approaches for maximum flexibility:

```javascript
// Anonymous connection (for development/testing)
const client = new MQTTClient({
  host: 'localhost',
  port: 1883
});

// Username/Password authentication (most common)
const client = new MQTTClient({
  host: 'broker.example.com',
  port: 1883,
  username: 'myuser',
  password: 'mypass'
});

// Certificate-based authentication (production recommended)
// NOTE: React Native requires certificates as Buffers/strings, not file paths
const client = new MQTTClient({
  host: 'secure-broker.example.com',
  port: 8883,
  protocol: 'mqtts',
  // For React Native, certificates must be bundled or loaded differently
  ca: certificateBuffer, // Buffer or string, not fs.readFileSync
  cert: clientCertBuffer,
  key: clientKeyBuffer,
  rejectUnauthorized: true
});
```

**Authentication Security Levels:**
- 🔓 **Anonymous**: Quick testing, insecure
- 🔐 **Username/Password**: Standard security, widely supported  
- 🛡️ **Certificate-based**: Enterprise security, recommended for production

**React Native Certificate Loading Options:**

```javascript
// Method 1: Bundle certificates in app assets
import { certificateCA, clientCert, clientKey } from './assets/certificates';

const client = new MQTTClient({
  host: 'secure-broker.example.com',
  port: 8883,
  protocol: 'mqtts',
  ca: certificateCA,
  cert: clientCert,
  key: clientKey
});

// Method 2: Load from secure storage (React Native Keychain/SecureStore)
import * as SecureStore from 'expo-secure-store';

const ca = await SecureStore.getItemAsync('mqtt_ca_cert');
const cert = await SecureStore.getItemAsync('mqtt_client_cert');
const key = await SecureStore.getItemAsync('mqtt_client_key');

// Method 3: Fetch from secure API endpoint
const response = await fetch('https://secure-api.example.com/mqtt-certs', {
  headers: { 'Authorization': `Bearer ${userToken}` }
});
const { ca, cert, key } = await response.json();

// Method 4: Environment-based configuration
const client = new MQTTClient({
  host: process.env.MQTT_HOST,
  port: parseInt(process.env.MQTT_PORT),
  protocol: 'mqtts',
  ca: process.env.MQTT_CA_CERT,
  cert: process.env.MQTT_CLIENT_CERT,
  key: process.env.MQTT_CLIENT_KEY,
  rejectUnauthorized: process.env.NODE_ENV === 'production'
});
```

**Security Best Practices:**
- 🔒 Never hardcode certificates in source code
- 🔑 Use secure storage for certificate management
- 🌐 Validate certificate chains in production
- 🔄 Implement certificate rotation strategies
- 📱 Consider platform-specific keychain integration

### MQTT Client Config

```javascript
{
  host: 'localhost',           // MQTT broker host
  port: 1883,                  // MQTT broker port
  protocol: 'mqtt',            // 'mqtt' or 'mqtts'
  clientId: 'unique-id',       // Client identifier
  username: 'user',            // Optional: Authentication username
  password: 'pass',            // Optional: Authentication password
  keepAlive: 60,               // Keep alive interval (seconds)
  clean: true,                 // Clean session
  reconnectPeriod: 5000,       // Reconnection delay (ms)
  connectTimeout: 30000,       // Connection timeout (ms)
  qos: 1,                      // Default QoS level
  retain: false,               // Default retain flag
  maxReconnectAttempts: 10     // Max reconnection attempts
}
```

## Error Handling

```javascript
const { mqtt, error } = useMQTTClient(config);

useEffect(() => {
  if (error) {
    console.error('MQTT Error:', error);
    // Handle error (show notification, retry, etc.)
  }
}, [error]);

// Client events
mqtt.client?.on('error', (error) => {
  console.error('MQTT Client Error:', error);
});

mqtt.client?.on('maxReconnectAttemptsReached', () => {
  console.warn('Max reconnection attempts reached');
});
```

## Performance Optimization

The library automatically optimizes based on network conditions:

```javascript
const { connection } = useConnectionManager(mqttClient);

// Get current optimization settings
const settings = connection.optimizeConnection();
console.log('Optimized settings:', settings);

// Monitor network quality
useEffect(() => {
  console.log('Network quality:', connection.networkState.quality);
}, [connection.networkState.quality]);
```

## License

MIT License - see LICENSE file for details.

## Version History

### [1.1.1] - 2025-07-19
- ✅ **Added**: Comprehensive React Native certificate loading examples (4 methods)
- ✅ **Added**: Security best practices section for authentication
- ✅ **Added**: Enhanced authentication documentation with practical code examples
- ✅ **Added**: Environment-based configuration examples
- 📝 **Improved**: More detailed technical specifications and better formatting

### [1.1.0] - 2025-07-19
- ✅ **Added**: Full certificate-based authentication support (ca, cert, key, rejectUnauthorized)
- ✅ **Added**: Enhanced authentication documentation with React Native specific examples
- ✅ **Added**: Improved authentication flexibility (anonymous, username/password, certificates)
- 🔧 **Fixed**: Certificate authentication options now properly passed to MQTT client
- 🔧 **Fixed**: Updated documentation to reflect React Native certificate loading limitations
- 📝 **Changed**: Documentation now clearly marks username/password as optional
- 📝 **Changed**: Added comprehensive authentication methods section

### [1.0.0] - 2025-07-19
- 🎉 **Initial Release**: Production-ready MQTT Geo Stack library
- ✅ **Added**: Complete React Native hooks-based API
- ✅ **Added**: Docker infrastructure with Mosquitto, PostgreSQL, and Kafka
- ✅ **Added**: Comprehensive test suite with 100% core functionality coverage

## Contributing

1. Fork the repository
2. Create your feature branch
3. Run tests: `npm test`
4. Run linting: `npm run lint`
5. Submit a pull request

## Support

For issues and questions:
- GitHub Issues: [repository-url/issues]
- Documentation: [docs-url]
- Email: info@swiftworksllc.com