/*
 * Go2Sensor.c
 *
 * Gocator system communication library
 * Copyright (C) 2010 by LMI Technologies Inc.
 *
 * Licensed under The MIT License.
 * Redistributions of files must retain the above copyright notice.
 */
#include <z/zGo2Sensor.h>
#include <z/zGo2System.h>
#include <z/zGo2Api.h>

GO2_EXPORT(Go2Status) Go2Sensor_Construct(Go2Sensor* sensor, Go2System system, z32u deviceId)
{
    Go2Sensor output = zNIL;
    Go2Status status = GO2_OK;

    zCHECK(zCalloc(&output, 1, sizeof(Go2SensorClass)));

    if (!zSUCCESS(status = Go2Sensor_Init(output, system, deviceId)))
    {
        zCHECK(Go2Object_Destroy(output));
        return status;
    }

    *sensor = output;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_Init(Go2Sensor sensor, Go2System system, z32u deviceId)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zXmlItem tempItem;

    zCHECK(Go2Object_Init(sensor, GO2_TYPE_SENSOR));

    obj->Release = Go2Sensor_VRelease;
    obj->system = system;
    obj->id = deviceId;
    obj->role = GO2_SENSOR_ROLE_INVALID;
    
    zCHECK(zXml_Construct(&obj->custom));
    zCHECK(zXml_AddItem(obj->custom, zNIL, "Custom", &tempItem));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_VRelease(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(zXml_Destroy(obj->custom));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_Destroy(Go2Sensor sensor)
{
    return Go2Object_Destroy(sensor);
}

GO2_EXPORT(Go2Status) Go2Sensor_ClearConfig(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    obj->hasConfig = zFALSE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ReadConfig(Go2Sensor sensor, zXml xml, zXml item)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zXmlItem exposureStepItem, stepItem, customItem, tempItem;
    Go2UInt32 i;
    zText256 tempText;
    z32u role;

    zCHECK(zXml_Attr32u(xml, item, "role", &role));
    if(role == 0)
    {
        obj->role = GO2_SENSOR_ROLE_MAIN;
    }
    else
    {
        obj->role = GO2_SENSOR_ROLE_BUDDY;
    }

    zCHECK(zXml_Child64f(xml, item, "Profiling/Exposure", &obj->exposure));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ExposureMin", &obj->exposureMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ExposureMax", &obj->exposureMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/DynamicExposureMin", &obj->dynamicExposureMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/DynamicExposureMax", &obj->dynamicExposureMax));
    zCHECK(zXml_Child32s(xml, item, "Profiling/ExposureMode", (Go2Int32*) &obj->exposureMode));
    zCHECK(zXml_Child32u(xml, item, "Profiling/ExposureTrainingEnabled", &obj->exposureTrainingEnabled));
    zCHECK(zXml_Child32u(xml, item, "Profiling/IntensityStepIndex", &obj->intensityStepIndex));
    zCHECK(zXml_Child32u(xml, item, "Profiling/ExposureDelay", &obj->exposureDelay));

    exposureStepItem = zXml_Child(xml, item, "Profiling/ExposureStep");
    if(!zIS_NIL(exposureStepItem))
    {
        obj->exposureStepCount = zXml_ChildCount(xml, exposureStepItem);
        for(i = 0; i < obj->exposureStepCount; i++)
        {
            stepItem = zXml_ChildAt(xml, exposureStepItem, i);   //These are "Step" items
            zCHECK(zXml_Item64f(xml, stepItem, &(obj->exposureSteps[i])));
        }
    }
    else
    {
        obj->exposureStepCount = 0;
    }

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaXMin", &obj->activeAreaXMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaXMax", &obj->activeAreaXMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaX", &obj->activeAreaX));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaYMin", &obj->activeAreaYMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaYMax", &obj->activeAreaYMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaY", &obj->activeAreaY));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaZMin", &obj->activeAreaZMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaZMax", &obj->activeAreaZMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaZ", &obj->activeAreaZ));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaWidthMin", &obj->activeAreaWidthMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaWidthMax", &obj->activeAreaWidthMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaWidth", &obj->activeAreaWidth));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaLengthMin", &obj->activeAreaLengthMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaLengthMax", &obj->activeAreaLengthMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaLength", &obj->activeAreaLength));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaHeightMin", &obj->activeAreaHeightMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaHeightMax", &obj->activeAreaHeightMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ActiveAreaHeight", &obj->activeAreaHeight));

    zCHECK(zXml_ChildText(xml, item, "Profiling/XSubsamplingOptions", tempText, zCOUNT(tempText)));
    zCHECK(Go2OptionList_Parse(tempText, obj->xResolutionDividerOptions, zCOUNT(obj->xResolutionDividerOptions), &obj->xResolutionDividerOptionCount));

    zCHECK(zXml_Child32u(xml, item, "Profiling/XSubsampling", &obj->xResolutionDivider));

    zCHECK(zXml_ChildText(xml, item, "Profiling/ZSubsamplingOptions", tempText, zCOUNT(tempText)));
    zCHECK(Go2OptionList_Parse(tempText, obj->zResolutionDividerOptions, zCOUNT(obj->zResolutionDividerOptions), &obj->zResolutionDividerOptionCount));

    zCHECK(zXml_Child32u(xml, item, "Profiling/ZSubsampling", &obj->zResolutionDivider));

    zCHECK(zXml_Child64f(xml, item, "Profiling/ResolutionMin", &obj->resolutionMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/ResolutionMax", &obj->resolutionMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/Resolution", &obj->resolution));

    zCHECK(zXml_Child32u(xml, item, "Profiling/FrontCameraX", &obj->frontCameraX));
    zCHECK(zXml_Child32u(xml, item, "Profiling/FrontCameraY", &obj->frontCameraY));
    zCHECK(zXml_Child32u(xml, item, "Profiling/FrontCameraWidth", &obj->frontCameraWidth));
    zCHECK(zXml_Child32u(xml, item, "Profiling/FrontCameraHeight", &obj->frontCameraHeight));

    zCHECK(zXml_Child32u(xml, item, "Profiling/BackCameraX", &obj->backCameraX));
    zCHECK(zXml_Child32u(xml, item, "Profiling/BackCameraY", &obj->backCameraY));
    zCHECK(zXml_Child32u(xml, item, "Profiling/BackCameraWidth", &obj->backCameraWidth));
    zCHECK(zXml_Child32u(xml, item, "Profiling/BackCameraHeight", &obj->backCameraHeight));

    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedX", &obj->calibratedX));
    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedY", &obj->calibratedY));
    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedZ", &obj->calibratedZ));
    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedWidth", &obj->calibratedWidth));
    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedLength", &obj->calibratedLength));
    zCHECK(zXml_Child64f(xml, item, "Profiling/CalibratedHeight", &obj->calibratedHeight));

    zCHECK(zXml_Child32u(xml, item, "Profiling/Tracking/Enabled", &obj->trackingEnabled));
    zCHECK(zXml_Child64f(xml, item, "Profiling/Tracking/AreaHeight", &obj->trackingAreaHeight));
    zCHECK(zXml_Child64f(xml, item, "Profiling/Tracking/AreaHeightMin", &obj->trackingAreaHeightMin));
    zCHECK(zXml_Child64f(xml, item, "Profiling/Tracking/AreaHeightMax", &obj->trackingAreaHeightMax));
    zCHECK(zXml_Child64f(xml, item, "Profiling/Tracking/SearchThreshold", &obj->trackingSearchThreshold));

    zCHECK(zXml_Clear(obj->custom));
    customItem = zXml_Child(xml, item, "Custom");

    if (!zIS_NIL(customItem))
    {
        zCHECK(zXml_CopyItem(obj->custom, zNIL, zNIL, xml, customItem, &tempItem));
    }

    obj->hasConfig = zTRUE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_WriteConfig(Go2Sensor sensor, zXml xml, zXml item)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zXmlItem profilingItem, exposureStepItem, stepItem, customItem;
    Go2UInt32 i;

    if(obj->role == GO2_SENSOR_ROLE_MAIN)
    {
        zCHECK(zXml_SetAttr32u(xml, item, "role", 0));
    }
    else
    {
        zCHECK(zXml_SetAttr32u(xml, item, "role", 1));
    }

    zCHECK(zXml_SetChild64f(xml, item, "Profiling/Exposure", obj->exposure));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/DynamicExposureMin", obj->dynamicExposureMin));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/DynamicExposureMax", obj->dynamicExposureMax));
    zCHECK(zXml_SetChild32s(xml, item, "Profiling/ExposureMode", obj->exposureMode));
    zCHECK(zXml_SetChild32u(xml, item, "Profiling/ExposureDelay", obj->exposureDelay));
    zCHECK(zXml_SetChild32u(xml, item, "Profiling/ExposureTrainingEnabled", obj->exposureTrainingEnabled));
    zCHECK(zXml_SetChild32u(xml, item, "Profiling/IntensityStepIndex", obj->intensityStepIndex));

    profilingItem = zXml_Child(xml, item, "Profiling");
    zCHECK(zXml_AddItem(xml, profilingItem, "ExposureStep", &exposureStepItem));
    for(i = 0; i < obj->exposureStepCount; i++)
    {
        zCHECK(zXml_AddItem(xml, exposureStepItem, "Step", &stepItem));
        zCHECK(zXml_SetItem64f(xml, stepItem, obj->exposureSteps[i]));
    }

    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaX", obj->activeAreaX));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaY", obj->activeAreaY));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaZ", obj->activeAreaZ));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaWidth", obj->activeAreaWidth));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaLength", obj->activeAreaLength));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/ActiveAreaHeight", obj->activeAreaHeight));

    zCHECK(zXml_SetChild32u(xml, item, "Profiling/XSubsampling", obj->xResolutionDivider));
    zCHECK(zXml_SetChild32u(xml, item, "Profiling/ZSubsampling", obj->zResolutionDivider));

    zCHECK(zXml_SetChild64f(xml, item, "Profiling/Resolution", obj->resolution));

    zCHECK(zXml_SetChild32u(xml, item, "Profiling/Tracking/Enabled", obj->trackingEnabled));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/Tracking/AreaHeight", obj->trackingAreaHeight));
    zCHECK(zXml_SetChild64f(xml, item, "Profiling/Tracking/SearchThreshold", obj->trackingSearchThreshold));

    //Custom config element for the sensor block
    zCHECK(zXml_CopyItem(xml, item, zNIL, obj->custom, zXml_Root(obj->custom), &customItem));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ClearInfo(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    obj->hasInfo = zFALSE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ReadInfo(Go2Sensor sensor, const Go2SensorInfo* info)

{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    if (!zSUCCESS(Go2SensorModel_Parse(info->model, &obj->model)))   //doesn't work with the existence of a base library that could have any name
    {
        obj->model = 0;
    }

    strcpy(obj->modelString, info->model);

    obj->id = info->deviceId;
    obj->role = info->role;
    obj->firmwareVersion = info->firmwareVersion;
    obj->isHost = info->isHost;

    obj->hasInfo = zTRUE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ClearTransform(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    obj->hasTransform = zFALSE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ReadTransform(Go2Sensor sensor, zXml xml, zXml item)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    z32u role;
    
    zCHECK(zXml_Attr32u(xml, item, "id", &role));
    if(role == 0)
    {
        obj->role = GO2_SENSOR_ROLE_MAIN;
    }
    else
    {
        obj->role = GO2_SENSOR_ROLE_BUDDY;
    }

    zCHECK(zXml_Child64f(xml, item, "X", &obj->xOffset));
    zCHECK(zXml_Child64f(xml, item, "Y", &obj->yOffset));
    zCHECK(zXml_Child64f(xml, item, "Z", &obj->zOffset));

    zCHECK(zXml_Child64f(xml, item, "XAngle", &obj->xAngle));
    zCHECK(zXml_Child64f(xml, item, "YAngle", &obj->yAngle));
    zCHECK(zXml_Child64f(xml, item, "ZAngle", &obj->zAngle));
    
    zCHECK(zXml_Child32u(xml, item, "Orientation", (Go2UInt32*) &obj->orientation));

    obj->hasTransform = zTRUE;

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_WriteTransform(Go2Sensor sensor, zXml xml, zXml item)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    if(obj->role == GO2_SENSOR_ROLE_MAIN)
    {
        zCHECK(zXml_SetAttr32u(xml, item, "id", 0));
    }
    else
    {
        zCHECK(zXml_SetAttr32u(xml, item, "id", 1));
    }

    zCHECK(zXml_SetChild64f(xml, item, "X", obj->xOffset));
    zCHECK(zXml_SetChild64f(xml, item, "Y", obj->yOffset));
    zCHECK(zXml_SetChild64f(xml, item, "Z", obj->zOffset));
    zCHECK(zXml_SetChild64f(xml, item, "XAngle", obj->xAngle));
    zCHECK(zXml_SetChild64f(xml, item, "YAngle", obj->yAngle));
    zCHECK(zXml_SetChild64f(xml, item, "ZAngle", obj->zAngle));
    zCHECK(zXml_SetChild32u(xml, item, "Orientation", obj->orientation));

    return GO2_OK;
}


GO2_EXPORT(Go2UInt32) Go2Sensor_Id(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->id;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_Model(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->model;
}

GO2_EXPORT(Go2Version) Go2Sensor_FirmwareVersion(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->firmwareVersion;
}

GO2_EXPORT(Go2Bool) Go2Sensor_IsOnline(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->hasInfo;
}

GO2_EXPORT(Go2Bool) Go2Sensor_IsHost(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->isHost;
}

GO2_EXPORT(Go2Status) Go2Sensor_CheckConfigurable(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system));

    if (!Go2Sensor_IsOnline(sensor) || 
        !(Go2Sensor_Role(sensor) == GO2_SENSOR_ROLE_MAIN || Go2Sensor_Role(sensor) == GO2_SENSOR_ROLE_BUDDY))
    {
        return zERROR_STATE;
    }

    return GO2_OK;
}

GO2_EXPORT(Go2SensorRole) Go2Sensor_Role(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->role;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetRole(Go2Sensor sensor, Go2SensorRole role)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    if(!obj->hasInfo)
    {
        return zERROR_STATE;
    }
    if ((obj->role == GO2_SENSOR_ROLE_MAIN) || !(role == GO2_SENSOR_ROLE_BUDDY || role == GO2_SENSOR_ROLE_UNASSIGNED))
    {
        //can only set role if sensor is not main and can only set role to BUDDY or UNASSIGNED
        return zERROR_PARAMETER;
    }

    zCHECK(Go2System_ChangeRole(obj->system, sensor, role));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ExposureMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureMax;
}

GO2_EXPORT(Go2Double) Go2Sensor_ExposureMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureMin;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetExposure(Go2Sensor sensor, Go2Double exposure)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));

    zCHECK(Go2System_Set64f(obj->system, &obj->exposure, exposure, obj->exposureMin, obj->exposureMax));

    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_Exposure(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposure;
}

GO2_EXPORT(Go2ExposureMode) Go2Sensor_ExposureMode(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureMode;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetExposureMode(Go2Sensor sensor, Go2ExposureMode mode)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    obj->exposureMode = mode;
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_ExposureDelay(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureDelay;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetExposureDelay(Go2Sensor sensor, Go2UInt32 delay)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    obj->exposureDelay = delay;
    return Go2System_SyncConfig(obj->system);
}

GO2_EXPORT(Go2Status) Go2Sensor_AddExposureStep(Go2Sensor sensor, Go2Double exposure)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    if(obj->exposureStepCount < GO2_MAX_EXPOSURES)
    {
        zCHECK(Go2System_Set64f(obj->system, &(obj->exposureSteps[obj->exposureStepCount]), exposure, obj->exposureMin, obj->exposureMax));
        obj->exposureStepCount++;
    }
    else
    {
        return GO2_ERROR;
    }
    zCHECK(Go2System_SyncConfig(obj->system));
    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_ClearExposureSteps(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    obj->exposureStepCount = 0;
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ExposureStepAt(Go2Sensor sensor, Go2UInt32 index)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureSteps[index];
}

GO2_EXPORT(Go2UInt32) Go2Sensor_ExposureStepCount(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureStepCount;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_IntensityStepIndex(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->intensityStepIndex;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_SetIntensityStepIndex(Go2Sensor sensor, Go2UInt32 index)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    obj->intensityStepIndex = index;
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_DynamicExposureMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->dynamicExposureMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetDynamicExposureMax(Go2Sensor sensor, Go2Double exposure)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->dynamicExposureMax, exposure, obj->exposureMin, obj->exposureMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_DynamicExposureMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->dynamicExposureMin;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetDynamicExposureMin(Go2Sensor sensor, Go2Double exposure)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->dynamicExposureMin, exposure, obj->exposureMin, obj->exposureMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Status) Go2Sensor_EnableExposureTraining(Go2Sensor sensor, Go2Bool enable)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    Go2UInt32 i;

    zCHECK(Go2Sensor_CheckConfigurable(sensor));

    if(enable)
    {
        //disable other sensors in the system
        for (i = 0; i < Go2System_SensorCount(obj->system); ++i)
        {
            Go2Sensor sensor = Go2System_SensorAt(obj->system, i);

            if ((Go2Sensor_Role(sensor) == GO2_SENSOR_ROLE_MAIN || Go2Sensor_Role(sensor) == GO2_SENSOR_ROLE_BUDDY) &&
                Go2Sensor_ExposureTrainingEnabled(sensor))
            {
                Go2Sensor_EnableExposureTraining(sensor, GO2_FALSE);
            }
        }
    }
    
    obj->exposureTrainingEnabled = enable;
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Bool) Go2Sensor_ExposureTrainingEnabled(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->exposureTrainingEnabled;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaLengthMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaLengthMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaLengthMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaLengthMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaLength(Go2Sensor sensor, Go2Double length)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaLength, length, obj->activeAreaLengthMin, obj->activeAreaLengthMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaLength(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaLength;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaYMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaYMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaYMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaYMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaY(Go2Sensor sensor, Go2Double y)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaY, y, obj->activeAreaYMin, obj->activeAreaYMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaY(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaY;
}



GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaHeightMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaHeightMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaHeightMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaHeightMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaHeight(Go2Sensor sensor, Go2Double height)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaHeight, height, obj->activeAreaHeightMin, obj->activeAreaHeightMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaHeight(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaHeight;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaZMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaZMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaZMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaZMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaZ(Go2Sensor sensor, Go2Double z)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaZ, z, obj->activeAreaZMin, obj->activeAreaZMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaZ(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaZ;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaWidthMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaWidthMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaWidthMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaWidthMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaWidth(Go2Sensor sensor, Go2Double width)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaWidth, width, obj->activeAreaWidthMin, obj->activeAreaWidthMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaWidth(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaWidth;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaXMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaXMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaXMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaXMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetActiveAreaX(Go2Sensor sensor, Go2Double x)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->activeAreaX, x, obj->activeAreaXMin, obj->activeAreaXMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ActiveAreaX(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->activeAreaX;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_XResolutionDividerOptionCount(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->xResolutionDividerOptionCount;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_XResolutionDividerOptionAt(Go2Sensor sensor, Go2UInt32 index)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->xResolutionDividerOptions[index];
}

GO2_EXPORT(Go2Status) Go2Sensor_SetXResolutionDivider( Go2Sensor sensor, Go2UInt32 xResolutionDivider )
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_SetOption(obj->system, &obj->xResolutionDivider, xResolutionDivider, obj->xResolutionDividerOptions, obj->xResolutionDividerOptionCount));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_XResolutionDivider(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->xResolutionDivider;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_ZResolutionDividerOptionCount(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->zResolutionDividerOptionCount;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_ZResolutionDividerOptionAt(Go2Sensor sensor, Go2UInt32 index)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->zResolutionDividerOptions[index];
}

GO2_EXPORT(Go2Status) Go2Sensor_SetZResolutionDivider( Go2Sensor sensor, Go2UInt32 zResolutionDivider )
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_SetOption(obj->system, &obj->zResolutionDivider, zResolutionDivider, obj->zResolutionDividerOptions, obj->zResolutionDividerOptionCount));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_ZResolutionDivider(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->zResolutionDivider;
}

GO2_EXPORT(Go2Double) Go2Sensor_ResolutionMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->resolutionMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_ResolutionMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->resolutionMax;
}

GO2_EXPORT(Go2Double) Go2Sensor_Resolution(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->resolution;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetResolution(Go2Sensor sensor, Go2Double resolution)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->resolution, resolution, obj->resolutionMin, obj->resolutionMax));
    zCHECK(Go2System_SyncConfig(obj->system));    

    return GO2_OK;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_FrontCameraX(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->frontCameraX;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_FrontCameraY(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->frontCameraY;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_FrontCameraWidth(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->frontCameraWidth;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_FrontCameraHeight(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->frontCameraHeight;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_BackCameraX(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->backCameraX;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_BackCameraY(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->backCameraY;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_BackCameraWidth(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->backCameraWidth;
}

GO2_EXPORT(Go2UInt32) Go2Sensor_BackCameraHeight(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->backCameraHeight;
}


GO2_EXPORT(Go2Double) Go2Sensor_CalibratedX(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedX;
}

GO2_EXPORT(Go2Double) Go2Sensor_CalibratedY(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedY;
}

GO2_EXPORT(Go2Double) Go2Sensor_CalibratedZ(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedZ;
}

GO2_EXPORT(Go2Double) Go2Sensor_CalibratedWidth(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedWidth;
}

GO2_EXPORT(Go2Double) Go2Sensor_CalibratedLength(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedLength;
}

GO2_EXPORT(Go2Double) Go2Sensor_CalibratedHeight(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->calibratedHeight;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetXOffset(Go2Sensor sensor, Go2Double offset)
{    
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->xOffset = offset;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_XOffset(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->xOffset;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetZOffset(Go2Sensor sensor, Go2Double offset)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->zOffset = offset;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_YOffset(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->yOffset;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetYOffset(Go2Sensor sensor, Go2Double offset)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->yOffset = offset;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ZOffset(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->zOffset;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetAngle(Go2Sensor sensor, Go2Double angle)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->yAngle = angle;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_Angle(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->yAngle;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetXAngle( Go2Sensor sensor, Go2Double xAngle )
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->xAngle = xAngle;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_XAngle(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->xAngle;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetYAngle( Go2Sensor sensor, Go2Double yAngle )
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->yAngle = yAngle;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_YAngle(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->yAngle;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetZAngle( Go2Sensor sensor, Go2Double zAngle )
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->zAngle = zAngle;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_ZAngle(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->zAngle;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetOrientation(Go2Sensor sensor, Go2SensorOrientation orientation)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2System_CheckConfigurable(obj->system)); //check system, not sensor, because this really is a system setting
    obj->orientation = orientation;
    zCHECK(Go2System_SyncTransform(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2SensorOrientation) Go2Sensor_Orientation(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->orientation;
}

GO2_EXPORT(Go2Status) Go2Sensor_EnableTracking(Go2Sensor sensor, Go2Bool enable)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    obj->trackingEnabled = enable;
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Bool) Go2Sensor_TrackingEnabled(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->trackingEnabled;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetTrackingAreaHeight(Go2Sensor sensor, Go2Double height)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->trackingAreaHeight, height, obj->trackingAreaHeightMin, obj->trackingAreaHeightMax));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_TrackingAreaHeight(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->trackingAreaHeight;
}

GO2_EXPORT(Go2Double) Go2Sensor_TrackingAreaHeightMin(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->trackingAreaHeightMin;
}

GO2_EXPORT(Go2Double) Go2Sensor_TrackingAreaHeightMax(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->trackingAreaHeightMax;
}

GO2_EXPORT(Go2Status) Go2Sensor_SetTrackingSearchThreshold(Go2Sensor sensor, Go2Double threshold)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    zCHECK(Go2Sensor_CheckConfigurable(sensor));
    zCHECK(Go2System_Set64f(obj->system, &obj->trackingSearchThreshold, threshold, 0.0, 100.0));
    zCHECK(Go2System_SyncConfig(obj->system));

    return GO2_OK;
}

GO2_EXPORT(Go2Double) Go2Sensor_TrackingSearchThreshold(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);
    return obj->trackingSearchThreshold;
}

GO2_EXPORT(zXml) Go2Sensor_CustomElement(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    return obj->custom;
}

GO2_EXPORT(zChar*) Go2Sensor_ModelString(Go2Sensor sensor)
{
    Go2SensorClass* obj = zHANDLE_POINTER(sensor);

    return obj->modelString;
}