#include "ltedsapi_stdtmpl.h"
#include <string.h>

static INT LTEDS_GetBaseCalInfo(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_BASE_CAL *info) {
    INT err = LTEDS_GetDate(ctx, 16, info ? &info->Date : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetChr5(ctx, 15, info ? info->Initials : NULL);
    if (err == LTEDS_OK) {
        DWORD val;
        err = LTEDS_GetUnInt(ctx, 12, &val);
        if ((err == LTEDS_OK) && (info != NULL)) {
            info->PeriodDays = val & 0xFFF;
        }
    }
    return err;
}


static INT LTEDS_PutBaseCalInfo(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_BASE_CAL *info) {
    INT err = LTEDS_PutDate(ctx, 16, &info->Date);
    if (err == LTEDS_OK)
        err = LTEDS_PutChr5(ctx, 15, info->Initials);
    if (err == LTEDS_OK)
        err = LTEDS_PutUnInt(ctx, 12, info->PeriodDays);
    return err;
}


static INT LTEDS_GetPhysicalRangeInfo(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_PHYSMEAS_RANGE *info) {
    DWORD val;
    INT err = LTEDS_GetSelectCase(ctx, 6, &val);
    if ((err == LTEDS_OK) && (info != NULL)) {
        info->Measurand = val & 0x3F;
    }

    if (err == LTEDS_OK)
        err = LTEDS_GetSingle(ctx, info ? &info->MinValue : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetSingle(ctx, info ? &info->MaxValue : NULL);
    return err;
}

static INT LTEDS_PutPhysicalRangeInfo(TLTEDS_ENCODE_CONTEXT *ctx,  const TLTEDS_INFO_PHYSMEAS_RANGE *info) {
    INT err = LTEDS_PutSelectCase(ctx, 6, info->Measurand);
    if (err == LTEDS_OK) {
        err = LTEDS_PutSingle(ctx, info->MinValue);
    }
    if (err == LTEDS_OK) {
        err = LTEDS_PutSingle(ctx, info->MaxValue);
    }
    return err;
}



static INT LTEDS_GetExcitationLevelsInfo(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_EXCITATION_LEVELS *info) {
    INT err = LTEDS_GetConRes(ctx, 9, 0.1, 0.1, info ? &info->NominalValue : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetConRes(ctx, 9, 0.1, 0.1, info ? &info->MinValue : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetConRes(ctx, 9, 0.1, 0.1, info ? &info->MaxValue : NULL);
    return err;
}

static INT LTEDS_PutExcitationLevelsInfo(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_EXCITATION_LEVELS *info) {
    INT err = LTEDS_PutConRes(ctx, 9, 0.1, 0.1, info->NominalValue);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRes(ctx, 9, 0.1, 0.1, info->MinValue);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRes(ctx, 9, 0.1, 0.1, info->MaxValue);
    return err;
}


static INT LTEDS_GetMeasLocationID(TLTEDS_DECODE_CONTEXT *ctx, WORD *id) {
    DWORD val;
    INT err = LTEDS_GetUnInt(ctx, 11, &val);
    if ((err == LTEDS_OK) && (id != NULL)) {
        *id = val & 0x7FF;
    }
    return err;
}

static INT LTEDS_PutMeasLocationID(TLTEDS_ENCODE_CONTEXT *ctx, WORD id) {
    return LTEDS_PutUnInt(ctx, 11, id);
}


static INT LTEDS_AccForceGetSens(TLTEDS_DECODE_CONTEXT *ctx, double *sens) {
    return LTEDS_GetConRelRes(ctx, 16, 5E-7, 0.00015, sens);
}

static INT LTEDS_AccForcePutSens(TLTEDS_ENCODE_CONTEXT *ctx, double sens) {
    return LTEDS_PutConRelRes(ctx, 16, 5E-7, 0.00015, sens);
}

static INT LTEDS_AccForceGetFHP(TLTEDS_DECODE_CONTEXT *ctx, double *fhp) {
    return LTEDS_GetConRelRes(ctx, 8, 0.005, 0.03, fhp);
}

static INT LTEDS_AccForcePutFHP(TLTEDS_ENCODE_CONTEXT *ctx, double fhp) {
    return LTEDS_PutConRelRes(ctx, 8, 0.005, 0.03, fhp);
}

static INT LTEDS_AccForceGetProgSens(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_ACCF_PROG_SENS *info) {
    DWORD val;
    INT err;

    err = LTEDS_GetUnInt(ctx, 2, &val);
    if ((err == LTEDS_OK) && info)
        info->DefaultSens = val & 3;
    if (err == LTEDS_OK) {
        err = LTEDS_GetUnInt(ctx, 1, &val);
        if ((err == LTEDS_OK) && info)
            info->SupportPassiveMode = val != 0;
    }
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetSens(ctx, info ? &info->Low.Sens : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetSens(ctx, info ? &info->High.Sens : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetFHP(ctx, info ? &info->Low.Fhp : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetFHP(ctx, info ? &info->High.Fhp : NULL);

    return err;
}


static INT LTEDS_AccForcePutProgSens(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_ACCF_PROG_SENS *info) {
    INT err;
    err = LTEDS_PutUnInt(ctx, 2, info->DefaultSens);
    if (err == LTEDS_OK)
        err = LTEDS_PutUnInt(ctx, 1, info->SupportPassiveMode);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutSens(ctx, info->Low.Sens);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutSens(ctx, info->High.Sens);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutFHP(ctx, info->Low.Fhp);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutFHP(ctx, info->High.Fhp);
    return err;
}


static INT LTEDS_AccForceGetMeasForce(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_ACCF_FORCE *info) {
    INT err = LTEDS_GetConRelRes(ctx, 6, 1e6, 0.1, info ? &info->Stiffness : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetConRelRes(ctx, 6, 0.1, 0.1, info ? &info->MassBelow : NULL);
    return err;
}


static INT LTEDS_AccForcePutMeasForce(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_ACCF_FORCE *info) {
    INT err = LTEDS_PutConRelRes(ctx, 6, 1e6, 0.1, info->Stiffness);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRelRes(ctx, 6, 0.1, 0.1, info->MassBelow);
    return err;
}



static INT LTEDS_AccForceGetTF(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_ACCF_TF *info) {
    DWORD val;
    INT err;
    err = LTEDS_GetSelectCase(ctx, 1, &val);
    if (err == LTEDS_OK) {
        BOOLEAN isSpecified = val != 0;
        if (info)
            info->IsSpecified = isSpecified;
        if (isSpecified) {
            err = LTEDS_GetConRelRes(ctx, 7, 10, 0.05, info ? &info->Flp : NULL);
            if (err == LTEDS_OK)
                err = LTEDS_GetConRelRes(ctx, 9, 100, 0.01, info ? &info->Fpres : NULL);
            if (err == LTEDS_OK)
                err = LTEDS_GetConRelRes(ctx, 9, 0.4, 0.01, info ? &info->Qp : NULL);
            if (err == LTEDS_OK)
                err = LTEDS_GetConRes(ctx, 7, -6.3, 0.1, info ? &info->AmpSlope : NULL);
            if (err == LTEDS_OK)
                err = LTEDS_GetConRes(ctx, 6, -0.8, 0.025, info ? &info->TempCoef : NULL);
        }
    }
    return  err;
}

static INT LTEDS_AccForcePutTF(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_ACCF_TF *info) {
    INT err;
    err = LTEDS_PutSelectCase(ctx, 1, info->IsSpecified);
    if ((err == LTEDS_OK) && info->IsSpecified) {

        err = LTEDS_PutConRelRes(ctx, 7, 10, 0.05, info->Flp);
        if (err == LTEDS_OK)
            err = LTEDS_PutConRelRes(ctx, 9, 100, 0.01, info->Fpres);
        if (err == LTEDS_OK)
            err = LTEDS_PutConRelRes(ctx, 9, 0.4, 0.01, info->Qp);
        if (err == LTEDS_OK)
            err = LTEDS_PutConRes(ctx, 7, -6.3, 0.1, info->AmpSlope);
        if (err == LTEDS_OK)
            err = LTEDS_PutConRes(ctx, 6, -0.8, 0.025, info->TempCoef);
    }
    return  err;
}


static INT LTEDS_AccForceGetCalInfo(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_ACCF_CALINFO *info) {
    INT err;

    err = LTEDS_GetConRelRes(ctx, 8, 0.35, 0.0175, info ? &info->RefFreq : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetConRes(ctx, 5, 15, 0.5, info ? &info->RefTemp : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetBaseCalInfo(ctx, info ? &info->Base : NULL);
    return err;
}

static INT LTEDS_AccForcePutCalInfo(TLTEDS_ENCODE_CONTEXT *ctx, const TLTEDS_INFO_ACCF_CALINFO *info) {
    INT err;

    err = LTEDS_PutConRelRes(ctx, 8, 0.35, 0.0175, info->RefFreq);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRes(ctx, 5, 15, 0.5, info->RefTemp);
    if (err == LTEDS_OK)
        err = LTEDS_PutBaseCalInfo(ctx, &info->Base);
    return err;
}


LTEDSAPI_DllExport(INT) LTEDS_GetTmpltInfoAccForce(TLTEDS_DECODE_CONTEXT *ctx,
                                                   TLTEDS_INFO_TMPLT_ACCFORCE *info) {
    INT err = LTEDS_OK;
    DWORD val;
    BYTE TransType = 0;
    BOOLEAN prog_sens = FALSE;

    err = LTEDS_GetSelectCase(ctx, 1, &val);
    if (err == LTEDS_OK)
        TransType = val & 1;
    err = LTEDS_GetSelectCase(ctx, 1, &val);
    if (err == LTEDS_OK)
        prog_sens = val != 0;

    if (err == LTEDS_OK) {
        if (info) {
            info->Meas.TransducerType = TransType;
            info->Meas.HasProgrSens = prog_sens;
        }

        if (TransType == LTEDS_INFO_ACCF_TRANS_TYPE_ACC) {
            if (!prog_sens) {
                err = LTEDS_AccForceGetSens(ctx, info ? &info->Meas.SensInfo.Sens : NULL);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForceGetFHP(ctx, info ? &info->Meas.SensInfo.Fhp : NULL);
            } else {
                err = LTEDS_AccForceGetProgSens(ctx, info ? &info->Meas.ProgrSensInfo : NULL);
            }
        } else {
            if (!prog_sens) {
                err = LTEDS_AccForceGetSens(ctx, info ? &info->Meas.SensInfo.Sens : NULL);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForceGetFHP(ctx, info ? &info->Meas.SensInfo.Fhp : NULL);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForceGetMeasForce(ctx, info ? &info->Meas.Force : NULL);
                if ((err == LTEDS_OK) && info)
                    info->Meas.Force.PhaseCorrection = 0;
            } else {
                err = LTEDS_AccForceGetProgSens(ctx, info ? &info->Meas.ProgrSensInfo : NULL);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForceGetMeasForce(ctx, info ? &info->Meas.Force : NULL);
                if (err == LTEDS_OK)
                    err = LTEDS_GetConRes(ctx, 6, -3.2, 0.1, info ? &info->Meas.Force.PhaseCorrection : NULL);
            }
        }
    }

    if (err == LTEDS_OK) {
        err = LTEDS_GetEnumVal(ctx, 2, &val);
        if ((err == LTEDS_OK) && info)
            info->Meas.SensDirection = val & 3;
    }
    if (err == LTEDS_OK)
        err = LTEDS_GetConRelRes(ctx, 6, 0.1, 0.1, info ? &info->Meas.Weight : NULL);
    if (err == LTEDS_OK) {
        err = LTEDS_GetEnumVal(ctx, 1, &val);
        if ((err == LTEDS_OK) && info) {
            info->ElecSigOut.Sign = val & 1;
            info->ElecSigOut.SigType = LTEDS_INFO_ELECSIGTYPE_VOLTAGE_SENSOR;
            info->ElecSigOut.AcCoupling = TRUE;
            info->ElecSigOut.MapMeth = LTEDS_INFO_MAPMETH_LINEAR;
        }
    }
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetTF(ctx, info ? &info->TransfFunc : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_AccForceGetCalInfo(ctx, info ? &info->CalInfo : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetMeasLocationID(ctx, info ? &info->MeasLocationID : NULL);
    return err;
}


LTEDSAPI_DllExport(INT) LTEDS_PutTmpltInfoAccForce(TLTEDS_ENCODE_CONTEXT *ctx,
                                                   const TLTEDS_INFO_TMPLT_ACCFORCE *info) {
    INT err = LTEDS_OK;
    if ((info->Meas.TransducerType != LTEDS_INFO_ACCF_TRANS_TYPE_ACC) ||
            (info->Meas.TransducerType != LTEDS_INFO_ACCF_TRANS_TYPE_FORCE)) {
        err = LTEDS_ERROR_ENCODE_VALUE;
    } else  {
        err = LTEDS_PutSelectCase(ctx, 1, info->Meas.TransducerType);
    }

    if (err == LTEDS_OK) {
        err = LTEDS_PutSelectCase(ctx, 1, info->Meas.HasProgrSens);
    }

    if (err == LTEDS_OK) {
        if (info->Meas.TransducerType == LTEDS_INFO_ACCF_TRANS_TYPE_ACC) {
            if (!info->Meas.HasProgrSens) {
                err = LTEDS_AccForcePutSens(ctx, info->Meas.SensInfo.Sens);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForcePutFHP(ctx, info->Meas.SensInfo.Fhp);
            } else {
                err = LTEDS_AccForcePutProgSens(ctx, &info->Meas.ProgrSensInfo);
            }
        } else {
            if (!info->Meas.HasProgrSens) {
                err = LTEDS_AccForcePutSens(ctx, info->Meas.SensInfo.Sens);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForcePutFHP(ctx, info->Meas.SensInfo.Fhp);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForcePutMeasForce(ctx, &info->Meas.Force);
            } else {
                err = LTEDS_AccForcePutProgSens(ctx, &info->Meas.ProgrSensInfo);
                if (err == LTEDS_OK)
                    err = LTEDS_AccForcePutMeasForce(ctx, &info->Meas.Force);
                if (err == LTEDS_OK)
                    err = LTEDS_PutConRes(ctx, 6, -3.2, 0.1, info->Meas.Force.PhaseCorrection);
            }
        }
    }

    if (err == LTEDS_OK)
        err = LTEDS_PutEnumVal(ctx, 2, info->Meas.SensDirection);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRelRes(ctx, 6, 0.1, 0.1, info->Meas.Weight);
    if (err == LTEDS_OK)
        err = LTEDS_PutEnumVal(ctx, 1, info->ElecSigOut.Sign);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutTF(ctx, &info->TransfFunc);
    if (err == LTEDS_OK)
        err = LTEDS_AccForcePutCalInfo(ctx, &info->CalInfo);
    if (err == LTEDS_OK)
        err = LTEDS_PutMeasLocationID(ctx, info->MeasLocationID);


    return err;
}














LTEDSAPI_DllExport(INT) LTEDS_GetTmpltInfoHLVOut(TLTEDS_DECODE_CONTEXT *ctx,
                                                         TLTEDS_INFO_TMPLT_HLVOUT *info) {
    INT err = LTEDS_OK;
    DWORD val;

    err = LTEDS_GetPhysicalRangeInfo(ctx, info ? &info->Meas : NULL);
    if (err == LTEDS_OK) {
        DWORD PrecType = 0;
        err = LTEDS_GetSelectCase(ctx, 2, &PrecType);
        if (err == LTEDS_OK) {
            TLTEDS_INFO_HLV_ELECTRICAL el;
            el.SigType = LTEDS_INFO_ELECSIGTYPE_VOLTAGE_SENSOR;
            el.MapMeth = LTEDS_INFO_MAPMETH_LINEAR;
            el.Range.PrecType = PrecType & 3;
            if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_STD_0_10V) {
                el.Range.MinValue = 0;
                el.Range.MaxValue = 10;
            } else if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_STD_PM10V) {
                el.Range.MinValue = -10;
                el.Range.MaxValue = 10;
            } else if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_20MV) {
                err = LTEDS_GetConRes(ctx, 11, -20.48, 0.02, &el.Range.MinValue);
                if (err == LTEDS_OK)
                    err = LTEDS_GetConRes(ctx, 11, -20.48, 0.02, &el.Range.MaxValue);
            } else if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_FULL) {
                err = LTEDS_GetSingle(ctx, &el.Range.MinValue);
                if (err == LTEDS_OK)
                    err = LTEDS_GetSingle(ctx, &el.Range.MaxValue);
            } else {
                err = LTEDS_ERROR_UNKNOWN_SEL_CASE;
            }

            if (err == LTEDS_OK) {
                err = LTEDS_GetEnumVal(ctx, 1, &val);
                if (err == LTEDS_OK)
                    el.AcCoupling = val ? TRUE : FALSE;
            }

            if (err == LTEDS_OK) {
                err = LTEDS_GetConRelRes(ctx, 12, 1, 0.001706, &el.OutputImpedance);
            }
            if (err == LTEDS_OK) {
                err = LTEDS_GetConRelRes(ctx, 6, 1e-6, 0.146, &el.ResponseTime);
            }

            if ((err == LTEDS_OK) && (info != NULL)) {
                info->ElecSigOut = el;
            }
        }

        if (err == LTEDS_OK) {
            TLTEDS_INFO_HLV_POWSUPPLY supply;
            memset(&supply, 0, sizeof(supply));
            err = LTEDS_GetSelectCase(ctx, 1, &val);
            if (err == LTEDS_OK) {
                supply.IsRequired = val != 0;
                if (supply.IsRequired) {
                    err = LTEDS_GetExcitationLevelsInfo(ctx, &supply.Levels);
                    if (err == LTEDS_OK) {
                        err = LTEDS_GetEnumVal(ctx, 2, &val);
                        if (err == LTEDS_OK) {
                            supply.Type = val & 3;
                        }
                    }
                    if (err == LTEDS_OK) {
                        err = LTEDS_GetConRelRes(ctx, 6, 1e-6, 0.129462705898, &supply.CurrentDraw);
                    }
                }
            }

            if ((err == LTEDS_OK) && (info != NULL)) {
               info->PowerSupply = supply;
            }
        }

        if (err == LTEDS_OK)
            err = LTEDS_GetBaseCalInfo(ctx, info ? &info->CalInfo : NULL);
        if (err == LTEDS_OK)
            err = LTEDS_GetMeasLocationID(ctx, info ? &info->MeasLocationID : NULL);
    }
    return  err;
}


LTEDSAPI_DllExport(INT) LTEDS_PutTmpltInfoHLVOut(TLTEDS_ENCODE_CONTEXT *ctx,
                                                         const TLTEDS_INFO_TMPLT_HLVOUT *info) {
    INT err = LTEDS_OK;
    err = LTEDS_PutPhysicalRangeInfo(ctx, &info->Meas);
    if (err == LTEDS_OK)
        err = LTEDS_PutSelectCase(ctx, 2, info->ElecSigOut.Range.PrecType);
    if (err == LTEDS_OK) {
        BYTE PrecType = info->ElecSigOut.Range.PrecType;
        if ((PrecType != LTEDS_INFO_HLV_ELEC_PREC_STD_0_10V)
                && (PrecType != LTEDS_INFO_HLV_ELEC_PREC_STD_PM10V))  {
            if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_20MV) {
                err = LTEDS_PutConRes(ctx, 11, -20.48, 0.02, info->ElecSigOut.Range.MinValue);
                if (err == LTEDS_OK)
                    err = LTEDS_PutConRes(ctx, 11, -20.48, 0.02, info->ElecSigOut.Range.MaxValue);
            } else if (PrecType == LTEDS_INFO_HLV_ELEC_PREC_FULL) {
                err = LTEDS_PutSingle(ctx, info->ElecSigOut.Range.MinValue);
                if (err == LTEDS_OK)
                    err = LTEDS_PutSingle(ctx, info->ElecSigOut.Range.MaxValue);
            } else {
                err = LTEDS_ERROR_UNKNOWN_SEL_CASE;
            }
        }
    }



    if (err == LTEDS_OK)
        err = LTEDS_PutEnumVal(ctx, 1, info->ElecSigOut.AcCoupling ? 1 : 0);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRelRes(ctx, 12, 1, 0.001706, info->ElecSigOut.OutputImpedance);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRelRes(ctx, 6, 1e-6, 0.146, info->ElecSigOut.ResponseTime);

    if (err == LTEDS_OK) {
        err = LTEDS_PutSelectCase(ctx, 1, info->PowerSupply.IsRequired ? 1 : 0);
        if ((err == LTEDS_OK) && info->PowerSupply.IsRequired) {
            err = LTEDS_PutExcitationLevelsInfo(ctx, &info->PowerSupply.Levels);
            if (err == LTEDS_OK)
                err = LTEDS_PutEnumVal(ctx, 2, info->PowerSupply.Type);
            if (err == LTEDS_OK)
                err = LTEDS_PutConRelRes(ctx, 6, 1e-6, 0.129462705898, info->PowerSupply.CurrentDraw);
        }
    }

    if (err == LTEDS_OK)
        err = LTEDS_PutBaseCalInfo(ctx, &info->CalInfo);
    if (err == LTEDS_OK)
        err = LTEDS_PutMeasLocationID(ctx, info->MeasLocationID);

    return  err;
}


LTEDSAPI_DllExport(INT) LTEDS_GetTmpltInfoBridge(TLTEDS_DECODE_CONTEXT *ctx, TLTEDS_INFO_TMPLT_BRIDGE *info) {
    DWORD val;
    INT err = LTEDS_OK;
    err = LTEDS_GetPhysicalRangeInfo(ctx, info ? &info->Meas : NULL);
    if (err == LTEDS_OK) {
        DWORD PrecType = 0;
        err = LTEDS_GetSelectCase(ctx, 2, &PrecType);
        if (err == LTEDS_OK) {
            TLTEDS_INFO_ELECTRICAL_RANGE el_range;
            el_range.PrecType = PrecType & 3;
            if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_11BIT) {
                /** @note в описании NI отличается диапазон и шаг на e-3,
                 * что выглядит несколько более логичным (т.к. является поддиапазоном
                 * старшего), но оставлено как в стандарте */
                err = LTEDS_GetConRes(ctx, 11, -1, 0.001, &el_range.MinValue);
                if (err == LTEDS_OK)
                    err = LTEDS_GetConRes(ctx, 11, -1, 0.001, &el_range.MaxValue);
            } else if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_11BIT) {
                err = LTEDS_GetConRes(ctx, 19, -6.55e-3, 25e-9, &el_range.MinValue);
                if (err == LTEDS_OK)
                    LTEDS_GetConRes(ctx, 19, -6.55e-3, 25e-9, &el_range.MaxValue);
            } else if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_FULL) {
                err = LTEDS_GetSingle(ctx, &el_range.MinValue);
                if (err == LTEDS_OK)
                    LTEDS_GetSingle(ctx, &el_range.MaxValue);
            } else {
                err = LTEDS_ERROR_UNKNOWN_SEL_CASE;
            }

            if ((err == LTEDS_OK) && (info != NULL))
                info->ElecSigOut.Range = el_range;
        }
    }

    if ((err == LTEDS_OK) && info) {
        info->ElecSigOut.SigType = LTEDS_INFO_ELECSIGTYPE_BRIDGE_SENSOR;
        info->ElecSigOut.MapMeth = LTEDS_INFO_MAPMETH_LINEAR;
    }

    if (err == LTEDS_OK) {
        err = LTEDS_GetEnumVal(ctx, 2, &val);
        if ((err == LTEDS_OK) && (info != NULL))
            info->ElecSigOut.BridgeType = val & 3;
    }
    if (err == LTEDS_OK)
        err = LTEDS_GetConRes(ctx, 18, 1, 0.1, info ? &info->ElecSigOut.BridgeImpedance : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetConRelRes(ctx, 6, 1e-6, 0.146, info ? &info->ElecSigOut.ResponseTime : NULL);
    if (err == LTEDS_OK)
        err= LTEDS_GetExcitationLevelsInfo(ctx, info ? &info->ExcitationLevels : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetBaseCalInfo(ctx, info ? &info->CalInfo : NULL);
    if (err == LTEDS_OK)
        err = LTEDS_GetMeasLocationID(ctx, info ? &info->MeasLocationID : NULL);
    return err;
}

LTEDSAPI_DllExport(INT) LTEDS_PutTmpltInfoBridge(TLTEDS_ENCODE_CONTEXT *ctx,
                                                 const TLTEDS_INFO_TMPLT_BRIDGE *info) {
    INT err = LTEDS_OK;
    err = LTEDS_PutPhysicalRangeInfo(ctx, &info->Meas);
    if (err == LTEDS_OK)
        err = LTEDS_PutSelectCase(ctx, 2, info->ElecSigOut.Range.PrecType);
    if (err == LTEDS_OK) {
        BYTE PrecType = info->ElecSigOut.Range.PrecType;
        if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_11BIT) {
            err = LTEDS_PutConRes(ctx, 11, -1, 0.001, info->ElecSigOut.Range.MinValue);
            if (err == LTEDS_OK)
                err = LTEDS_PutConRes(ctx, 11, -1, 0.001, info->ElecSigOut.Range.MaxValue);
        } else if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_11BIT) {
            err = LTEDS_PutConRes(ctx, 19, -6.55e-3, 25e-9, info->ElecSigOut.Range.MinValue);
            if (err == LTEDS_OK)
                LTEDS_PutConRes(ctx, 19, -6.55e-3, 25e-9, info->ElecSigOut.Range.MaxValue);
        } else if (PrecType == LTEDS_INFO_BRIDGE_ELEC_PREC_FULL) {
            err = LTEDS_PutSingle(ctx, info->ElecSigOut.Range.MinValue);
            if (err == LTEDS_OK)
                LTEDS_PutSingle(ctx, info->ElecSigOut.Range.MaxValue);
        } else {
            err = LTEDS_ERROR_UNKNOWN_SEL_CASE;
        }
    }

    if (err == LTEDS_OK)
        err = LTEDS_PutEnumVal(ctx, 2, info->ElecSigOut.BridgeType);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRes(ctx, 18, 1, 0.1, info->ElecSigOut.BridgeImpedance);
    if (err == LTEDS_OK)
        err = LTEDS_PutConRelRes(ctx, 6, 1e-6, 0.146, info->ElecSigOut.ResponseTime);
    if (err == LTEDS_OK)
        err = LTEDS_PutExcitationLevelsInfo(ctx, &info->ExcitationLevels);
    if (err == LTEDS_OK)
        err = LTEDS_PutBaseCalInfo(ctx, &info->CalInfo);
    if (err == LTEDS_OK)
        err = LTEDS_PutMeasLocationID(ctx, info->MeasLocationID);
    return err;
}


LTEDSAPI_DllExport(INT) LTEDS_GetTmpltInfoCalTable(TLTEDS_DECODE_CONTEXT *ctx,
                                                   TLTEDS_INFO_TMPLT_CAL_TABLE *info) {
    DWORD val;
    INT err = LTEDS_OK;

    err = LTEDS_GetEnumVal(ctx, 1, &val);
    if ((err == LTEDS_OK) && (info != NULL))
        info->Domain = val & 1;
    if (err == LTEDS_OK)
        err = LTEDS_GetStructArraySize(ctx, 7, &val);
    if (err == LTEDS_OK) {
        BYTE pt_idx, pt_cnt;
        pt_cnt = val & 0x7F;
        if (info != NULL)
            info->DataSetCount = pt_cnt;
        for (pt_idx = 0; (pt_idx < pt_cnt) && (err == LTEDS_OK); pt_idx++) {
            TLTEDS_INFO_CALTABLE_DATASET dset;
            err = LTEDS_GetConRes(ctx, 16, 0, 0.00153, &dset.DomainValue);
            if (err == LTEDS_OK)
                err = LTEDS_GetConRes(ctx, 21, -100, 0.0001, &dset.RangeDeviation);
            if ((err == LTEDS_OK) && info)
                info->DataSets[pt_idx] = dset;
        }
    }
    return err;
}

LTEDSAPI_DllExport(INT) LTEDS_PutTmpltInfoCalTable(TLTEDS_ENCODE_CONTEXT *ctx,
                                                   const TLTEDS_INFO_TMPLT_CAL_TABLE *info) {
    INT err = LTEDS_OK;
    err = LTEDS_PutEnumVal(ctx, 1, info->Domain);
    if (err == LTEDS_OK)
        err = LTEDS_PutStructArraySize(ctx, 7, info->DataSetCount);
    if (err == LTEDS_OK) {
        BYTE pt_idx;
        for (pt_idx = 0; (pt_idx < info->DataSetCount) && (err == LTEDS_OK); pt_idx++) {
            err = LTEDS_PutConRes(ctx, 16, 0, 0.00153, info->DataSets[pt_idx].DomainValue);
            if (err == LTEDS_OK)
                err = LTEDS_PutConRes(ctx, 21, -100, 0.0001, info->DataSets[pt_idx].RangeDeviation);
        }
    }
    return err;
}

