Lean MES Open Source Manufacturing Execution System
Flexible Manufacturing Solutions through Open Standards and Free Software....

Atlas Copco Open Protocol Communication Driver for OPTO22 PAC


Compatible with Atlas Copco Power Focus 3000, 3100 and 4000 products. Interoperable with Stanley Alpha products.
Supports Heartbeat, Enable, Disable, PSET Select and Subscribe (TRQ/ANG) commands. JOB command is optionally expendable.
Stable active production confirmed on: SNAP-PAC-R2, S1 (Rev.8.4a); LCE, ADS, M64 (Rev.7.2h).

Deployment/Test Instructions:
1. Tool IP and PAC IP are configured ,preferably, on the same subnet. Both devices connected to the same physical network.
    (Removes unnecessary routing and reduce risk of failure).
2. Verify and update if necessary the tool's communication for Cell keep alive is greater then driver's keep alive timer preset.
2. Tool settings configured to use Ethernet/Serial in Pset select source.
3. Tool has at least 1 functional pset configured.
4. Download the ctEth_OpenAtlasCopco_TTxx.zip and extract files.
5. Copy and include files from extracted .\subroutines folder to strategy's subroutines folder
6. Import the extracted ctEth_OpenAtlasCopco_TTxx.cxf into strategy
      (Note! all tags are going to maintain their generic template names,
      refer to OPTO22 PAC Pro Code Replication Techniques tutorial below).
7. Update chTTxx_tcp tag in PAC Control Communication Handles to a specific tool's IP address, keep port 4545.
8. Compile strategy, load to PAC and click the Run Strategy button.
9. Run the driver flow(chart). Verify nTTxx_CommSts has value 1.
10. View the example of communication command sequences here.
11. View example of handling tool and tracking torque values in OI sample for air-bag install here
Access to instruction handler (includes communication sequence commands and error handling) code in repository:
https://aat.dyndns.biz/websvn/Open.FMF/Source Code/Instruction Handlers/4.TorqueOpenProtocol/
       uid: mes
       pwd: 123



The Driver code below is for quick reference use only, access the repository for released version.

//******************************************************************************
//Atlas Copco Open Protocol Communication Driver for OPTO22 PACs
//Driver Chart
//Copyright (C) 2010  Peter Tiagunov peter.tiagunov@leanmes.net

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

//--keepalive timer--------------------------------------------------
if(nTT01_CommSts)then
  if(GetStringLength(sTT01_Tx)==0 and GetNumCharsWaiting(chTT01_tcp)==0)then
    if (HasDownTimerExpired(tdTT01_KeepAlive)) then
        sTT01_Tx=stMID[88];  // <> Keep alive message "9999"
        SetDownTimerPreset(9.0,tdTT01_KeepAlive);
        StartTimer(tdTT01_KeepAlive);
    endif
  else
    SetDownTimerPreset(9.0,tdTT01_KeepAlive);
    StartTimer(tdTT01_KeepAlive);
  endif
endif

//--open protocol interface-------------------------------------------------------------------------------------
if(srACOnProtocol(chTT01_tcp,      //  >in ACTool communication handle
                  sTT01_MIDRev,    //  >in MID revision (000 ; 001 ; 002 .... 999)
                  stMID,           //  >in MID table
                  sTT01_Tx,        //  >in MID to send
                  sTT01_ConfigData,//  >in MID configuration(optional)
                  sTT01_Tx_Sent,   //  <out Tx data sent
                  sTT01_Rx,        //  <out data received
                  sTT01_ResultData,//  <out result data
                  nTT01_CommSts,   //  <out communication status 1-on, 0-off
                  sTT01_MIDerror,  //  <out MID reply error
                  nTT01_error      //  <out error code
                  )==0)then
endif

//--error log--------------------------------------------------------------------------------------------------------------
if(nTT01_error<>0)then
    DateToStringDDMMYYYY(sDate);
    TimeToString(sTime);
    NumberToString(nTT01_error,stTT01_ErorLog[nTT01_index]);
    stTT01_ErorLog[nTT01_index]=stTT01_ErorLog[nTT01_index]+";"+sDate+";"+sTime+";"+sTT01_ConfigData+";"+sTT01_MIDerror+";"+sTT01_Tx_Sent;
    if(nTT01_index==15)then
        nTT01_index=0;
    else
        nTT01_index=nTT01_index+1;
    endif
endif

//--control scan rate-------------------------------------------
if(not(nTT01_CommSts))then
    nTT01_ScanRate=10000; //if connection lost reconnect every 10 sec.
elseif(nTT01_CommSts and nTT01_ScanRate>=1000)then
    nTT01_ScanRate=100; //set normal scan rate once
endif

DelayMsec(nTT01_ScanRate);




//******************************************************************************
//Atlas Copco Open Protocol Communication Driver for OPTO22 PACs
//Subroutine srACOnProtocol
//Copyright (C) 2010  Peter Tiagunov peter.tiagunov@leanmes.net

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

nMaxTry=1;
//initialize socket connection-----------------------------------------------------------------------------------------
if(not(IsCommunicationOpen(in_ch)))then
    nCommSts=OpenOutgoingCommunication(in_ch);
    if(nCommSts==0 or nCommSts==-47)then //socket created or Open failed. Handle has already been opened.
        nCommSts=SendCommunicationHandleCommand(in_ch, "set.to:1.0");
        out_error=0;//clear error
        ClearCommunicationReceiveBuffer(in_ch);
        SetEndOfMessageTerminator(in_ch,0);
        //in_MIDRev    ="001";
        sSpare  ="000000000";
        sHeader =in_stMID[0]+in_MIDRev+sSpare;
        NumberToString(GetStringLength(sHeader)+4,sLength);
        if(GetStringLength(sLength)<4)then //left pad sLength with "0"'s
            while(GetStringLength(sLength)<4)
                sLength="0"+sLength;
            wend
        endif
        sHeader=sLength+sHeader;
        if(GetStringLength(sHeader)==20)then //header length 20 bytes
            in_Tx=sHeader+Chr(0);
            nTry=0;//reset Try counter
            nCommSts=-1;//set initial nCommSts
            while(nTry<nMaxTry and nCommSts<>0) //try up to max tries or success
                //start communication
                nCommSts=TransmitString(in_Tx,in_ch);//send message
                if(nCommSts==0)then //data transmisson success
                    out_Rx="";//clear output Rx buffer
                    nTimeout=2000;
                    //wait for start communication acknowledge reply
                    //==============================================
                    while(out_Rx=="" and nTimeout>0)
                        DelayMsec(10);
                        nCommSts=GetNumCharsWaiting(in_ch);
                        if (nCommSts>0)then //receive data available
                            nTry=0;//reset Try counter
                            nCommSts=-1;//set initial nCommSts
                            while(nTry<nMaxTry and nCommSts<>0)
                                nCommSts=ReceiveString(out_Rx, in_ch);
                                if(nCommSts==0)then //receive success
                                    out_error=0;//clear error
                                    //in_keepalive=0;//reset keepalive request
                                    if(not(out_Rx==""))then
                                        if(GetStringLength(out_Rx)>=20)then
                                            GetSubstring(out_Rx,0,4,sLength);
                                            GetSubstring(out_Rx,4,4,sMID);
                                            GetSubstring(out_Rx,20,(GetStringLength(out_Rx)-20),out_Data);
                                            //verify message length = actual message length
                                            if(StringToInt32(sLength)==GetStringLength(out_Rx))then
                                                //start communication acknowledge reply or client already connected
                                                if(sMID==in_stMID[1] or (sMID==in_stMID[3]and out_Data=="000196"))then
                                                    out_MIDerror="";//clear MID error
                                                    out_sts=1;//communication established
                                                    out_error=0;//clear error
                                                elseif(sMID==in_stMID[3])then  //command error
                                                    GetSubstring(out_Data,0,6,out_MIDerror);
                                                else
                                                    out_error=78081;//unexpected reply
                                                endif
                                            else
                                                out_error=78071;//message length mismatch
                                            endif
                                        else
                                            out_error=78061;//message length invalid
                                        endif
                                    endif
                                elseif(nTry>=(nMaxTry-1))then
                                    out_error=78051;//socket receive error
                                endif
                                nTry=nTry+1;
                            wend
                        elseif (nCommSts==0)then //no data
                            //out_error=0;
                        else
                            out_error=78041;//socket receive buffer error
                        endif
                        nTimeout=nTimeout-10;
                        //exit while on timeout or error
                        if (nTimeout<=0)then
                            out_error=78031;//communication reply timeout
                        endif
                    wend //==============================================
                elseif(nCommSts<>0 and nTry>=(nMaxTry-1))then
                    out_error=78021;//socket send error
                endif
                nTry=nTry+1;
            wend
        else
            out_error=78011;  //message header error
        endif
    elseif(out_error==0)then
        out_error=78001;//create socket error
    endif
    if(out_error>0)then
        out_sts=0;//communication lost
    endif
    out_Tx=in_Tx;
    in_Tx="";
endif

if(out_sts==1)then
    //send command or subscribe request------------------------------------------------------------------------------------
    if(GetStringLength(in_Tx)==4 and GetNumCharsWaiting(in_ch)==0)then
        sSpare  ="000000000";
        if(GetStringLength(in_Data)>0)then //MID + configuration data
            sTxBuff=in_Tx+in_MIDRev+sSpare+in_Data;
        else //MID only
            sTxBuff=in_Tx+in_MIDRev+sSpare;
        endif
        NumberToString(GetStringLength(sTxBuff)+4,sLength);
        if(GetStringLength(sLength)<4)then //left pad sLength with "0"'s
            while(GetStringLength(sLength)<4)
                sLength="0"+sLength;
            wend
        endif
        sTxBuff=sLength+sTxBuff;
        //verify message length
        if(GetStringLength(sTxBuff)==StringToInt32(sLength))then
            sTxBuff=sTxBuff+Chr(0);
            nTry=0;//reset Try counter
            nCommSts=-1;//set initial nCommSts
            while(nTry<nMaxTry and nCommSts<>0) //try up to nMaxTry times or success
                nCommSts=TransmitString(sTxBuff,in_ch);//send message
                if(nCommSts==0)then //data transmisson success
                    out_Rx="";//clear output Rx buffer
                    nTimeout=2000;
                    //wait for reply
                    while (out_Rx=="" and nTimeout>0)
                        DelayMsec(10);
                        nCommSts=GetNumCharsWaiting(in_ch);
                        if (nCommSts>0)then //receive data available
                            nTry=0;//reset Try counter
                            nCommSts=-1;//set initial nCommSts
                            while(nTry<nMaxTry and nCommSts<>0) //try up to nMaxTry times or success
                                nCommSts=ReceiveString(out_Rx, in_ch);
                                if (nCommSts==0)then //receive success
                                    out_error=0;
                                    if(not(out_Rx==""))then
                                        if(GetStringLength(out_Rx)>=20)then
                                            GetSubstring(out_Rx,0,4,sLength);
                                            GetSubstring(out_Rx,4,4,sMID);
                                            GetSubstring(out_Rx,20,(GetStringLength(out_Rx)-20),out_Data);
                                            //verify message length = actual message length
                                            if(StringToInt32(sLength)==GetStringLength(out_Rx))then
                                                out_sts=1;//communication established confirm
                                                if(sMID==in_stMID[4])then //command accepted
                                                    out_MIDerror="";//clear MID error
                                                elseif(sMID==in_stMID[88])then //keepalive echo reply
                                                    out_MIDerror="";//clear MID error
                                                elseif(sMID==in_stMID[3])then  //command error
                                                    GetSubstring(out_Data,0,6,out_MIDerror);
                                                endif
                                                in_Data="";//clear configuration data
                                            else
                                                out_error=78074;//message length mismatch
                                            endif
                                        else
                                            out_error=78064;//message length invalid
                                        endif
                                    endif
                                elseif(nCommSts<>0 and nTry>=(nMaxTry-1))then
                                    out_error=78054;//socket receive error
                                endif
                                nTry=nTry+1;
                            wend
                        elseif (nCommSts==0)then //no data
                            //out_error=0;
                        else
                            out_error=78044;//socket receive buffer error
                        endif
                        nTimeout=nTimeout-10;
                        //exit while on timeout or error
                        if (nTimeout<=0)then
                            out_error=78034;//communication reply timeout
                        endif
                    wend
                elseif(nCommSts<>0 and nTry>=(nMaxTry-1))then
                    out_error=78024;//socket send error
                endif
                nTry=nTry+1;           
            wend
        else
            out_error=78074;//message length mismatch
        endif
        out_Tx=in_Tx;
        in_Tx="";//clear input Tx buffer
    endif
    //listen for subscription events----------------------------------------------------------------------------------------
    if(GetNumCharsWaiting(in_ch)>0)then
            nTry=0;//reset Try counter
            nCommSts=-1;//set initial nCommSts
            while(nTry<nMaxTry and nCommSts<>0)                       
                nCommSts=ReceiveString(out_Rx, in_ch);
                if (nCommSts==0)then //receive success
                    out_error=0;
                    if(not(out_Rx==""))then
                        if(GetStringLength(out_Rx)>=20)then
                            GetSubstring(out_Rx,0,4,sLength);
                            GetSubstring(out_Rx,4,4,sMID);
                            GetSubstring(out_Rx,20,(GetStringLength(out_Rx)-20),out_Data);
                            //verify message length = actual message length
                            if(StringToInt32(sLength)==GetStringLength(out_Rx))then //create event acknowledge
                                if    (sMID==in_stMID[10])then //Parameter set "selected" event
                                    sTxBuff="0020"+in_stMID[11]+"001000000000"+Chr(0);//Parameter set "selected" event acknowledge
                                elseif(sMID==in_stMID[21])then //Job "info" event
                                    sTxBuff="0020"+in_stMID[22]+"001000000000"+Chr(0);//Job "info" event acknowledge
                                elseif(sMID==in_stMID[33])then //Vehicle Id Number upload event
                                    sTxBuff="0020"+in_stMID[34]+"001000000000"+Chr(0);//Vehicle Id Number upload event acknowledge
                                elseif(sMID==in_stMID[37])then //Last tightening result data upload event
                                    sTxBuff="0020"+in_stMID[38]+"001000000000"+Chr(0);//Last tightening result data event acknowledge
                                elseif(sMID==in_stMID[43])then //Alarm Upload event
                                    sTxBuff="0020"+in_stMID[44]+"001000000000"+Chr(0);//Alarm Upload event acknowledge
                                elseif(sMID==in_stMID[46])then //Alarm Acknowledged on torque controller event
                                    sTxBuff="0020"+in_stMID[47]+"001000000000"+Chr(0);//Alarm Acknowledged Ack
                                elseif(sMID==in_stMID[48])then //Alarm Status event
                                    sTxBuff="0020"+in_stMID[49]+"001000000000"+Chr(0);//Alarm Status event acknowledge
                                elseif(sMID==in_stMID[54])then //Multi spindle status upload event
                                    sTxBuff="0020"+in_stMID[55]+"001000000000"+Chr(0);//Multi spindle status upload event acknowledge
                                elseif(sMID==in_stMID[58])then //Multi spindle result upload event
                                    sTxBuff="0020"+in_stMID[59]+"001000000000"+Chr(0);//Multi spindle result upload event acknowledge
                                elseif(sMID==in_stMID[77])then //Status "external monitored inputs" upload event
                                    sTxBuff="0020"+in_stMID[78]+"001000000000"+Chr(0);//Status "external monitored inputs" upload acknowledge
                                //***************************************************
                                elseif(sMID==in_stMID[88])then //keepalive echo reply
                                    out_MIDerror="";//clear MID error
                                    sTxBuff="";//clear Tx data
                                    //in_keepalive=0;//reset keepalive request
                                elseif(sMID==in_stMID[1] or (sMID==in_stMID[3]and out_Data=="000196"))then
                                    out_MIDerror="";//clear MID error
                                    out_sts=1;//communication established
                                    out_error=0;//clear error
                                //***************************************************
                                elseif(sMID==in_stMID[3])then  //command error
                                    GetSubstring(out_Data,0,6,out_MIDerror);
                                else//unknown reply
                                    //ClearCommunicationReceiveBuffer(in_ch);
                                endif
                                if(GetStringLength(sTxBuff)>0)then
                                    nTry=0;//reset Try counter
                                    nCommSts=-1;//set initial nCommSts
                                    while(nTry<nMaxTry and nCommSts<>0) //try up to nMaxTry times or success
                                        nCommSts=TransmitString(sTxBuff,in_ch);
                                          if(nCommSts<>0)then
                                              nTry=nTry+1;
                                          endif
                                    wend
                                    if(nCommSts<>0 and nTry>=(nMaxTry-1))then  
                                        out_error=78022;//socket send error
                                    endif
                                endif
                            else
                                out_error=78072;//message length mismatch
                            endif

                        else
                            out_error=78062;//message length invalid
                        endif
                    endif
                elseif(nCommSts<>0 and nTry>=(nMaxTry-1))then
                    out_error=78052;//socket receive error
                endif
                nTry=nTry+1;           
            wend
        out_Tx=sTxBuff;
        sTxBuff="";//clear internal Tx buffer
    endif
endif

//close opened socket if error-----------------------------------------------------------------------------------------
if(out_error>0)then
    if(IsCommunicationOpen(in_ch))then
        ClearCommunicationReceiveBuffer(in_ch);
        nCommSts=CloseCommunication(in_ch);
        if(nCommSts<>0)then
            out_error=7809;//close socket error
        endif
        out_sts=0;//communication lost
        //in_keepalive=0;
    endif
endif




//******************************************************************************
//Atlas Copco Open Protocol Communication Driver for OPTO22 PACs
//Subroutine srACOnProtMID0013Parser
//Copyright (C) 2010  Peter Tiagunov peter.tiagunov@leanmes.net

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

//Example:
//          10        20        30        40        50        60        70        80        90        100       110       120       130       140       150       160       170       180       190       200       210
//0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//0100102PSET1                    0310403050012000600150007001400080036009007201000480
//
//               Id Value DataLen Start End      Total
//Name           (2bytes)+(bytes) Pos.  Pos.    Length                 Notes
//-------------- -------- ------- ----- ---- --------- ---------------------
//Pset Id              01       3     0    4   5 bytes
//Pset Name            02      25     5   31  27 bytes
//Rotation Direction   03       1    32   34   3 bytes
//Batch Size           04       2    35   38   4 bytes
//Torque Min           05       6    39   46   8 bytes
//Torque Max           06       6    47   54   8 bytes
//Torque Final target  07       6    55   62   8 bytes
//Angle Min            08       5    63   69   7 bytes
//Angle Max            09       5    70   76   7 bytes
//Final Angle Target   10       5    77   83   7 bytes
//
GetSubstring(in_ResultData, 7, 25,out_PsetName);
GetSubstring(in_ResultData, 37, 2,sString);
out_BatchSize=(StringToInt32(sString));

//Example:
//          10        20        30        40        50        60        70        80        90        100       110       120       130       140       150       160       170       180       190       200       210
//0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//0100102PSET1                    0310403050012000600150007001400080036009007201000480
//
//               Id Value DataLen Start End      Total
//Name           (2bytes)+(bytes) Pos.  Pos.    Length                 Notes
//-------------- -------- ------- ----- ---- --------- ---------------------
//Pset Id              01       3     0    4   5 bytes
//Pset Name            02      25     5   31  27 bytes
//Rotation Direction   03       1    32   34   3 bytes
//Batch Size           04       2    35   38   4 bytes
//Torque Min           05       6    39   46   8 bytes
//Torque Max           06       6    47   54   8 bytes
//Torque Final target  07       6    55   62   8 bytes
//Angle Min            08       5    63   69   7 bytes
//Angle Max            09       5    70   76   7 bytes
//Final Angle Target   10       5    77   83   7 bytes
//
GetSubstring(in_ResultData, 7, 25,out_PsetName);
GetSubstring(in_ResultData, 37, 2,sString);
out_BatchSize=(StringToInt32(sString));



//******************************************************************************
//Atlas Copco Open Protocol Communication Driver for OPTO22 PACs
//Subroutine srACOnProtMID0061Parser
//Copyright (C) 2010  Peter Tiagunov peter.tiagunov@leanmes.net

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

//Example, Batch of 4:
//          10        20        30        40        50        60        70        80        90        100       110       120       130       140       150       160       170       180       190       200       210
//0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//010000020003                         04                         050006001070004080001091101111120009001300110014001000150010061600000170999918000001900107202006-08-17:11:50:29212006-08-17:10:17:27220230000000040
//010000020003                         04                         05000600107000408000209110111112000900130011001400100015001017171600000170999918000001900102202006-08-17:11:51:31212006-08-17:10:17:27220230000000041
//010000020003                         04                         050006001070004080003091101111120009001300110014001000150010171600000170999918000001900018202006-08-17:11:52:44212006-08-17:10:17:27220230000000042
//010000020003                         04                         050006001070004080004091101111120009001300110014001000150010141600000170999918000001900018202006-08-17:11:53:23212006-08-17:10:17:27221230000000043
//
//               Id Value DataLen Start End      Total
//Name           (2bytes)+(bytes) Pos.  Pos.    Length                 Notes
//-------------- -------- ------- ----- ---- --------- ---------------------
//Cell Id              01       4     0    5   6 bytes
//Channel Id           02       2     6    9   4 bytes
//Tool Name            03      25    10   36  27 bytes
//VIN Number           04      25    37   63  27 bytes
//Job Number           05       2    64   67   4 bytes
//Pset Number          06       3    68   72   5 bytes      
//Batch Size           07       4    73   78   6 bytes
//Batch Counter        08       4    79   84   6 bytes
//Tightening Status    09       1    85   87   3 bytes  0-NOK/1-OK
//Torque status        10       1    88   90   3 bytes
//Angle status         11       1    91   93   3 bytes
//Torque Min limit     12       6    94  101   8 bytes  xxxxxx (0000.00)
//Torque Max limit     13       6   102  109   8 bytes  xxxxxx (0000.00)
//Torque final target  14       6   110  117   8 bytes  xxxxxx (0000.00)
//Torque               15       6   118  125   8 bytes  xxxxxx (0000.00)
//Angle Min            16       5   126  132   7 bytes  degrees 00000-99999
//Angle Max            17       5   133  139   7 bytes  degrees 00000-99999
//Final Angle Target   18       5   140  146   7 bytes  degrees 00000-99999
//Angle                19       5   147  153   7 bytes  degrees 00000-99999
//Time stamp           20      19   154  174  21 bytes  YYYY-MM-DD:HH:MM:SS
//Date/time of last
//change in Pset
//settings             21      19   175  195  21 bytes  YYYY-MM-DD:HH:MM:SS
//Batch status         22      1    196  198   3 bytes  0-NOK/1-OK/2-NotUsed
//Tightening Id        23     10    199  210  12 bytes  0-4294967295       
//
GetSubstring(in_ResultData, 87, 1,out_tighteningstatus);
GetSubstring(in_ResultData,198, 1,out_BatchStatus);

//string     int32  float   string
//--------   -----  -----   -------
//"001017" > 1017 > 10.17 > "10.17"
GetSubstring(in_ResultData,120, 6,sString);
GetSubstring(sString,0, 4,sTorqueWhole); //get torque whole part
GetSubstring(sString,4, 2,sTorqueDecimals);//get torque decimal part
nTorqueWhole=(StringToInt32(sTorqueWhole));
NumberToString(nTorqueWhole, sTorqueWhole);
out_Torque=sTorqueWhole+"."+sTorqueDecimals;

GetSubstring(in_ResultData,149, 5,out_Angle);