> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloneable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Starting workflows

## Overview

Start utility measurement workflows through `CloneablePlatform`. Each workflow returns results asynchronously.

## Prerequisites

Before starting a workflow, confirm:

* The user is authenticated.
* Camera, location, and motion permissions are granted.
* Your content is wrapped in `CloneableWorkflowWrapper`.

## Basic setup

### SwiftUI Integration

```swift theme={null}
import SwiftUI
import CloneablePlatformiOS

struct UtilityMeasurementView: View {
    @EnvironmentObject var cloneable: CloneablePlatform
    @State private var isWorkflowActive = false
    
    var body: some View {
        // Essential: Wrap your content in CloneableWorkflowWrapper
        CloneableWorkflowWrapper(cloneablePlatform: cloneable) {
            VStack(spacing: 20) {
                // Your UI content here
                utilityWorkflowButtons
            }
        }
    }
    
    private var utilityWorkflowButtons: some View {
        VStack(spacing: 16) {
            Button("Measure Pole") {
                Task { await startPoleMeasurement() }
            }
            .disabled(isWorkflowActive)
            
            Button("Measure Midspan") {
                Task { await startMidspanMeasurement() }
            }
            .disabled(isWorkflowActive)
            
            Button("Measure Guy Wire") {
                Task { await startGuyMeasurement() }
            }
            .disabled(isWorkflowActive)
        }
    }
}
```

## Pole and vertical measurements

### Basic pole measurement

```swift theme={null}
func startPoleMeasurement() async {
    do {
        isWorkflowActive = true
        
        // Create basic configuration
        let config = VerticalMeasurementConfiguration(
            type: .pole,
            accuracy: .standardAccuracy,
            inventoryClasses: nil,
            wireClasses: nil,
            guyWireOptions: nil,
            ownerOptions: nil,
            shouldCaptureAttachments: true
        )
        
        // Start the workflow
        let result = try await cloneable.startVerticalMeasurement(config: config)
        
        // Process the result
        await processPoleMeasurementResult(result)
        
    } catch {
        print("Pole measurement failed: \(error)")
        await handleMeasurementError(error)
    } finally {
        isWorkflowActive = false
    }
}
```

### High-accuracy pole measurement

```swift theme={null}
func startHighAccuracyPoleMeasurement() async {
    do {
        let config = VerticalMeasurementConfiguration(
            type: .pole,
            accuracy: .highAccuracy,  // Requires reference stick measurement
            inventoryClasses: customInventoryClasses,
            wireClasses: customWireClasses,
            guyWireOptions: customGuyOptions,
            ownerOptions: utilityOwners,
            shouldCaptureAttachments: true
        )
        
        let result = try await cloneable.startVerticalMeasurement(config: config)
        await processHighAccuracyResult(result)
        
    } catch VerticalMeasurementError.referenceStickRequired {
        // Handle case where high accuracy requires reference stick
        await showReferenceStickInstructions()
    } catch {
        await handleMeasurementError(error)
    }
}
```

### Pole measurement with custom inventory

```swift theme={null}
func startCustomPoleMeasurement() async {
    // Define custom inventory for your utility
    let customInventory = [
        InventoryClass(name: "Transformer", subcategories: [
            InventorySubcategory(name: "KVA Rating", options: ["25", "50", "75", "100"], required: true),
            InventorySubcategory(name: "Type", options: ["Overhead", "Padmount"], required: true)
        ]),
        InventoryClass(name: "Switch", subcategories: [
            InventorySubcategory(name: "Operation", options: ["Manual", "Automatic"], required: false)
        ])
    ]
    
    let config = VerticalMeasurementConfiguration(
        type: .pole,
        accuracy: .standardAccuracy,
        inventoryClasses: customInventory,
        wireClasses: nil,
        guyWireOptions: nil,
        ownerOptions: ["City Power", "Regional Coop"],
        shouldCaptureAttachments: true
    )
    
    do {
        let result = try await cloneable.startVerticalMeasurement(config: config)
        await processCustomPoleMeasurement(result)
    } catch {
        await handleMeasurementError(error)
    }
}
```

## Midspan measurements

### Basic midspan measurement

```swift theme={null}
func startMidspanMeasurement() async {
    do {
        let config = VerticalMeasurementConfiguration(
            type: .midspan,
            accuracy: .standardAccuracy,
            inventoryClasses: nil,              // Midspans typically don't have attachments
            wireClasses: conductorTypes,        // Focus on conductor classification
            guyWireOptions: nil,
            ownerOptions: circuitOwners,
            shouldCaptureAttachments: false     // Skip attachment documentation
        )
        
        let result = try await cloneable.startVerticalMeasurement(config: config)
        await processMidspanResult(result)
        
    } catch {
        print("Midspan measurement failed: \(error)")
        await handleMeasurementError(error)
    }
}
```

### High-accuracy midspan with conductor types

```swift theme={null}
func startHighAccuracyMidspan() async {
    let conductorTypes = [
        InventoryClass(name: "Primary Conductor", subcategories: [
            InventorySubcategory(name: "Type", options: ["ACSR", "AAC", "AAAC"], required: true),
            InventorySubcategory(name: "Size", options: ["2/0", "4/0", "336", "477"], required: true),
            InventorySubcategory(name: "Voltage", options: ["12kV", "25kV", "35kV"], required: true)
        ])
    ]
    
    let config = VerticalMeasurementConfiguration(
        type: .midspan,
        accuracy: .highAccuracy,
        inventoryClasses: nil,
        wireClasses: conductorTypes,
        guyWireOptions: nil,
        ownerOptions: ["Primary Utility", "Secondary Utility"],
        shouldCaptureAttachments: false
    )
    
    do {
        let result = try await cloneable.startVerticalMeasurement(config: config)
        await processDetailedMidspanResult(result)
    } catch {
        await handleMeasurementError(error)
    }
}
```

## Guy anchor measurements

### Basic guy wire measurement

```swift theme={null}
func startGuyMeasurement() async {
    do {
        // Guy wire measurements use a simplified workflow
        let result = try await cloneable.startGuyWorkflow()
        await processGuyMeasurementResult(result)
        
    } catch {
        print("Guy wire measurement failed: \(error)")
        await handleMeasurementError(error)
    }
}
```

### Guy anchor measurement with location context

```swift theme={null}
func startGuyMeasurementWithContext() async {
    // Ensure pole location is available for guy anchor calculations
    guard let poleLocation = getCurrentPoleLocation() else {
        await showLocationRequiredAlert()
        return
    }
    
    do {
        let result = try await cloneable.startGuyWorkflow()
        
        // Calculate anchor location using pole location and guy measurements
        let anchorLocation = calculateAnchorLocation(
            poleLocation: poleLocation,
            guyVector: result
        )
        
        await processGuyWithLocation(result, anchorLocation: anchorLocation)
        
    } catch {
        await handleMeasurementError(error)
    }
}
```

## Workflow state management

### Manage active workflows

```swift theme={null}
class WorkflowManager: ObservableObject {
    @Published var isWorkflowActive = false
    @Published var currentWorkflowType: WorkflowType?
    
    enum WorkflowType {
        case pole
        case midspan
        case guy
    }
    
    func startWorkflow(_ type: WorkflowType, with cloneable: CloneablePlatform) async {
        guard !isWorkflowActive else {
            print("Workflow already active")
            return
        }
        
        DispatchQueue.main.async {
            self.isWorkflowActive = true
            self.currentWorkflowType = type
        }
        
        defer {
            DispatchQueue.main.async {
                self.isWorkflowActive = false
                self.currentWorkflowType = nil
            }
        }
        
        switch type {
        case .pole:
            await startPoleMeasurement(with: cloneable)
        case .midspan:
            await startMidspanMeasurement(with: cloneable)
        case .guy:
            await startGuyMeasurement(with: cloneable)
        }
    }
}
```

## Result processing examples

### Basic result processing

```swift theme={null}
func processPoleMeasurementResult(_ result: CloneableJSON) async {
    // Extract basic measurements
    if let poleInfo = result["pole_information"],
       let height = poleInfo["height"]?.getNumberValue() {
        print("Measured pole height: \(height) feet")
    }
    
    // Extract location
    if let location = result["pole_information"]?["location"]?.getLocationValue() {
        print("Pole location: \(location.coordinate)")
    }
    
    // Save complete result
    await saveResultToDatabase(result)
    
    // Show success message
    await showMeasurementComplete()
}

func processGuyMeasurementResult(_ result: GuyAnchorVector) async {
    print("Guy wire measured:")
    print("  Lead length: \(result.leadLength) feet")
    print("  Angle: \(result.angle)° from north")
    
    // Save guy data
    await saveGuyDataToDatabase(result)
    
    // Show completion
    await showGuyMeasurementComplete()
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.