Skip to content

Commit 27e8eac

Browse files
authoredAug 6, 2024
Merge pull request #2 from loupeteam/develop
Release first version
2 parents 5a6b473 + 48d9439 commit 27e8eac

34 files changed

+8028
-2
lines changed
 

‎.gitignore

+536
Large diffs are not rendered by default.

‎README.md

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,29 @@
1-
# A2B2Cat
2-
Library for monitoring and controlling ABB robots via TwinCat (ABB + TwinCat = A*(2*B) + (2*Cat) => A2B2Cat !)
1+
# TcAbbLinkin
2+
3+
## Info
4+
This tool is provided by Loupe.
5+
https://loupe.team
6+
info@loupe.team
7+
1-800-240-7042
8+
9+
## Description
10+
A library for monitoring and controlling ABB robots via TwinCat.
11+
12+
ABB RobotWare exposes an RESTful HTTP server called Robot Web Services ("RWS"). Clients
13+
are able to fetch status, set values, and perform control functions via this interface. This library
14+
allows a user to leverage a small-but-useful subset of the RWS API for common tasks.
15+
16+
### FAQs
17+
18+
#### Q: Why is the library named TcAbbLinkin?
19+
20+
The name of this library is intended to be a pun, sounding like the name of Abraham "Abe" Lincoln, the 16th President of the United States.
21+
22+
<img src="./img/AbeLincolnWithTwinCats.jpg" alt="Abe Lincoln with twin cats, generated with Microsoft Copilot Image Creator" width="400" height="400">
23+
24+
## Documentation
25+
26+
The library documentation can be found [here](https://loupeteam.github.io/LoupeDocs/libraries_beckhoff/tcabblinkin.html)
27+
28+
## Licensing
29+
This project is licensed under the [MIT License](LICENSE).

‎TwinCat/TcAbbLinkin.sln

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# TcXaeShell Solution File, Format Version 11.00
4+
VisualStudioVersion = 15.0.33403.129
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{B1E792BE-AA5F-4E3C-8C82-674BF9C0715B}") = "TcAbbLinkin", "TcAbbLinkin\TcAbbLinkin.tsproj", "{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|TwinCAT CE7 (ARMV7) = Debug|TwinCAT CE7 (ARMV7)
11+
Debug|TwinCAT OS (ARMT2) = Debug|TwinCAT OS (ARMT2)
12+
Debug|TwinCAT RT (x64) = Debug|TwinCAT RT (x64)
13+
Debug|TwinCAT RT (x86) = Debug|TwinCAT RT (x86)
14+
Release|TwinCAT CE7 (ARMV7) = Release|TwinCAT CE7 (ARMV7)
15+
Release|TwinCAT OS (ARMT2) = Release|TwinCAT OS (ARMT2)
16+
Release|TwinCAT RT (x64) = Release|TwinCAT RT (x64)
17+
Release|TwinCAT RT (x86) = Release|TwinCAT RT (x86)
18+
EndGlobalSection
19+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
21+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
22+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
23+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
24+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
25+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
26+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
27+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
28+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
29+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
30+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
31+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
32+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
33+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
34+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
35+
{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
36+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
37+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
38+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
39+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
40+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
41+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
42+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
43+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
44+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
45+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
46+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
47+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
48+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
49+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
50+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
51+
{D1D47807-DDC9-4C87-BA84-A94C789102DA}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
52+
EndGlobalSection
53+
GlobalSection(SolutionProperties) = preSolution
54+
HideSolutionNode = FALSE
55+
EndGlobalSection
56+
GlobalSection(ExtensibilityGlobals) = postSolution
57+
SolutionGuid = {1906EA77-343F-4DCF-A35A-9A81C62F1579}
58+
EndGlobalSection
59+
EndGlobal
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0"?>
2+
<TcSmProject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.beckhoff.com/schemas/2012/07/TcSmProject" TcSmVersion="1.0" TcVersion="3.1.4024.53">
3+
<Project ProjectGUID="{FE0364B9-19AA-4F25-85B0-28EE12CF31C5}" Target64Bit="true" ShowHideConfigurations="#x6">
4+
<System>
5+
<Settings MaxCpus="4" NonWinCpus="1">
6+
<Cpu CpuId="3"/>
7+
</Settings>
8+
<Tasks>
9+
<Task Id="3" Priority="20" CycleTime="100000" AmsPort="350" AdtTasks="true">
10+
<Name>PlcTask</Name>
11+
</Task>
12+
</Tasks>
13+
</System>
14+
<Plc>
15+
<Project GUID="{D1D47807-DDC9-4C87-BA84-A94C789102DA}" Name="TcAbbLinkin" PrjFilePath="TcAbbLinkin\TcAbbLinkin.plcproj" TmcFilePath="TcAbbLinkin\TcAbbLinkin.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" SymbolicMapping="true">
16+
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcPath="TcAbbLinkinPLC\TcAbbLinkinPLC.tmc" TmcHash="{0A9DD89F-25AA-8229-C1D6-0EBCEA5A013C}">
17+
<Name>TcAbbLinkin Instance</Name>
18+
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
19+
<Contexts>
20+
<Context>
21+
<Id>0</Id>
22+
<Name>PlcTask</Name>
23+
<ManualConfig>
24+
<OTCID>#x02010030</OTCID>
25+
</ManualConfig>
26+
<Priority>20</Priority>
27+
<CycleTime>10000000</CycleTime>
28+
</Context>
29+
</Contexts>
30+
<TaskPouOids>
31+
<TaskPouOid Prio="20" OTCID="#x08502001"/>
32+
</TaskPouOids>
33+
</Instance>
34+
</Project>
35+
</Plc>
36+
</Project>
37+
</TcSmProject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_AUTH_HEADER_VALUE" Id="{99690849-bea9-4839-8bf4-6dc76e95b60f}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
{attribute 'qualified_only'}
6+
{attribute 'strict'}
7+
TYPE ABBLINKIN_AUTH_HEADER_VALUE :
8+
(
9+
NONE,
10+
BASIC,
11+
DIGEST
12+
);
13+
END_TYPE
14+
]]></Declaration>
15+
</DUT>
16+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_COMMAND_TYPE" Id="{d7d89884-2a0b-4df0-8653-de60d8f0522a}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
{attribute 'qualified_only'}
6+
{attribute 'strict'}
7+
TYPE ABBLINKIN_COMMAND_TYPE :
8+
(
9+
GET_IO,
10+
GET_CTRL_STATE,
11+
GET_OP_MODE,
12+
GET_RAPID_STATE,
13+
GET_SYMBOL,
14+
POWER_OFF,
15+
POWER_ON,
16+
RAPID_RESET,
17+
RAPID_START,
18+
RAPID_STOP,
19+
SET_IO,
20+
SET_SYMBOL
21+
);
22+
END_TYPE
23+
]]></Declaration>
24+
</DUT>
25+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_DATA_TYPE_Typ" Id="{ab428c6a-3178-4506-83fd-90df6da75be6}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
{attribute 'qualified_only'}
6+
{attribute 'strict'}
7+
TYPE ABBLINKIN_DATA_TYPE_Typ :
8+
(
9+
_NONE,
10+
_STRING,
11+
_BOOL,
12+
_DINT,
13+
_LREAL
14+
);
15+
END_TYPE
16+
]]></Declaration>
17+
</DUT>
18+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_RWS_API_VERSION" Id="{34efa19d-f9cb-43b8-bfe7-6b289ebee141}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
{attribute 'qualified_only'}
6+
{attribute 'strict'}
7+
TYPE ABBLINKIN_RWS_API_VERSION :
8+
(
9+
V1 := 0,
10+
V2 := 2
11+
);
12+
END_TYPE
13+
]]></Declaration>
14+
</DUT>
15+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_STATE" Id="{74fac755-88b4-4b19-95ed-c39f2425b0c7}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
{attribute 'qualified_only'}
6+
{attribute 'strict'}
7+
TYPE ABBLINKIN_STATE :
8+
(
9+
IDLE,
10+
SEND_REQUEST,
11+
WAIT_FOR_RESONSE,
12+
PROCESS_RESPONSE,
13+
AUTH_START,
14+
AUTH_SEND_REQUEST,
15+
AUTH_WAIT_FOR_RESONSE,
16+
AUTH_PROCESS_RESPONSE,
17+
AUTH_DIGEST_RESPONSE_CALCULATE,
18+
AUTH_DIGEST_RESPONSE_SEND,
19+
ERROR
20+
);
21+
END_TYPE
22+
]]></Declaration>
23+
</DUT>
24+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="ABBLINKIN_STRING_EX_LEN" Id="{ee5ab662-46b9-48e0-aa78-fcaad380107f}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE ABBLINKIN_STRING_EX_LEN : STRING(2000); END_TYPE
6+
]]></Declaration>
7+
</DUT>
8+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinAuthDigest_Typ" Id="{9ed59e39-fc70-44a3-b78f-e9eab3846bf1}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinAuthDigest_Typ :
6+
STRUCT
7+
realm : STRING;
8+
qop : STRING;
9+
nonce : STRING;
10+
opaque : STRING;
11+
nc : STRING;
12+
cnonce : STRING;
13+
response : STRING;
14+
authContent : ABBLINKIN_STRING_EX_LEN;
15+
END_STRUCT
16+
END_TYPE
17+
]]></Declaration>
18+
</DUT>
19+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinAuth_Typ" Id="{3b3e7797-3422-4ef6-95c4-998015db4fcc}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinAuth_Typ :
6+
STRUCT
7+
numAttempts : UINT;
8+
wwwAuthContent : ABBLINKIN_STRING_EX_LEN;
9+
digest : AbbLinkinAuthDigest_Typ;
10+
httpSessionCookie : STRING;
11+
ABBCXCookie : STRING;
12+
END_STRUCT
13+
END_TYPE
14+
]]></Declaration>
15+
</DUT>
16+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinConfiguration_Typ" Id="{eb4cc820-41d0-4679-875f-49cfa6130169}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinConfiguration_Typ :
6+
STRUCT
7+
rwsIpAddress : STRING := '127.0.0.1';
8+
rwsTcpPort : USINT := 80;
9+
rwsVersion : ABBLINKIN_RWS_API_VERSION;
10+
rwsUsername : STRING := 'Default User';
11+
rwsPassword : STRING := 'robotics';
12+
tlsAllowRwsCertSelfSigned : BOOL := FALSE;
13+
tlsCAFile : STRING(255) := '';
14+
END_STRUCT
15+
END_TYPE
16+
]]></Declaration>
17+
</DUT>
18+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinRequestQueue_Typ" Id="{0da73142-5815-463c-9973-c8dbb7228de0}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinRequestQueue_Typ :
6+
STRUCT
7+
request : AbbLinkinRequest_Typ;
8+
empty : BOOL := TRUE;
9+
END_STRUCT
10+
END_TYPE
11+
]]></Declaration>
12+
</DUT>
13+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinRequestResults_Typ" Id="{c39ae275-6a6c-40ae-b6c4-efffb32a9ec5}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinRequestResults_Typ :
6+
STRUCT
7+
pDataBool : POINTER TO BOOL;
8+
pDataDint : POINTER TO DINT;
9+
pDataLreal : POINTER TO LREAL;
10+
pDataString : POINTER TO STRING;
11+
dataType : ABBLINKIN_DATA_TYPE_Typ;
12+
dataLen : INT;
13+
END_STRUCT
14+
END_TYPE
15+
]]></Declaration>
16+
</DUT>
17+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinRequestStatus_Typ" Id="{6ed46d5e-f2a5-4e32-a29c-f034b05f637f}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinRequestStatus_Typ :
6+
STRUCT
7+
busy : BOOL;
8+
done : BOOL;
9+
error : BOOL;
10+
errorID : DINT;
11+
errorMsg : STRING;
12+
END_STRUCT
13+
END_TYPE
14+
]]></Declaration>
15+
</DUT>
16+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<DUT Name="AbbLinkinRequest_Typ" Id="{9d01c7cf-9f93-4ceb-b209-32052c2214ca}">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
TYPE AbbLinkinRequest_Typ :
6+
STRUCT
7+
command : ABBLINKIN_COMMAND_TYPE;
8+
uri : STRING;
9+
httpMethod : ETcIotHttpRequestType;
10+
httpBody : ABBLINKIN_STRING_EX_LEN := '';
11+
pStatus : POINTER TO AbbLinkinRequestStatus_Typ;
12+
results : AbbLinkinRequestResults_Typ;
13+
END_STRUCT
14+
END_TYPE
15+
]]></Declaration>
16+
</DUT>
17+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<POU Name="Example" Id="{6ae7d968-fc96-4ba1-b6bb-dff0068c2fd8}" SpecialFunc="None">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
PROGRAM Example
6+
VAR
7+
myRobotLink : TcAbbLinkin;
8+
initConfiguration : BOOL := TRUE;
9+
initConnection : BOOL := TRUE;
10+
userCommand_GetCtrlState : BOOL := TRUE;
11+
getCtrlStateStatus : AbbLinkinRequestStatus_Typ;
12+
currentState : STRING;
13+
output : STRING;
14+
END_VAR
15+
]]></Declaration>
16+
<Implementation>
17+
<ST><![CDATA[// Initialize configuration
18+
IF initConfiguration THEN
19+
myRobotLink.configuration.rwsIpAddress := '127.0.0.1';
20+
myRobotLink.configuration.rwsTcpPort := 80;
21+
myRobotLink.configuration.rwsVersion := ABBLINKIN_RWS_API_VERSION.V2;
22+
myRobotLink.configuration.rwsUsername := 'Default User';
23+
myRobotLink.configuration.rwsPassword := 'robotics';
24+
myRobotLink.configuration.tlsAllowRwsCertSelfSigned := TRUE;
25+
26+
initConfiguration := FALSE;
27+
END_IF
28+
29+
myRobotLink.Cyclic();
30+
31+
/////////////////////////
32+
// Connect
33+
IF initConnection THEN
34+
myRobotLink.Connect();
35+
initConnection := FALSE;
36+
END_IF
37+
38+
/////////////////////////
39+
// Get State
40+
41+
// Send command
42+
IF myRobotLink.readyForCmd AND userCommand_GetCtrlState THEN
43+
myRobotLink.GetCtrlState(pStatus := ADR(getCtrlStateStatus), pResultState := ADR(currentState));
44+
userCommand_GetCtrlState := FALSE;
45+
END_IF
46+
47+
// Process Results
48+
IF getCtrlStateStatus.done THEN
49+
output := CONCAT('Current state is ', currentState);
50+
ELSIF getCtrlStateStatus.error THEN
51+
output := 'An Error occured.';
52+
END_IF
53+
]]></ST>
54+
</Implementation>
55+
<LineIds Name="Example">
56+
<LineId Id="137" Count="35" />
57+
<LineId Id="22" Count="0" />
58+
</LineIds>
59+
</POU>
60+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
3+
<POU Name="MAIN" Id="{af726fc5-8ad0-4774-86c1-258758d62ada}" SpecialFunc="None">
4+
<Declaration><![CDATA[// Copyright (c) 2024 Loupe (https://loupe.team), provided under the MIT License.
5+
PROGRAM MAIN
6+
VAR
7+
myRobotLink : TcAbbLinkin;
8+
userSetConfigurationNow : BOOL := TRUE;
9+
userConnectStartNow : BOOL := TRUE;
10+
userConnectStopNow : BOOL;
11+
12+
userGetCtrlStateNow : BOOL;
13+
userGetCtrlStateStatus : AbbLinkinRequestStatus_Typ;
14+
userGetCtrlStateResult : STRING;
15+
16+
userGetOpModeNow : BOOL;
17+
userGetOpModeStatus : AbbLinkinRequestStatus_Typ;
18+
userGetOpModeResult : STRING;
19+
20+
userGetRapidStateNow : BOOL;
21+
userGetRapidStateStatus : AbbLinkinRequestStatus_Typ;
22+
userGetRapidStateResult : STRING;
23+
24+
userGetIoBoolNow : BOOL;
25+
userGetIoBoolStatus : AbbLinkinRequestStatus_Typ;
26+
userGetIoBoolResult : BOOL;
27+
28+
userGetIoLrealNow : BOOL;
29+
userGetIoLrealStatus : AbbLinkinRequestStatus_Typ;
30+
userGetIoLrealResult : LREAL;
31+
32+
userGetIoDintNow : BOOL;
33+
userGetIoDintStatus : AbbLinkinRequestStatus_Typ;
34+
userGetIoDintResult : DINT;
35+
36+
37+
userSetIoBoolNow : BOOL;
38+
userSetIoBoolValue : BOOL := 1;
39+
userSetIoBoolStatus : AbbLinkinRequestStatus_Typ;
40+
userSetIoDintNow : BOOL;
41+
userSetIoDintValue : DINT := 57;
42+
userSetIoDintStatus : AbbLinkinRequestStatus_Typ;
43+
userSetIoLrealNow : BOOL;
44+
userSetIoLrealValue : LREAL := 41.123456;
45+
userSetIoLrealStatus : AbbLinkinRequestStatus_Typ;
46+
47+
48+
userGetSymbolBoolNow : BOOL;
49+
userGetSymbolBoolResult : BOOL;
50+
userGetSymbolBoolStatus : AbbLinkinRequestStatus_Typ;
51+
userGetSymbolNumNow : BOOL;
52+
userGetSymbolNumResult : LREAL;
53+
userGetSymbolNumStatus : AbbLinkinRequestStatus_Typ;
54+
userGetSymbolStringNow : BOOL;
55+
userGetSymbolStringResult : STRING;
56+
userGetSymbolStringStatus : AbbLinkinRequestStatus_Typ;
57+
58+
userSetSymbolBoolNow : BOOL;
59+
userSetSymbolBoolValue : BOOL := 1;
60+
userSetSymbolBoolStatus : AbbLinkinRequestStatus_Typ;
61+
userSetSymbolDintNow : BOOL;
62+
userSetSymbolDintValue : DINT := -57;
63+
userSetSymbolDintStatus : AbbLinkinRequestStatus_Typ;
64+
userSetSymbolLrealNow : BOOL;
65+
userSetSymbolLrealValue : LREAL := -41.123456;
66+
userSetSymbolLrealStatus : AbbLinkinRequestStatus_Typ;
67+
userSetSymbolStringNow : BOOL;
68+
userSetSymbolStringValue : STRING := 'test String';
69+
userSetSymbolStringStatus : AbbLinkinRequestStatus_Typ;
70+
userSetSymbolWStringNow : BOOL;
71+
userSetSymbolWStringValue : WSTRING := "test WString";
72+
userSetSymbolWStringStatus : AbbLinkinRequestStatus_Typ;
73+
74+
75+
userPowerOffNow : BOOL;
76+
userPowerOffStatus : AbbLinkinRequestStatus_Typ;
77+
userPowerOnNow : BOOL;
78+
userPowerOnStatus : AbbLinkinRequestStatus_Typ;
79+
userRapidResetNow : BOOL;
80+
userRapidResetStatus : AbbLinkinRequestStatus_Typ;
81+
userRapidStopNow : BOOL;
82+
userRapidStopStatus : AbbLinkinRequestStatus_Typ;
83+
userRapidStartNow : BOOL;
84+
userRapidStartStatus : AbbLinkinRequestStatus_Typ;
85+
86+
87+
userAckErrorNow : BOOL;
88+
END_VAR
89+
]]></Declaration>
90+
<Implementation>
91+
<ST><![CDATA[// Set configuration
92+
if userSetConfigurationNow then
93+
myRobotLink.configuration.rwsIpAddress := '127.0.0.1';
94+
myRobotLink.configuration.rwsTcpPort := 80;
95+
myRobotLink.configuration.rwsVersion := ABBLINKIN_RWS_API_VERSION.V2;
96+
myRobotLink.configuration.rwsUsername := 'Default User';
97+
myRobotLink.configuration.rwsPassword := 'robotics';
98+
//myRobotLink.configuration.tlsAllowRwsCertSelfSigned := TRUE;
99+
myRobotLink.configuration.tlsAllowRwsCertSelfSigned := FALSE;
100+
myRobotLink.configuration.tlsCAFile := 'C:\TwinCAT\3.1\Config\Certificates\TcAbbLinkinCA.pem';
101+
102+
userSetConfigurationNow := FALSE;
103+
END_IF
104+
105+
106+
// Cyclic
107+
myRobotLink.Cyclic();
108+
109+
110+
IF userConnectStartNow THEN
111+
myRobotLink.Connect();
112+
userConnectStartNow := FALSE;
113+
END_IF
114+
115+
IF userConnectStopNow THEN
116+
myRobotLink.Disconnect();
117+
userConnectStopNow := FALSE;
118+
END_IF
119+
120+
121+
IF userGetCtrlStateNow THEN
122+
myRobotLink.GetCtrlState(ADR(userGetCtrlStateStatus), ADR(userGetCtrlStateResult));
123+
userGetCtrlStateNow := FALSE;
124+
END_IF
125+
126+
127+
IF userGetOpModeNow THEN
128+
myRobotLink.GetOpMode(ADR(userGetOpModeStatus), ADR(userGetOpModeResult));
129+
userGetOpModeNow := FALSE;
130+
END_IF
131+
132+
133+
IF userGetRapidStateNow THEN
134+
myRobotLink.GetRapidState(ADR(userGetRapidStateStatus), ADR(userGetRapidStateResult));
135+
userGetRapidStateNow := FALSE;
136+
END_IF
137+
138+
139+
IF userGetIoBoolNow THEN
140+
myRobotLink.GetIODigital(signal := 'myInputDIG', pStatus := ADR(userGetIoBoolStatus), pResult := ADR(userGetIoBoolResult));
141+
userGetIoBoolNow := FALSE;
142+
END_IF
143+
144+
IF userGetIoLrealNow THEN
145+
myRobotLink.GetIOAnalog(signal := 'myInputANA', pStatus := ADR(userGetIoLrealStatus), pResult := ADR(userGetIoLrealResult));
146+
userGetIoLrealNow := FALSE;
147+
END_IF
148+
149+
IF userGetIoDintNow THEN
150+
myRobotLink.GetIOGroup(signal := 'myInputGRP', pStatus := ADR(userGetIoDintStatus), pResult := ADR(userGetIoDintResult));
151+
userGetIoDintNow := FALSE;
152+
END_IF
153+
154+
155+
IF userSetIoBoolNow THEN
156+
myRobotLink.SetIO('myInputDIG', userSetIoBoolValue, ADR(userSetIoBoolStatus));
157+
userSetIoBoolNow := FALSE;
158+
END_IF
159+
IF userSetIoDintNow THEN
160+
myRobotLink.SetIO('myInputGRP', userSetIoDintValue, ADR(userSetIoDintStatus));
161+
userSetIoDintNow := FALSE;
162+
END_IF
163+
IF userSetIoLrealNow THEN
164+
myRobotLink.SetIO('myInputANA', userSetIoLrealValue, ADR(userSetIoLrealStatus));
165+
userSetIoLrealNow := FALSE;
166+
END_IF
167+
168+
169+
IF userGetSymbolBoolNow THEN
170+
myRobotLink.GetSymbolBool(symbolUrl := 'RAPID/T_ROB1/Module1/myRapidBool', pStatus := ADR(userGetSymbolBoolStatus), pResult := ADR(userGetSymbolBoolResult));
171+
userGetSymbolBoolNow := FALSE;
172+
END_IF
173+
IF userGetSymbolNumNow THEN
174+
myRobotLink.GetSymbolNum(symbolUrl := 'RAPID/T_ROB1/Module1/myRapidNum', pStatus := ADR(userGetSymbolNumStatus), pResult := ADR(userGetSymbolNumResult));
175+
userGetSymbolNumNow := FALSE;
176+
END_IF
177+
IF userGetSymbolStringNow THEN
178+
myRobotLink.GetSymbolString(symbolUrl := 'RAPID/T_ROB1/Module1/myRapidString', pStatus := ADR(userGetSymbolStringStatus), pResult := ADR(userGetSymbolStringResult));
179+
userGetSymbolStringNow := FALSE;
180+
END_IF
181+
182+
183+
IF userSetSymbolBoolNow THEN
184+
myRobotLink.SetSymbol('RAPID/T_ROB1/Module1/myRapidBool', userSetSymbolBoolValue, ADR(userSetSymbolBoolStatus));
185+
userSetSymbolBoolNow := FALSE;
186+
END_IF
187+
IF userSetSymbolDintNow THEN
188+
myRobotLink.SetSymbol('RAPID/T_ROB1/Module1/myRapidNum', userSetSymbolDintValue, ADR(userSetSymbolDintStatus));
189+
userSetSymbolDintNow := FALSE;
190+
END_IF
191+
IF userSetSymbolLrealNow THEN
192+
myRobotLink.SetSymbol('RAPID/T_ROB1/Module1/myRapidNum', userSetSymbolLrealValue, ADR(userSetSymbolLrealStatus));
193+
userSetSymbolLrealNow := FALSE;
194+
END_IF
195+
IF userSetSymbolStringNow THEN
196+
myRobotLink.SetSymbol('RAPID/T_ROB1/Module1/myRapidString', userSetSymbolStringValue, ADR(userSetSymbolStringStatus));
197+
userSetSymbolStringNow := FALSE;
198+
END_IF
199+
IF userSetSymbolWStringNow THEN
200+
myRobotLink.SetSymbol('RAPID/T_ROB1/Module1/myRapidString', userSetSymbolWStringValue, ADR(userSetSymbolWStringStatus));
201+
userSetSymbolWStringNow := FALSE;
202+
END_IF
203+
204+
205+
IF userPowerOffNow THEN
206+
myRobotLink.PowerOff(ADR(userPowerOffStatus));
207+
userPowerOffNow := FALSE;
208+
END_IF
209+
IF userPowerOnNow THEN
210+
myRobotLink.PowerOn(ADR(userPowerOnStatus));
211+
userPowerOnNow := FALSE;
212+
END_IF
213+
IF userRapidResetNow THEN
214+
myRobotLink.RapidReset(ADR(userRapidResetStatus));
215+
userRapidResetNow := FALSE;
216+
END_IF
217+
IF userRapidStopNow THEN
218+
myRobotLink.RapidStop(ADR(userRapidStopStatus));
219+
userRapidStopNow := FALSE;
220+
END_IF
221+
IF userRapidStartNow THEN
222+
myRobotLink.RapidStart(ADR(userRapidStartStatus));
223+
userRapidStartNow := FALSE;
224+
END_IF
225+
226+
227+
IF userAckErrorNow THEN
228+
myRobotLink.AckError();
229+
userAckErrorNow := FALSE;
230+
END_IF
231+
232+
]]></ST>
233+
</Implementation>
234+
<LineIds Name="MAIN">
235+
<LineId Id="1207" Count="140" />
236+
<LineId Id="2" Count="0" />
237+
</LineIds>
238+
</POU>
239+
</TcPlcObject>

‎TwinCat/TcAbbLinkin/TcAbbLinkin/POUs/TcAbbLinkin.TcPOU

+2,953
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<TcPlcObject Version="1.1.0.1">
3+
<Task Name="PlcTask" Id="{2ca3a035-9876-4353-ab6e-484b60f77333}">
4+
<!--CycleTime in micro seconds.-->
5+
<CycleTime>10000</CycleTime>
6+
<Priority>20</Priority>
7+
<PouCall>
8+
<Name>MAIN</Name>
9+
</PouCall>
10+
<TaskFBGuid>{b156abb6-db8c-4df4-9c2a-24e57f853a73}</TaskFBGuid>
11+
<Fb_init>{199985ee-d45d-4c84-8180-8a5b29cae032}</Fb_init>
12+
<Fb_exit>{72795d93-b6c4-45a7-bf58-a7c315b625be}</Fb_exit>
13+
<CycleUpdate>{20b3cee3-b09f-44b2-97da-f92286e41abe}</CycleUpdate>
14+
<PostCycleUpdate>{90dd9f63-491f-4b1f-bad7-9fc807692f85}</PostCycleUpdate>
15+
<ObjectProperties />
16+
</Task>
17+
</TcPlcObject>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<FileVersion>1.0.0.0</FileVersion>
5+
<SchemaVersion>2.0</SchemaVersion>
6+
<ProjectGuid>{d1d47807-ddc9-4c87-ba84-a94c789102da}</ProjectGuid>
7+
<SubObjectsSortedByName>True</SubObjectsSortedByName>
8+
<DownloadApplicationInfo>true</DownloadApplicationInfo>
9+
<WriteProductVersion>true</WriteProductVersion>
10+
<GenerateTpy>false</GenerateTpy>
11+
<Name>TcAbbLinkin</Name>
12+
<ProgramVersion>3.1.4024.0</ProgramVersion>
13+
<Application>{3c914a8d-4a17-4f1e-9445-1becbb2b5183}</Application>
14+
<TypeSystem>{1c6e5c95-0d27-455e-908e-faaa1e8978af}</TypeSystem>
15+
<Implicit_Task_Info>{2b6e5500-fd60-42e2-b5f1-33190fdb4fe9}</Implicit_Task_Info>
16+
<Implicit_KindOfTask>{9ac765d3-3ac0-47da-b792-f5c56075217f}</Implicit_KindOfTask>
17+
<Implicit_Jitter_Distribution>{4dab9041-af5c-40f9-aeb5-736c8459509b}</Implicit_Jitter_Distribution>
18+
<LibraryReferences>{995e1ac0-267a-47a1-8ab1-6aac09d641b7}</LibraryReferences>
19+
<Company>Loupe</Company>
20+
<Released>false</Released>
21+
<Title>TcAbbLinkin</Title>
22+
<ProjectVersion>0.1.0</ProjectVersion>
23+
<CombineIds>true</CombineIds>
24+
<Author>Loupe</Author>
25+
</PropertyGroup>
26+
<ItemGroup>
27+
<Compile Include="DUTs\AbbLinkinAuthDigest_Typ.TcDUT">
28+
<SubType>Code</SubType>
29+
</Compile>
30+
<Compile Include="DUTs\AbbLinkinConfiguration_Typ.TcDUT">
31+
<SubType>Code</SubType>
32+
</Compile>
33+
<Compile Include="DUTs\AbbLinkinRequestResults_Typ.TcDUT">
34+
<SubType>Code</SubType>
35+
</Compile>
36+
<Compile Include="DUTs\AbbLinkinRequest_Typ.TcDUT">
37+
<SubType>Code</SubType>
38+
</Compile>
39+
<Compile Include="DUTs\AbbLinkinRequestQueue_Typ.TcDUT">
40+
<SubType>Code</SubType>
41+
</Compile>
42+
<Compile Include="DUTs\AbbLinkinRequestStatus_Typ.TcDUT">
43+
<SubType>Code</SubType>
44+
</Compile>
45+
<Compile Include="DUTs\AbbLinkinAuth_Typ.TcDUT">
46+
<SubType>Code</SubType>
47+
</Compile>
48+
<Compile Include="DUTs\ABBLINKIN_AUTH_HEADER_VALUE.TcDUT">
49+
<SubType>Code</SubType>
50+
</Compile>
51+
<Compile Include="DUTs\ABBLINKIN_RWS_API_VERSION.TcDUT">
52+
<SubType>Code</SubType>
53+
</Compile>
54+
<Compile Include="DUTs\ABBLINKIN_STATE.TcDUT">
55+
<SubType>Code</SubType>
56+
</Compile>
57+
<Compile Include="DUTs\ABBLINKIN_COMMAND_TYPE.TcDUT">
58+
<SubType>Code</SubType>
59+
</Compile>
60+
<Compile Include="DUTs\ABBLINKIN_DATA_TYPE_Typ.TcDUT">
61+
<SubType>Code</SubType>
62+
</Compile>
63+
<Compile Include="DUTs\ABBLINKIN_STRING_EX_LEN.TcDUT">
64+
<SubType>Code</SubType>
65+
</Compile>
66+
<Compile Include="PlcTask.TcTTO">
67+
<SubType>Code</SubType>
68+
</Compile>
69+
<Compile Include="POUs\MAIN.TcPOU">
70+
<SubType>Code</SubType>
71+
</Compile>
72+
<Compile Include="POUs\Example.TcPOU">
73+
<SubType>Code</SubType>
74+
</Compile>
75+
<Compile Include="POUs\TcAbbLinkin.TcPOU">
76+
<SubType>Code</SubType>
77+
</Compile>
78+
</ItemGroup>
79+
<ItemGroup>
80+
<Folder Include="DUTs" />
81+
<Folder Include="GVLs" />
82+
<Folder Include="VISUs" />
83+
<Folder Include="POUs" />
84+
</ItemGroup>
85+
<ItemGroup>
86+
<PlaceholderReference Include="Tc2_Standard">
87+
<DefaultResolution>Tc2_Standard, * (Beckhoff Automation GmbH)</DefaultResolution>
88+
<Namespace>Tc2_Standard</Namespace>
89+
</PlaceholderReference>
90+
<PlaceholderReference Include="Tc2_System">
91+
<DefaultResolution>Tc2_System, * (Beckhoff Automation GmbH)</DefaultResolution>
92+
<Namespace>Tc2_System</Namespace>
93+
</PlaceholderReference>
94+
<PlaceholderReference Include="Tc2_Utilities">
95+
<DefaultResolution>Tc2_Utilities, * (Beckhoff Automation GmbH)</DefaultResolution>
96+
</PlaceholderReference>
97+
<PlaceholderReference Include="Tc3_IotBase">
98+
<DefaultResolution>Tc3_IotBase, * (Beckhoff Automation GmbH)</DefaultResolution>
99+
<Namespace>Tc3_IotBase</Namespace>
100+
</PlaceholderReference>
101+
<PlaceholderReference Include="Tc3_JsonXml">
102+
<DefaultResolution>Tc3_JsonXml, * (Beckhoff Automation GmbH)</DefaultResolution>
103+
<Namespace>Tc3_JsonXml</Namespace>
104+
</PlaceholderReference>
105+
<PlaceholderReference Include="Tc3_Module">
106+
<DefaultResolution>Tc3_Module, * (Beckhoff Automation GmbH)</DefaultResolution>
107+
<Namespace>Tc3_Module</Namespace>
108+
</PlaceholderReference>
109+
</ItemGroup>
110+
<ItemGroup>
111+
<None Include="TcAbbLinkin.tmc">
112+
<SubType>Content</SubType>
113+
</None>
114+
</ItemGroup>
115+
<ProjectExtensions>
116+
<PlcProjectOptions>
117+
<XmlArchive>
118+
<Data>
119+
<o xml:space="preserve" t="OptionKey">
120+
<v n="Name">"&lt;ProjectRoot&gt;"</v>
121+
<d n="SubKeys" t="Hashtable" ckt="String" cvt="OptionKey">
122+
<v>{40450F57-0AA3-4216-96F3-5444ECB29763}</v>
123+
<o>
124+
<v n="Name">"{40450F57-0AA3-4216-96F3-5444ECB29763}"</v>
125+
<d n="SubKeys" t="Hashtable" />
126+
<d n="Values" t="Hashtable" ckt="String" cvt="String">
127+
<v>ActiveVisuProfile</v>
128+
<v>IR0whWr8bwfwBwAAiD2qpQAAAABVAgAA37x72QAAAAABAAAAAAAAAAEaUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwACTHsAZgA5ADUAYgBiADQAMgA2AC0ANQA1ADIANAAtADQAYgA0ADUALQA5ADQAMAAwAC0AZgBiADAAZgAyAGUANwA3AGUANQAxAGIAfQADCE4AYQBtAGUABDBUAHcAaQBuAEMAQQBUACAAMwAuADEAIABCAHUAaQBsAGQAIAA0ADAAMgA0AC4ANwAFFlAAcgBvAGYAaQBsAGUARABhAHQAYQAGTHsAMQA2AGUANQA1AGIANgAwAC0ANwAwADQAMwAtADQAYQA2ADMALQBiADYANQBiAC0ANgAxADQANwAxADMAOAA3ADgAZAA0ADIAfQAHEkwAaQBiAHIAYQByAGkAZQBzAAhMewAzAGIAZgBkADUANAA1ADkALQBiADAANwBmAC0ANABkADYAZQAtAGEAZQAxAGEALQBhADgAMwAzADUANgBhADUANQAxADQAMgB9AAlMewA5AGMAOQA1ADgAOQA2ADgALQAyAGMAOAA1AC0ANAAxAGIAYgAtADgAOAA3ADEALQA4ADkANQBmAGYAMQBmAGUAZABlADEAYQB9AAoOVgBlAHIAcwBpAG8AbgALBmkAbgB0AAwKVQBzAGEAZwBlAA0KVABpAHQAbABlAA4aVgBpAHMAdQBFAGwAZQBtAE0AZQB0AGUAcgAPDkMAbwBtAHAAYQBuAHkAEAxTAHkAcwB0AGUAbQARElYAaQBzAHUARQBsAGUAbQBzABIwVgBpAHMAdQBFAGwAZQBtAHMAUwBwAGUAYwBpAGEAbABDAG8AbgB0AHIAbwBsAHMAEyhWAGkAcwB1AEUAbABlAG0AcwBXAGkAbgBDAG8AbgB0AHIAbwBsAHMAFCRWAGkAcwB1AEUAbABlAG0AVABlAHgAdABFAGQAaQB0AG8AcgAVIlYAaQBzAHUATgBhAHQAaQB2AGUAQwBvAG4AdAByAG8AbAAWFHYAaQBzAHUAaQBuAHAAdQB0AHMAFwxzAHkAcwB0AGUAbQAYGFYAaQBzAHUARQBsAGUAbQBCAGEAcwBlABkmRABlAHYAUABsAGEAYwBlAGgAbwBsAGQAZQByAHMAVQBzAGUAZAAaCGIAbwBvAGwAGyJQAGwAdQBnAGkAbgBDAG8AbgBzAHQAcgBhAGkAbgB0AHMAHEx7ADQAMwBkADUAMgBiAGMAZQAtADkANAAyAGMALQA0ADQAZAA3AC0AOQBlADkANAAtADEAYgBmAGQAZgAzADEAMABlADYAMwBjAH0AHRxBAHQATABlAGEAcwB0AFYAZQByAHMAaQBvAG4AHhRQAGwAdQBnAGkAbgBHAHUAaQBkAB8WUwB5AHMAdABlAG0ALgBHAHUAaQBkACBIYQBmAGMAZAA1ADQANAA2AC0ANAA5ADEANAAtADQAZgBlADcALQBiAGIANwA4AC0AOQBiAGYAZgBlAGIANwAwAGYAZAAxADcAIRRVAHAAZABhAHQAZQBJAG4AZgBvACJMewBiADAAMwAzADYANgBhADgALQBiADUAYwAwAC0ANABiADkAYQAtAGEAMAAwAGUALQBlAGIAOAA2ADAAMQAxADEAMAA0AGMAMwB9ACMOVQBwAGQAYQB0AGUAcwAkTHsAMQA4ADYAOABmAGYAYwA5AC0AZQA0AGYAYwAtADQANQAzADIALQBhAGMAMAA2AC0AMQBlADMAOQBiAGIANQA1ADcAYgA2ADkAfQAlTHsAYQA1AGIAZAA0ADgAYwAzAC0AMABkADEANwAtADQAMQBiADUALQBiADEANgA0AC0ANQBmAGMANgBhAGQAMgBiADkANgBiADcAfQAmFk8AYgBqAGUAYwB0AHMAVAB5AHAAZQAnVFUAcABkAGEAdABlAEwAYQBuAGcAdQBhAGcAZQBNAG8AZABlAGwARgBvAHIAQwBvAG4AdgBlAHIAdABpAGIAbABlAEwAaQBiAHIAYQByAGkAZQBzACgQTABpAGIAVABpAHQAbABlACkUTABpAGIAQwBvAG0AcABhAG4AeQAqHlUAcABkAGEAdABlAFAAcgBvAHYAaQBkAGUAcgBzACs4UwB5AHMAdABlAG0ALgBDAG8AbABsAGUAYwB0AGkAbwBuAHMALgBIAGEAcwBoAHQAYQBiAGwAZQAsEnYAaQBzAHUAZQBsAGUAbQBzAC1INgBjAGIAMQBjAGQAZQAxAC0AZAA1AGQAYwAtADQAYQAzAGIALQA5ADAANQA0AC0AMgAxAGYAYQA3ADUANgBhADMAZgBhADQALihJAG4AdABlAHIAZgBhAGMAZQBWAGUAcgBzAGkAbwBuAEkAbgBmAG8AL0x7AGMANgAxADEAZQA0ADAAMAAtADcAZgBiADkALQA0AGMAMwA1AC0AYgA5AGEAYwAtADQAZQAzADEANABiADUAOQA5ADYANAAzAH0AMBhNAGEAagBvAHIAVgBlAHIAcwBpAG8AbgAxGE0AaQBuAG8AcgBWAGUAcgBzAGkAbwBuADIMTABlAGcAYQBjAHkAMzBMAGEAbgBnAHUAYQBnAGUATQBvAGQAZQBsAFYAZQByAHMAaQBvAG4ASQBuAGYAbwA0MEwAbwBhAGQATABpAGIAcgBhAHIAaQBlAHMASQBuAHQAbwBQAHIAbwBqAGUAYwB0ADUaQwBvAG0AcABhAHQAaQBiAGkAbABpAHQAeQDQAAIaA9ADAS0E0AUGGgfQBwgaAUUHCQjQAAkaBEUKCwQDAAAABQAAAA0AAAAAAAAA0AwLrQIAAADQDQEtDtAPAS0Q0AAJGgRFCgsEAwAAAAUAAAANAAAAKAAAANAMC60BAAAA0A0BLRHQDwEtENAACRoERQoLBAMAAAAFAAAADQAAAAAAAADQDAutAgAAANANAS0S0A8BLRDQAAkaBEUKCwQDAAAABQAAAA0AAAAUAAAA0AwLrQIAAADQDQEtE9APAS0Q0AAJGgRFCgsEAwAAAAUAAAANAAAAAAAAANAMC60CAAAA0A0BLRTQDwEtENAACRoERQoLBAMAAAAFAAAADQAAAAAAAADQDAutAgAAANANAS0V0A8BLRDQAAkaBEUKCwQDAAAABQAAAA0AAAAAAAAA0AwLrQIAAADQDQEtFtAPAS0X0AAJGgRFCgsEAwAAAAUAAAANAAAAKAAAANAMC60EAAAA0A0BLRjQDwEtENAZGq0BRRscAdAAHBoCRR0LBAMAAAAFAAAADQAAAAAAAADQHh8tINAhIhoCRSMkAtAAJRoFRQoLBAMAAAADAAAAAAAAAAoAAADQJgutAAAAANADAS0n0CgBLRHQKQEtENAAJRoFRQoLBAMAAAADAAAAAAAAAAoAAADQJgutAQAAANADAS0n0CgBLRHQKQEtEJoqKwFFAAEC0AABLSzQAAEtF9AAHy0t0C4vGgPQMAutAQAAANAxC60XAAAA0DIarQDQMy8aA9AwC60CAAAA0DELrQMAAADQMhqtANA0Gq0A0DUarQA=</v>
129+
</d>
130+
</o>
131+
<v>{192FAD59-8248-4824-A8DE-9177C94C195A}</v>
132+
<o>
133+
<v n="Name">"{192FAD59-8248-4824-A8DE-9177C94C195A}"</v>
134+
<d n="SubKeys" t="Hashtable" />
135+
<d n="Values" t="Hashtable" />
136+
</o>
137+
</d>
138+
<d n="Values" t="Hashtable" />
139+
</o>
140+
</Data>
141+
<TypeList>
142+
<Type n="Hashtable">System.Collections.Hashtable</Type>
143+
<Type n="OptionKey">{54dd0eac-a6d8-46f2-8c27-2f43c7e49861}</Type>
144+
<Type n="String">System.String</Type>
145+
</TypeList>
146+
</XmlArchive>
147+
</PlcProjectOptions>
148+
</ProjectExtensions>
149+
</Project>

‎img/AbeLincolnWithTwinCats.jpg

138 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"id": "089950f5-bad4-4163-9add-782be6d3e68b",
3+
"name": "TcAbbLinkin Environment",
4+
"values": [
5+
{
6+
"key": "abbhost",
7+
"value": "127.0.0.1",
8+
"type": "default",
9+
"enabled": true
10+
},
11+
{
12+
"key": "user",
13+
"value": "Default User",
14+
"type": "default",
15+
"enabled": true
16+
},
17+
{
18+
"key": "pw",
19+
"value": "robotics",
20+
"type": "default",
21+
"enabled": true
22+
},
23+
{
24+
"key": "http_mode",
25+
"value": "http",
26+
"type": "default",
27+
"enabled": true
28+
}
29+
],
30+
"_postman_variable_scope": "environment",
31+
"_postman_exported_at": "2024-08-05T20:23:25.464Z",
32+
"_postman_exported_using": "Postman/11.6.2"
33+
}

‎testing/Postman/TcAbbLinkin.postman_collection.json

+3,506
Large diffs are not rendered by default.

‎testing/RobotStudio/IO_setup.JPG

201 KB
Loading

‎testing/RobotStudio/Module1.mod

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
MODULE Module1
2+
!***********************************************************
3+
!
4+
! Module: Module1
5+
!
6+
! Description:
7+
! <Insert description here>
8+
!
9+
! Author: dwiens
10+
!
11+
! Version: 1.0
12+
!
13+
!***********************************************************
14+
15+
VAR num myRapidNum := 4;
16+
VAR bool myRapidBool := True;
17+
VAR string myRapidString := "HelloWorld";
18+
19+
!***********************************************************
20+
!
21+
! Procedure main
22+
!
23+
! This is the entry point of your program
24+
!
25+
!***********************************************************
26+
PROC main()
27+
!Add your code here
28+
ENDPROC
29+
ENDMODULE

‎testing/RobotStudio/Module1_setup.JPG

91.9 KB
Loading

‎testing/py/digest.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Ref: https://www.whitelist1.com/2018/04/calculating-http-digest-authentication.html
2+
3+
import hashlib
4+
5+
# from wireshark
6+
7+
# in 401 from server
8+
# Digest realm="validusers@robapi.abb", domain="/", qop="auth", nonce="MGY0Yjc2MGY2Y2QyZjAwNzp2YWxpZHVzZXJzQHJvYmFwaS5hYmI6MTkwMjg5NjRlNGE6MA==", opaque="799d5", algorithm="MD5", stale="FALSE"
9+
10+
# in second GET from client
11+
# Digest username="Default User", realm="validusers@robapi.abb", nonce="MGY0Yjc2MGY2Y2QyZjAwNzp2YWxpZHVzZXJzQHJvYmFwaS5hYmI6MTkwMjg5NjRlNGE6MA==", uri="/rw/rapid/execution", algorithm="MD5", qop=auth, nc=00000001, cnonce="diddLOPR", response="c36e30cdd2961584cd41f6f49f6bcbba", opaque="799d5"
12+
13+
un = 'Default User'
14+
pw = 'robotics'
15+
realm = "validusers@robapi.abb"
16+
17+
h1=hashlib.md5((':'.join([un, realm, pw])).encode('utf-8')).hexdigest()
18+
print("h1: ", h1)
19+
20+
method = 'GET'
21+
uri = '/rw/rapid/execution'
22+
23+
h2=hashlib.md5((':'.join([method, uri])).encode('utf-8')).hexdigest()
24+
print("h2: ", h2)
25+
26+
qop = 'auth'
27+
nonce = 'MGY0Yjc2MGY2Y2QyZjAwNzp2YWxpZHVzZXJzQHJvYmFwaS5hYmI6MTkwMjg5NjRlNGE6MA=='
28+
cnonce = 'diddLOPR'
29+
nc = '00000001'
30+
31+
32+
response=hashlib.md5((':'.join([h1, nonce, nc, cnonce, qop, h2])).encode('utf-8')).hexdigest()
33+
34+
print("resp: ", response)
35+
# Correct response: c36e30cdd2961584cd41f6f49f6bcbba

‎testing/py/httpsServer/server.key

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyx9id2L5xgYxt
3+
WjOLb6bnbN7g31MsY1jTqqaheoRQcerj0alT939lssCiG0Orz3QzdGpQz2Az4kww
4+
FdC8qCWWfmAd2YrMOPTjLqF8w/9K4kknBUOYzzPz+UvgsK33az0fGah+fYe0i4gJ
5+
WoSLmSviPfBv54E9fsr6lVtB2k5Z9WQQI4utnKTKM/l3LkjGypwPIHZ4N2ypCtS8
6+
wSE/yRMDIOy/C8jzDNOkaQSPeGbROwOgjFOPk32HTmlEcVgU1wWHKru48lS9dXpy
7+
8Qlq+J4qS0LK6U/T3fuz/simLaaCZIKoOz+83eAoWaEZjuRLzjuMeWHDjic8rIhA
8+
DssSnyKBAgMBAAECggEBAIVMPFZ0pIo87VcbShNMzEUBB6zi1kDiUfh/5H3Bu6W/
9+
SkNSr83LW1GYVciIS4xuwVUcF6jo9fG5aNTxbxE6zcvHriKTcMmULgK1YfKEsHRF
10+
BAX0BtKIq1PdLJX7Jbq0Wn41w0uMjQIwht1ygCEVs4KcbAkDs3kGcJEli0UuX/zx
11+
mwPGudfaV2fm/U33c5ge7S9qEJvAUtjXlSy4crOo0sbgSwSQEioDL7uJYsA+4pjz
12+
XtFz59Z77OyecnObRcarbjWcQYw8FQoos1PoqHIXYHzNtKP5ZI+uRr8vhracT5OV
13+
Z187dHS7No76SW5to2MdiGgrq29wrkEH77y4AjTqE4ECgYEA1tz/fDKdCc0Qyv1U
14+
iFwrPeUARJOCMEZgMQy0xHsD/Xrx3ua7VOqplgpun7Ms20QF40UpvQX0PHka0fAi
15+
XsQZeua8poXIFPYdm0Kxxx3q63fV8DPEdTGC0UC4wFya9rppdShJC8pTqi34nI+3
16+
z5xsKl4ExoBHf/xJf52Fyh6RSOcCgYEA1QJYjA0VJvbGccLWOQrMRRwWznJzRfoq
17+
plj3k7GuavNhFl6geGwx0SOnaq2DMI+bb3ZHS+Ededf9x9pbFEv0wZwvF9Z3skAP
18+
9q1Vk02OsL9K+9LA4/maQIJptfCJGSYsXjLQESjGrEjrCFlEzCxG2P06qjWMkzVf
19+
l8hiHWLORFcCgYBXYBm5TO/Vm4HXuntU1H51NhoMyRupPAVEDRG50PjHbObNKXFG
20+
0ALU1Ds2UGvOYvQt/uNBThmLOghxFUE03nQqKYjQAxlhhNB3YgDfo0f0J5BllPew
21+
XMkBBVvcRgxyh035ab+Cvu2VCArQyBUMpWTLOd6hRmtNHbBZ6BoPHq0gQwKBgQDC
22+
xbBd76CFzmTKpRPpeNwr3XFlOPX66LOTBAruPCx2kzEVmVU2iAhNakKtoxcwkj/Y
23+
/dhXo/Kl9UCTPDDIMGQPnVbafztX/IgcUYbMeMCfEWvpNF84loXbsuQif119Z5Bu
24+
WhwzdIumAc8YBTiJUXs+8t5vwSNXgBh2274LjMt7ZQKBgB3PIptcDbwfw0zoI1Qh
25+
6+5gmi4TYsAFaUEQKKxN8A2SzNDBDeGM60JGmANROM0CcECgoZyqkHyU//hb03TK
26+
IUDu/Mys6B1NkbZHfP4qdRo80UE6YVt8a1ItPLegZxh4COoEznZ0vagg5SrKv/VP
27+
Klu4pFbHayzFIC3RjczEMR0F
28+
-----END PRIVATE KEY-----

‎testing/py/httpsServer/server.pem

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDazCCAlOgAwIBAgIUIihTzbb536ztwX5YSAkYhPfxePcwDQYJKoZIhvcNAQEL
3+
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4+
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA2MTcxODQxMTdaFw0yNTA2
5+
MTcxODQxMTdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
6+
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
7+
AQUAA4IBDwAwggEKAoIBAQCyx9id2L5xgYxtWjOLb6bnbN7g31MsY1jTqqaheoRQ
8+
cerj0alT939lssCiG0Orz3QzdGpQz2Az4kwwFdC8qCWWfmAd2YrMOPTjLqF8w/9K
9+
4kknBUOYzzPz+UvgsK33az0fGah+fYe0i4gJWoSLmSviPfBv54E9fsr6lVtB2k5Z
10+
9WQQI4utnKTKM/l3LkjGypwPIHZ4N2ypCtS8wSE/yRMDIOy/C8jzDNOkaQSPeGbR
11+
OwOgjFOPk32HTmlEcVgU1wWHKru48lS9dXpy8Qlq+J4qS0LK6U/T3fuz/simLaaC
12+
ZIKoOz+83eAoWaEZjuRLzjuMeWHDjic8rIhADssSnyKBAgMBAAGjUzBRMB0GA1Ud
13+
DgQWBBS5s1Ew2X3+8esgoEch83NOzY0aUjAfBgNVHSMEGDAWgBS5s1Ew2X3+8esg
14+
oEch83NOzY0aUjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCi
15+
BY/QJD4qOkFkO18Bi3YAkd5iYDz9mBJCWEelIcUv74B70xCXh2svE/zJGCDI9O1M
16+
2ZzqsAcx/xoxvPZL4TD8HZiTMCys0bWKnB2rWXBYND1D3vCTsXOyFEBfvutEOj4K
17+
KoY9MQCFybaosBYeQFF5hAx4YXDD62MWIjpCIlS1E1mmFUE9wtNNv1MqCbQwPoiV
18+
2bLBBk74f16bXhuRM22f87tMfWC/aMPCNv3GRuY7yS4MbVDc+iesK5UBj0CSA9Lf
19+
Gf5LpUGX/nOIcYyTn/JxQEwNfwQUNnvSvnXU/OYfr1nMemNe9DEFgbZLa5y2zeN9
20+
CC4gDHAAzpp2Raa1nosI
21+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
import http.server
3+
import ssl
4+
import socket
5+
6+
class RequestHandler(http.server.SimpleHTTPRequestHandler):
7+
def do_GET(self):
8+
if self.path == '/rw/rapid/execution':
9+
self.send_response(200)
10+
self.send_header('Content-type', 'application/hal+json;v=2.0')
11+
self.end_headers()
12+
self.wfile.write(b'{"_links":{"base":{"href":"http://127.0.0.1:80/rw/rapid/"},"self":{"href":"execution"}},"status":{"code":294912},"state":[{"_type":"rap-execution","_title":"execution","ctrlexecstate":"stopped","cycle":"forever"}]}')
13+
else:
14+
self.send_response(404)
15+
self.end_headers()
16+
self.wfile.write(b'Path not found')
17+
18+
def run(server_class=http.server.HTTPServer, handler_class=RequestHandler, port=443):
19+
server_address = ('', port)
20+
httpd = server_class(server_address, handler_class)
21+
httpd.socket = ssl.wrap_socket(httpd.socket,
22+
server_side=True,
23+
certfile='server.pem', # to generate, install openssl from https://slproweb.com/products/Win32OpenSSL.html, then run `openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout server.key -out server.pem`
24+
keyfile='server.key', # (see above comment)
25+
ssl_version=ssl.PROTOCOL_TLS)
26+
print(f'Starting HTTPS server on port {port}...')
27+
httpd.serve_forever()
28+
29+
if __name__ == '__main__':
30+
run()

‎testing/py/irc5.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import requests
2+
# Define the URL
3+
4+
scheme = 'http://'
5+
host = '127.0.0.1'
6+
path = '/rw/rapid/execution'
7+
auth_user = 'Default User'
8+
auth_pw = 'robotics'
9+
10+
dictParams = {'json': '1'}
11+
# dictParams = {}
12+
13+
# Send the GET request
14+
url = scheme + host + path
15+
response = requests.get(url, params=dictParams, auth=requests.auth.HTTPDigestAuth(auth_user, auth_pw))
16+
17+
# Check if the request was successful
18+
if response.status_code == 200:
19+
print("Request was successful!")
20+
# Print the response content
21+
print("Response Content:", response.text)
22+
else:
23+
print("Failed to retrieve data")
24+
print("Status Code:", response.status_code)
25+
print("Response Content:", response.text)

‎testing/py/listenUdpPort8000.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import socket
2+
3+
# Define the IP address and port to listen on
4+
UDP_IP = "127.0.0.1"
5+
UDP_PORT = 8000
6+
7+
# Create a UDP socket
8+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
9+
10+
# Bind the socket to the IP address and port
11+
sock.bind((UDP_IP, UDP_PORT))
12+
13+
print(f"Listening for UDP packets on {UDP_IP}:{UDP_PORT}")
14+
15+
while True:
16+
# Receive data from the socket (buffer size is 1024 bytes)
17+
data, addr = sock.recvfrom(1024)
18+
19+
# Print the received data
20+
print(f"Received message from {addr}: {data.decode('utf-8', 'ignore')}")

0 commit comments

Comments
 (0)
Please sign in to comment.