Closed tukusejssirs closed 1 year ago
This is on Linux, correct?
I bet you what is happening is that one of the native calls being made is not marked with the proper constant for Linux. I have been focusing on Windows and ARM only so far.
If you are using the default config.yaml then the class to look at would be strategy_type: l99.driver.fanuc.collectors.Basic07. It would be easier to modify the config.yaml to call Basic01 collector, which has much less calls:
strategy_type: l99.driver.fanuc.collectors.Basic01, fanuc
This is on Linux, correct?
Yes, on Fedora 32 x86_64, though the production will be on CentOS 8 x86_64.
I bet you what is happening is that one of the native calls being made is not marked with the proper constant for Linux. I have been focusing on Windows and ARM only so far.
If you are using the default config.yaml then the class to look at would be strategy_type: l99.driver.fanuc.collectors.Basic07. It would be easier to modify the config.yaml to call Basic01 collector, which has much less calls:
strategy_type: l99.driver.fanuc.collectors.Basic01, fanuc
I tried several strategy types and handler types, but the error is still the same.
Is there a way to help you somehow?
Basically as I go through the functions I need to call I add a conditional to fwlib32.cs for that method. So here:
I change that to:
let me go through it and try it on my linux box.
Try the latest push. I tried on Ubuntu 20.04.
dotnet build /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 -p:DefineConstants=LINUX64
You should get this error.
Here is the problem: https://stackoverflow.com/questions/52984790/fieldsoffset-in-structs-in-x64-c-sharp-application
We have three options:
Well looks like x86 is not supported.
https://github.com/dotnet/core/blob/main/os-lifecycle-policy.md
So back to trying to get it running on 64bit? I'm not sure of any other option.
Also, if you comment out line 65,66 from Basic01, it should run for you.
If you want to fiddle around and try to make RdParam call work on 64 bit, that would be appreciated.
Try the latest push. I tried on Ubuntu 20.04.
dotnet build /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 -p:DefineConstants=LINUX64
You should get this error.
I’ve got the same error.
Also, if you comment out line 65,66 from Basic01, it should run for you.
No, it couldn’t run. Now I’ve got the original error again (Collector initialization failed. System.DllNotFoundException: Unable to load shared library 'FWLIB32.dll' or one of its dependencies.
).
FYI, currently I test fanuc-driver
on Doosan Puma 2600LM with Fanuc Series 0i-TF controller.
We have three options:
1. go through fwlib32.cs and make it work for 64bit. 2. test on 32bit. 3. run in Docker using a 32bit image.
Optioin 1 would be ideal from my point of view, if not, then 32-bit program.
Well looks like x86 is not supported.
https://github.com/dotnet/core/blob/main/os-lifecycle-policy.md
So back to trying to get it running on 64bit? I'm not sure of any other option.
Well, as I’d like to run fanuc-driver
on a 64-bit OS, that would be awesome, however, seeing the limitations, is it possible with the resources we (you) have?
If you want to fiddle around and try to make RdParam call work on 64 bit, that would be appreciated.
I’d like to do that, I just some pointers–what should I fiddle with in the shared code? Change the FieldOffset
s? Is this info available somewhere in the Fanuc manuals?
Anyway, a big thank you for trying and helping me out! I should by you a beer or something. :wink:
Update:
I read cnc_rdparam
docs, but there is no information on the configuration for Fanuc i0-TF. I still don’t how or what exactly should I modify in order to fiddle around. Maybe you ment to port it to 64-bit?
While going through the code, I keep seeing focas1
(e.g. fanuc/platform/RdParam.cs
(L53)). ATM I test fanuc-driver
on FOCAS2-enabled machines. Is that a problem? Or can fanuc-driver
work with both FOCAS1 and FOCAS2?
Update 3:
Would a parameter manual for specific Fanuc controller help?
I don't understand why the latest push wouldn't run for you.
dotnet build /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 -p:DefineConstants=LINUX64
You are calling out Basic01.cs in config?
strategy_type: l99.driver.fanuc.collectors.Basic01, fanuc
Is this a limitation of which *nix flavor the library can run on?
And last I heard, Linux support has been dropped from Focas because "too many Linux variants".
Yes, sorry, I meant port it to 64bit. This is more of an exercise in p/invoke and marshaling types between unmanaged code and .NET, like this link (https://stackoverflow.com/questions/52984790/fieldsoffset-in-structs-in-x64-c-sharp-application), but you are not even getting this type of error.
Re Focas1/Focas2: the fwlib32.cs file comes from the A02B-0207-K737 CD.
Can I convince you to run it on a Raspberry Pi (bare metal or docker / armv7) or Nano Pi (docker / aarch64)?
Let's drink a beer after we get this working.
I don't understand why the latest push wouldn't run for you.
dotnet build /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 -p:DefineConstants=LINUX64
You are calling out Basic01.cs in config?
strategy_type: l99.driver.fanuc.collectors.Basic01, fanuc
Definitely yes. Below is the content of config.yaml
I used.
config.yaml
Is this a limitation of which *nix flavor the library can run on?
I can’t answer that.
And last I heard, Linux support has been dropped from Focas because "too many Linux variants".
Yes, so I heard too. However, I personally don’t really care if they support it as long as it works. :wink:
Yes, sorry, I meant port it to 64bit. This is more of an exercise in p/invoke and marshaling types between unmanaged code and .NET, like this link (https://stackoverflow.com/questions/52984790/fieldsoffset-in-structs-in-x64-c-sharp-application), but you are not even getting this type of error.
I see. I’ll do my best, but keep in mind that my C/C++/C# knowledge is minimal at best.
Re Focas1/Focas2: the fwlib32.cs file comes from the A02B-0207-K737 CD.
There is only one mention of FOCAS2 in that screenshot: Since the functions of all FOCAS2 is not defined, add the function not defined in this file.
Does it mean that all functions that are added to FOCAS2 in comparison with FOCAS1 are not defined in fwlib32.cs
/fwlib32.vb
(and therefore fwlib32.cs
/fwlib32.vb
is not meant to be working with FOCAS2) or the only added function is not defined
(as in one function named not_defined()
), and therefore all that is needed to make fwlib32.cs
/fwlib32.vb
compatible with FOCAS2 is to defined that function?
Can I convince you to run it on a Raspberry Pi (bare metal or docker / armv7) or Nano Pi (docker / aarch64)?
Not really. I’d rather run a Docker image that having an extra hardware to a dedicated bare-metal/physical server + VMware ESXi + VM (CentOS 8)
Let's drink a beer after we get this working.
Agreed! :+1:
This should help with porting to 64bit.
But again, the Basic01.cs example runs fine for me on Ubuntu. But not for you...
This should help with porting to 64bit.
Thanks, I’ll look at it.
But again, the Basic01.cs example runs fine for me on Ubuntu. But not for you...
Are there any additional requirements/dependencies that are fullfilled on Ubuntu by default, but not on Fedora / RHEL-like systems?
I don't know. Do you want to spin up a Ubuntu VM and we can try there?
Does it mean that all functions that are added to FOCAS2 in comparison with FOCAS1 are not defined in fwlib32.cs/fwlib32.vb (and therefore fwlib32.cs/fwlib32.vb is not meant to be working with FOCAS2) or the only added function is not defined (as in one function named not_defined()), and therefore all that is needed to make fwlib32.cs/fwlib32.vb compatible with FOCAS2 is to defined that function?
Maybe ?
I don't know. Do you want to spin up a Ubuntu VM and we can try there?
I’ll try doing that.
Does it mean that (1) all functions that are added to FOCAS2 in comparison with FOCAS1 are not defined in fwlib32.cs/fwlib32.vb (and therefore fwlib32.cs/fwlib32.vb is not meant to be working with FOCAS2) or (2) the only added function is not defined (as in one function named not_defined()), and therefore all that is needed to make fwlib32.cs/fwlib32.vb compatible with FOCAS2 is to defined that function?
Maybe ?
Which of the two possible explations are maybe valid? :wink:
2 !
Probably a stupid question: can’t we use 32-bit library in 64-bit C# code on x86_64 multilib Linux?
I don't think you can mix bitness in .NET process...
Then for running fanuc-driver
without VM/Docker/RPi, I see only two other possibilities:
fanuc-driver
:
fwlib
to 64-bit:
fwlib
?32 bit runs great on a Raspberry Pi and Windows.
We don't know. And we don't know what other issues will come up for 64bit. I would assume that fwlib64.dll for Windows would be better tested than the Linux 64bit shared objects.
I compared your fwlib32.cs
with dlozina’s fwlib64.cs
using git diff --no-index
. Of course, I pre-processed the two files in order to remove comments, most extra spaces and replacing FWLIB32.dll
with FWLIB64.dll
. You can find the compared files here → fwlib32_orig.txt
, fwlib64_mdfd_dlozina.txt
. This produces 1587 lines of diff
code vs ~12,000 lines in each files. Here’s the diff → fwlib32_64_diff.txt.
As I am not a C/C++/C# coder, I believe you could better see the changes required to improve the x64 support in fwlib32.cs
. From what I have seen, he has some additional/different classes and also defines some additional variables.
Looking at that diff, I'm not sure how 64bit compatible that specific fwlib64.cs really is.
From my understanding the changes would be something like this:
native definition:
/* read parameter */
FWLIBAPI short WINAPI cnc_rdparam( unsigned short, short, short, short, IODBPSD * ) ;
typedef struct iodbpsd {
short datano ; /* data number */
short type ; /* axis number */
union {
char cdata ; /* parameter / setting data */
short idata ;
long ldata ;
char cdatas[MAX_AXIS] ;
short idatas[MAX_AXIS] ;
long ldatas[MAX_AXIS] ;
} u ;
} IODBPSD
32bit:
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3
{
[FieldOffset(0)]
public short datano;
[FieldOffset(2)]
public short type;
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(4), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
64bit:
[StructLayout(LayoutKind.Sequential)]
public class IODBPSD_3
{
public short datano;
public short type;
public IODBPSD_3_INNER inner;
}
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3_INNER
{
[FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
Basically we are modifying how the data coming from the unmanaged C side will be fit into a .NET object.
https://devblogs.microsoft.com/oldnewthing/20090813-00/?p=17113
I see. Would it be possible to use fwlib64.cs
without (much) modifications in fanuc-driver
? I could test it it would work like that, but could you create a simple test script (or a test branch) for me that would utilise fwlib64.cs
? What I mean is when running on x86_64 OS, simply use fwlib64.cs
.
When testing the commented out lines in Basic01.cs
, I have forgotten to recompile the changes. :facepalm: Now I get the same error as if I haven’t commented them out (Could not load type 'IODBPSD_3' from assembly 'fanuc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field.
).
I tested this on Ubuntu 20.04.01 in VirtualBox. I installed dotnet
v3.1 using these instructions (did you install them using snap
?). Then I did as follows:
git clone --recurse-submodules git@github.com:Ladder99/fanuc-driver.git
DOTNET_CLI_TELEMETRY_OPTOUT=true dotnet build /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 -p:DefineConstants=LINUX64 fanuc-driver/fanuc/fanuc.csproj
cd fanuc-driver/fanuc
DOTNET_CLI_TELEMETRY_OPTOUT=true dotnet run /nowarn:CS0618 /nowarn:CS8632 /nowarn:CS1998 fanuc.csproj
Some warnings were raised, see below the output of the dotnet
commands.
dotnet build
dotnet run
Can I convince you to run it on a Raspberry Pi (bare metal or docker / armv7) or Nano Pi (docker / aarch64)?
On second thoughts: could you send me some commands how could I test out the Docker armv7 version?
That said, I still would like to see a fully functioning native x86_64 Linux version.
Can I convince you to run it on a Raspberry Pi (bare metal or docker / armv7) or Nano Pi (docker / aarch64)?
On second thoughts: could you send me some commands how could I test out the Docker armv7 version?
That said, I still would like to see a fully functioning native x86_64 Linux version.
lol...
I tried to create the Docker image, but it fails.
sudo dnf -y upgrade
sudo dnf -y install curl docker python3-pip libffi-devel openssl-devel python3-devel python3 python3-pip
sudo systemctl enable --now docker
sudo pip3 install docker-compose
sudo sync
git clone --recurse-submodules -j8 https://github.com/Ladder99/fanuc-driver.git
cd fanuc-driver && sudo docker build -f Dockerfile.ARM --tag=ladder99/fanuc-driver:latest .
sudo docker push ladder99/fanuc-driver
sudo docker run -it ladder99/fanuc-driver:latest
The following command was not successful; see the logs. I haven’t found the standard_init_linux.go
file in fanuc-driver
repository nor in the content of any files in it.
sudo docker build -f Dockerfile.ARM --tag=ladder99/fanuc-driver:latest .
Aah, you're trying to run an ARMv7 image on x86 architecture. You have to run this on ARM directly, like a Raspberry Pi.
So Focas ARM library will run on armv7 and aarch64. Both of which have supported .NET. Focas Linux x86 will run on 32 bit Linux, but .NET is not supported on Linux 32 bit. Focas Linux x64 will run on 64 bit Linux, but we have the issues with unmanaged code marshaling. ... and Focas Windows 64bit will run on 64bit Windows, but again, unmanaged code marshaling issues.
And you don't need docker push
. That pushes the built image to https://hub.docker.com/repository/docker/ladder99/fanuc-driver.
Also, you should not sudo
docker run
.
Aah, you're trying to run an ARMv7 image on x86 architecture. You have to run this on ARM directly, like a Raspberry Pi.
So Focas ARM library will run on armv7 and aarch64. Both of which have supported .NET. Focas Linux x86 will run on 32 bit Linux, but .NET is not supported on Linux 32 bit. Focas Linux x64 will run on 64 bit Linux, but we have the issues with unmanaged code marshaling. ... and Focas Windows 64bit will run on 64bit Windows, but again, unmanaged code marshaling issues.
I’m a bit lost here. Does this mean it won’t work on x86_64 Linux?
And you don't need
docker push
. That pushes the built image to https://hub.docker.com/repository/docker/ladder99/fanuc-driver.
So remove it from the instructions please. :wink: You place a hash sign before it, but I though it means to be run as superuser, but now I think use just commented it out.
Also, you should not
sudo
docker run
.
Well, yeah, but the default installation of docker
via dnf
/yum
on RHEL-like systems allows running it only by root. Of course, I could create a separate user/group (like you suggest in the instructions), but for testing purposes this shouldn’t an issue.
I see. Would it be possible to use
fwlib64.cs
without (much) modifications infanuc-driver
? I could test it it would work like that, but could you create a simple test script (or a test branch) for me that would utilisefwlib64.cs
? What I mean is when running on x86_64 OS, simply usefwlib64.cs
.
@MRIIOT, you haven’t reacted on this yet. Is it possible?
I see. Would it be possible to use
fwlib64.cs
without (much) modifications infanuc-driver
? I could test it it would work like that, but could you create a simple test script (or a test branch) for me that would utilisefwlib64.cs
? What I mean is when running on x86_64 OS, simply usefwlib64.cs
.@MRIIOT, you haven’t reacted on this yet. Is it possible?
We would have to test each 64bit call individually. So yes, it will be possible once we validate that 64bit calls are working. It might be more work than necessary right now. I would prefer to build some use cases for 32bit for now... since it is working.
Aah, you're trying to run an ARMv7 image on x86 architecture. You have to run this on ARM directly, like a Raspberry Pi. So Focas ARM library will run on armv7 and aarch64. Both of which have supported .NET. Focas Linux x86 will run on 32 bit Linux, but .NET is not supported on Linux 32 bit. Focas Linux x64 will run on 64 bit Linux, but we have the issues with unmanaged code marshaling. ... and Focas Windows 64bit will run on 64bit Windows, but again, unmanaged code marshaling issues.
I’m a bit lost here. Does this mean it won’t work on x86_64 Linux?
Only the Linux 64 Fanuc library will work in the x86_64 context, bare metal or docker.
Only the Arm Focas library will work in the ARMV7/AARCH context.
For Linux 64 you want to use Dockerfile.LINUX64
... but we have the 64bit issue.
And you don't need
docker push
. That pushes the built image to https://hub.docker.com/repository/docker/ladder99/fanuc-driver.So remove it from the instructions please. 😉 You place a hash sign before it, but I though it means to be run as superuser, but now I think use just commented it out.
OK
Also, you should not
sudo
docker run
.Well, yeah, but the default installation of
docker
viadnf
/yum
on RHEL-like systems allows running it only by root. Of course, I could create a separate user/group (like you suggest in the instructions), but for testing purposes this shouldn’t an issue.
I see. Would it be possible to use
fwlib64.cs
without (much) modifications infanuc-driver
? I could test it it would work like that, but could you create a simple test script (or a test branch) for me that would utilisefwlib64.cs
? What I mean is when running on x86_64 OS, simply usefwlib64.cs
.@MRIIOT, you haven’t reacted on this yet. Is it possible?
We would have to test each 64bit call individually. So yes, it will be possible once we validate that 64bit calls are working. It might be more work than necessary right now. I would prefer to build some use cases for 32bit for now... since it is working.
I see. How could I help you validate if the 64-bit calls are working?
Well.... It's a process.
Here is the result on Ubuntu 20.04.
So there is no need for a separate fwlib64.cs. The fwlib32.cs needs to be modified to work with 32 and 64 bit. Above is an example of a call to cnc_rdparam with IODBPSD_1 structure.
The changes required just for this one are:
before:
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_1
{
[FieldOffset(0)]
public short datano;
[FieldOffset(2)]
public short type;
[FieldOffset(4)]
public byte cdata;
[FieldOffset(4)]
public short idata;
[FieldOffset(4)]
public int ldata;
}
after:
[StructLayout(LayoutKind.Sequential)]
public class IODBPSD_1
{
public short datano;
public short type;
public IODBPSD_1_INNER data;
}
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_1_INNER
{
[FieldOffset(0)]
public byte cdata;
[FieldOffset(0)]
public short idata;
[FieldOffset(0)]
public int ldata;
}
I see this pattern across a lot function calls in the Focas library. Here, for example, parameters can be different sizes, so they just stick cdata, idata, ldata into the same structure, same memory location, just different size. It's up to the developer to know to look at ldata in the case of 'power on time'.
This change, of course, trickles down because now any references to IODBPSD_1.ldata are now IODBPSD_1.data.ldata.
I guess validation of data is best done at the machine depending on the data we want to collect. So we can focus on any of the current Focas calls I have implemented.
Someone (I can when I have time) has to go through the entire fwlib32.cs and:
Thanks. :+1:
If I got it right, there 240 different functions/classes (see the list below) that need to be fixed + 4 which are commented out (L8788-8799: IODBPSD_A
, IODBPSD_B
, IODBPSD_C
, IODBPSD_D
). It is quite a lot to do; I presume it cover most (if not all) of the code in fwlib32.cs
.
I see this pattern across a lot function calls in the Focas library. Here, for example, parameters can be different sizes, so they just stick cdata, idata, ldata into the same structure, same memory location, just different size.
Okay, therefore I need to get the parameter list in order fix those functions/methods, right?
It's up to the developer to know to look at ldata in the case of 'power on time'.
Therefore when I want to implement power on time
in my app (which would use fanuc-driver
), I need to check the parameter list of the particular controller to get the right variable name (cdata
, idata
, or ldata
), right?
Thanks. 👍
If I got it right, there 240 different functions/classes (see the list below) that need to be fixed + 4 which are commented out (L8788-8799:
IODBPSD_A
,IODBPSD_B
,IODBPSD_C
,IODBPSD_D
). It is quite a lot to do; I presume it cover most (if not all) of the code infwlib32.cs
.list of functions/classes
Yeah, and I don't think we have to touch them all right away, just as they are needed.
I see this pattern across a lot function calls in the Focas library. Here, for example, parameters can be different sizes, so they just stick cdata, idata, ldata into the same structure, same memory location, just different size.
Okay, therefore I need to get the parameter list in order fix those functions/methods, right?
edit: not really, the method signatures are what they are. the cnc_rdparam function that takes IODBPSD_1 is fixed up for 64bit. IODBPSD_2, IODBPSD_3, IODBPSD_4 should be fixed up as they can be used right now from fanuc-driver code base.
edit: unions .... https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-classes-structures-and-unions#unions-sample
edit: ObjectLayoutInspector... https://github.com/SergeyTeplyakov/ObjectLayoutInspector
Yes, should be in the manual, called out with data type. I think there is a Focas function to interrogate a specific parameter and return what type it is and stuff.
It's up to the developer to know to look at ldata in the case of 'power on time'.
Therefore when I want to implement
power on time
in my app (which would usefanuc-driver
), I need to check the parameter list of the particular controller to get the right variable name (cdata
,idata
, orldata
), right?
Yes sir. And getting the ldata is implemented using https://github.com/Ladder99/fanuc-driver/blob/main/fanuc/veneers/RdParamLData.cs (which could be made more generic).
If I got it right, there 240 different functions/classes (see the list below) that need to be fixed + 4 which are commented out (L8788-8799:
IODBPSD_A
,IODBPSD_B
,IODBPSD_C
,IODBPSD_D
). It is quite a lot to do; I presume it cover most (if not all) of the code infwlib32.cs
.
I think we can use this list to keep track of what has been converted to 64bit and tested .
Argh … I’m a bit lost in C#; so many new stuff for me.
Is the following code refactoring the right way to do it? Note that I didn’t check anything anywhere nor changed anything else in the code. I seems I need to changed something else, because the collector sweep failed
didn’t go away.
// Original code
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3
{
[FieldOffset(0)]
public short datano; /* data number */
[FieldOffset(2)]
public short type; /* axis number */
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
// Refactored code
[StructLayout(LayoutKind.Sequential)]
public class IODBPSD_3
{
public short datano;
public short type;
public IODBPSD_3_INNER data;
}
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3_INNER
{
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
edit: unions .... https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-classes-structures-and-unions#unions-sample
Unions look be me like simple objects in JS or hashes in Perl, but unions are typed, right?
Anyway, where do I need them to use? I grepped the whole code, but no match found.
Okay, therefore I need to get the parameter list in order fix those functions/methods, right?
edit: not really, the method signatures are what they are.
What are method signatures?
the cnc_rdparam function that takes IODBPSD_1 is fixed up for 64bit. IODBPSD_2, IODBPSD_3, IODBPSD_4 should be fixed up as they can be used right now from fanuc-driver code base.
At least for me, the latest commit of main
still complains about collector sweeping failed
and that it could not load IODBPSD_3
.
edit: ObjectLayoutInspector... https://github.com/SergeyTeplyakov/ObjectLayoutInspector
How can I use ObjectLayoutInspector
with fanuc-driver
(actually with the FOCAS2 response)?
Yes, should be in the manual, called out with data type. I think there is a Focas function to interrogate a specific parameter and return what type it is and stuff.
That function might be useful for me (us) to get the parameter metadata, but I have no idea how to use it.
Meanwhile, I have created a list of data we would like to get (read) from Fanucs with functions from the list provided by inventcom.net. I did my best to assign those functions correctly; you might find some misassignments and definitely there are some missing functions which provide some specific information.
cnc_sysinfo
;cnc_sysinfo_ex
(difference between cnc_sysinfo
and cnc_sysinfo_ex
?);cnc_sysconfig
;cnc_rdsyssoft
;cnc_rdsyssoft2
;cnc_rdsyssoft3
;cnc_rdsyshard
;cnc_rdetherinfo
;cnc_rdproginfo
;cnc_rdprgnum
;cnc_exeprgname
;cnc_rdseqnum
;cnc_rdblkcount
;cnc_rdexecprog
;cnc_rdrepeatval
;cnc_rdrepeatval_ext
;cnc_rdparam
(6711
, 6712
and 6713
);cnc_alarm
;cnc_alarm2
;cnc_rdalminfo
;cnc_rdalmmsg
(this one may be redundant, as cnc_rdalmmsg2
should contain the same information + axis names);cnc_rdalmmsg2
;cnc_getdtailerr
(I am not quite sure if the detailed error is regarding alarms or some other kind of errors);cnc_statinfo
;cnc_statinfo2
;cnc_rdopnlsgnl
(slct_data
, bits 4 and 5);rapid traverse override
by Fanuc; this is not that important to get);
cnc_rdopnlsgnl
(slct_data
, bit 3).Okay, with the latest code (main
@ 337aded) and the changing of the code below in fwlib.cs
(L1240-1256) there is no error, but also no output (beside the values of --config
and --nlog
).
// Original code
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3
{
[FieldOffset(0)]
public short datano; /* data number */
[FieldOffset(2)]
public short type; /* axis number */
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(4),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
// Refactored code
[StructLayout(LayoutKind.Sequential)]
public class IODBPSD_3
{
public short datano;
public short type;
public IODBPSD_3_INNER data;
}
[StructLayout(LayoutKind.Explicit)]
public class IODBPSD_3_INNER
{
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public byte[] cdatas = new byte[MAX_AXIS];
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public short[] idatas = new short[MAX_AXIS];
[FieldOffset(0),
MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_AXIS)]
public int[] ldatas = new int[MAX_AXIS];
}
How can I output the gathered values?
Anyway, could the focas2.log
be a text file with newline-delimited records? Currently, it contains some control characters (at least ^C
/ETX
/0x03
) and the records are delimited with 175+ spaces. From my point of view, it is a log and as such it should be a bit more human readable.
For now, I use sed 's/\x03//g;s/\r/\n/g;s/ \+\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\)/\n\1/g' focas2.log | sed -z 's/^[\n ]*//;s/[\n ]*$//' | less
to make it more human-readable.
I'm traveling this week. I will be back later this week. I will probably hop on tomorrow night.
As far as output, turn up the logging in nlog.config. Also, do you have an mqtt broker set up? That is where the data goes by default. What system will be consuming this data in your environment?
Anyway, could the
focas2.log
be a text file with newline-delimited records? Currently, it contains some control characters (at least^C
/ETX
/0x03
) and the records are delimited with 175+ spaces. From my point of view, it is a log and as such it should be a bit more human readable.For now, I use
sed 's/\x03//g;s/\r/\n/g;s/ \+\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\)/\n\1/g' focas2.log | sed -z 's/^[\n ]*//;s/[\n ]*$//' | less
to make it more human-readable.
focas2.log is a Linux only log from the Fanuc library. We have no control over it.
public static extern short cnc_startupprocess(long level, string filename);
Okay, with the latest code (
main
@ 337aded) and the changing of the code below infwlib.cs
(L1240-1256) there is no error, but also no output (beside the values of--config
and--nlog
).public class IODBPSD_3_INNER {
I renamed _INNER to _UNION, which makes more sense.
do you have an mqtt broker set up? That is where the data goes by default.
No, I didn’t. I coudn’t find anything on MQTT configuration in fanuc-driver
in README.md
. Could you provide me a sample configuration to subscribe to all messages/topics?
Anyway, could you tell me what is that disco
for in MQTT? I could not find anything on this on the Internet (it looks like I queried the wrong strings :wink:).
What system will be consuming this data in your environment?
Well, my downstream app would be written in Node JS (JS for now, later in TS). It would process the gathered data. All of this (fanuc-driver
+ my Node JS app) would run locally on a x86_64 Linux server.
focas2.log is a Linux only log from the Fanuc library. We have no control over it.
public static extern short cnc_startupprocess(long level, string filename);
I see. But could you not catch the output prior to writing it to file? I know, this is not that important, but it’s nice to have. :wink:
I renamed
_INNER
to_UNION
, which makes more sense.
Thanks for letting me know. :+1:
So all those unions are actually objects (as in JSON/TS/TS) or hashes (as in Perl), right?
Could you make fanuc-driver
work from any CWD? You should use the script/program path as the CWD of the program, not the CWD the user is in when they run fanuc-driver
. See the log below.
dotnet run
do you have an mqtt broker set up? That is where the data goes by default.
No, I didn’t. I coudn’t find anything on MQTT configuration in
fanuc-driver
inREADME.md
. Could you provide me a sample configuration to subscribe to all messages/topics?
Look in config.yml at the broker section.
Look in config.yml at the broker section.
Yes, I have looked in there, see the config below.
broker:
enabled: !!bool true
net_ip: 127.0.0.1
net_port: !!int 1883
auto_connect: !!bool true
publish_status: !!bool true
publish_arrivals: !!bool true
publish_changes: !!bool true
publish_disco: !!bool true
disco_base_topic: fanuc
I have started an MQTT server (broker) in Node JS using aedes
; I believe I need to subscribe some topics/messages, but I have no idea what are their names (or whatever they are called). Or should I start an MQTT client using async-mqtt
? I am a bit lost in the MQTT terminology (I have never used MQTT).
fanuc-driver
seems to connect to the MQTT broker (server), because when the broker is not running prior to starting fanuc-driver
, it errors out that the broker connection failed
. When the broker is already running, there is no error, but also no output.
This underlines my assumptions that all I need is to subscribe some topics/messages. Could you tell me where could I find the topic/message names I need to subscribe? Thanks in advance! :wink:
Update
Okay, I’ve got it working. I usee #
to subscribe to all topics. Now I better (not fully though) understand how fanuc-driver
works.
A bit OT (related to #8): as I understand it, fanuc-driver
gathers all information it can (i.e. it is programmed to collect). Could we define what should be gathered in order to minimise the communication between machine(s) and fanuc-driver
? Of course, there are some data that should be always gathered (esp at connection initialisation), but even most of that could be configurable in config.yml
(i.e. the downstream app could collect those information fanuc-driver
runs the very first time and the subsequent fanuc-driver
runs could use that info instead of collecting them again. Of course, this is just a brain exercise for you.
A bit OT (related to #8): as I understand it,
fanuc-driver
gathers all information it can (i.e. it is programmed to collect). Could we define what should be gathered in order to minimise the communication between machine(s) andfanuc-driver
? Of course, there are some data that should be always gathered (esp at connection initialisation), but even most of that could be configurable inconfig.yml
(i.e. the downstream app could collect those informationfanuc-driver
runs the very first time and the subsequentfanuc-driver
runs could use that info instead of collecting them again. Of course, this is just a brain exercise for you.
Agreed, no need to pull axis names every second. This should be optimized eventually.
What system will be consuming this data in your environment?
Well, my downstream app would be written in Node JS (JS for now, later in TS). It would process the gathered data. All of this (
fanuc-driver
+ my Node JS app) would run locally on a x86_64 Linux server.
MQTT-WS is your friend.
focas2.log is a Linux only log from the Fanuc library. We have no control over it.
public static extern short cnc_startupprocess(long level, string filename);
I see. But could you not catch the output prior to writing it to file? I know, this is not that important, but it’s nice to have. 😉
It looks like it would be helpful for reversing the protocol on the wire.
Could you make
fanuc-driver
work from any CWD? You should use the script/program path as the CWD of the program, not the CWD the user is in when they runfanuc-driver
. See the log below.
dotnet run
How?
fanuc-driver
seems to connect to the MQTT broker (server), because when the broker is not running prior to startingfanuc-driver
, it errors out that thebroker connection failed
. When the broker is already running, there is no error, but also no output.
Yup, re-connects need to be handled.
MQTT-WS is your friend.
You mean mqtt-ws
? That code seen last release 8 years ago. The repo link is dead. The NPM description says is uses mqtt.js
which seems to be client only, while (as I understand it), fanuc-driver
is implemented as MQTT client and the client app needs to be an MQTT server, which is why I use aedes
, which works as expected.
Therefore currently, I don’t see this as an issue. :wink:
focas2.log is a Linux only log from the Fanuc library. We have no control over it.
public static extern short cnc_startupprocess(long level, string filename);
I see. But could you not catch the output prior to writing it to file? I know, this is not that important, but it’s nice to have. wink
It looks like it would be helpful for reversing the protocol on the wire.
Indeed it would be useful for that. :wink:
Could you make
fanuc-driver
work from any CWD? You should use the script/program path as the CWD of the program, not the CWD the user is in when they runfanuc-driver
. See the log below.dotnet run
How?
You could take a look at this SO answer or other answers in that question.
Basically, all you need to do is:
{repo_root}/fanuc
).That way you wouldn’t use relative paths anymore, but absolute paths.
I have encountered the following error. I am not sure if the error is raised because I haven’t placed a library at the required location. Actually, I didn’t move/copy any library files, because (as I understand it)
fanuc-driver
should contain the required libraries (of course, not for all Fanuc controller versions).I found
fanuc/Fwlib32.dll
, but it does not even symlinking it tofanuc/FWLIB32.dll
wouldn’t solve the problem (presuming that the problem is in the case sensitivity of Linux).Update:
Although I presume
fanuc-driver
supports FOCAS2,fanuc/fwlib32.cs
(L4) states it is for FOCAS1. It might not be an issue though.One note: I try to connect to Fanuc Series 0i-TF, which might not be fully supported by
fanuc-driver
, however, I presume that at least I should be able to connect to FOCAS2.Update 2
Here is the list of all functions/classes that needs to be ported to x64 (or at least reviewed) in order to make
fanuc-driver
work on x64 systems.list of functions/classes
- [ ] `ALMINFO_1`; - [ ] `ALMINFO_2`; - [ ] `CFILEINFO`; - [ ] `DSMNTINFO`; - [ ] `HSPDATA_1`; - [ ] `HSPDATA_2`; - [ ] `HSPDATA_3`; - [ ] `HSPINFO`; - [ ] `HSPINFO_data`; - [ ] `IDBCHAN`; - [ ] `IDBITD`; - [ ] `IDBMGRP`; - [ ] `IDBPDFSDIR`; - [ ] `IDBPDFTDIR`; - [ ] `IDBSFBCHAN`; - [ ] `IDBTLM`; - [ ] `IDBUNSOLICMSG`; - [ ] `IDBWRA`; - [ ] `IDBWRC`; - [ ] `IDBWRR`; - [ ] `IODBBUSPRM`; - [ ] `IODBDIDO`; - [ ] `IODBDSSET`; - [ ] `IODBETP_ETB`; - [ ] `IODBETP_FTP`; - [ ] `IODBETP_HOST`; - [ ] `IODBETP_TCP`; - [ ] `IODBGNRL`; - [ ] `IODBHPAC`; - [ ] `IODBHPPR`; - [ ] `IODBHPST`; - [ ] `IODBIDINF`; - [ ] `IODBINDEADR`; - [ ] `IODBITEM`; - [ ] `IODBMLTTL`; - [ ] `IODBMR`; - [ ] `IODBMSTP`; - [ ] `IODBMTAP`; - [ ] `IODBOVL`; - [ ] `IODBPI`; - [ ] `IODBPMAINTE`; - [ ] `IODBPMC0`; - [ ] `IODBPMC1`; - [ ] `IODBPMC2`; - [ ] `IODBPMCCNTL`; - [ ] `IODBPMCEXT`; - [ ] `IODBPR`; - [ ] `IODBPRFADR`; - [ ] `IODBPRM`; - [ ] `IODBPRMNO`; - [x] `IODBPSD_1`; - [ ] `IODBPSD_2`; - [x] `IODBPSD_3`; - [ ] `IODBPSD_4`; - [ ] `IODBRDNA`; - [ ] `IODBRMTPRM`; - [ ] `IODBSAFE`; - [ ] `IODBSGNL`; - [ ] `IODBSIG`; - [ ] `IODBSIG2`; - [ ] `IODBSIG3`; - [ ] `IODBSIGAD`; - [ ] `IODBSLVADR`; - [ ] `IODBSLVID`; - [ ] `IODBSLVPRM`; - [ ] `IODBSLVPRM2`; - [ ] `IODBSLVPRM3`; - [ ] `IODBTD`; - [ ] `IODBTD2`; - [ ] `IODBTGI`; - [ ] `IODBTGI2`; - [ ] `IODBTGI3`; - [ ] `IODBTGI4`; - [ ] `IODBTIME`; - [ ] `IODBTLCTL`; - [ ] `IODBTLDT`; - [ ] `IODBTLGRP`; - [ ] `IODBTLMAG`; - [ ] `IODBTLMAG2`; - [ ] `IODBTLMNG`; - [ ] `IODBTLMNG_F2`; - [ ] `IODBTLMNG_F2_data`; - [ ] `IODBTLTOOL`; - [ ] `IODBTLZN`; - [ ] `IODBTO_1_1`; - [ ] `IODBTO_1_2`; - [ ] `IODBTO_1_3`; - [ ] `IODBTO_2`; - [ ] `IODBTO_3`; - [ ] `IODBTR`; - [ ] `IODBUNSOLIC`; - [ ] `IODBWAVE`; - [ ] `IODBWVPRM`; - [ ] `IODBZOFS`; - [ ] `IODBZOR`; - [ ] `ODB3DCD`; - [ ] `ODB3DHDL`; - [ ] `ODB3DPLS`; - [ ] `ODB3DTO`; - [ ] `ODB5AXMAN`; - [ ] `ODBACT`; - [ ] `ODBACT2`; - [ ] `ODBACTTLZN`; - [ ] `ODBAD`; - [ ] `ODBAHIS`; - [ ] `ODBAHIS2`; - [ ] `ODBAHIS3`; - [ ] `ODBAHIS5`; - [ ] `ODBALM`; - [ ] `ODBALMMSG`; - [ ] `ODBALMMSG2`; - [ ] `ODBAXDT`; - [ ] `ODBAXIS`; - [ ] `ODBAXISNAME`; - [ ] `ODBBRS`; - [ ] `ODBBUF`; - [ ] `ODBCAXIS`; - [ ] `ODBCMD`; - [ ] `ODBCSS`; - [ ] `ODBDATRNG`; - [ ] `ODBDGN_1`; - [ ] `ODBDGN_2`; - [ ] `ODBDGN_3`; - [ ] `ODBDGN_4`; - [ ] `ODBDIAGIF`; - [ ] `ODBDIAGNUM`; - [ ] `ODBDNCDGN`; - [ ] `ODBDSDIR`; - [ ] `ODBDSMNT`; - [ ] `ODBDY2_1`; - [ ] `ODBDY2_2`; - [ ] `ODBERR`; - [ ] `ODBETMSG`; - [ ] `ODBEXAXISNAME`; - [ ] `ODBEXEM`; - [ ] `ODBEXEPRG`; - [ ] `ODBEXGP`; - [ ] `ODBFINFO`; - [ ] `ODBFINFORM`; - [ ] `ODBFIX`; - [ ] `ODBGCD`; - [ ] `ODBHDDDIR`; - [ ] `ODBHDDINF`; - [ ] `ODBHIS`; - [ ] `ODBHND`; - [ ] `ODBHOSTDIR`; - [ ] `ODBLFNO`; - [ ] `ODBLOFS`; - [ ] `ODBM`; - [ ] `ODBMDIP`; - [ ] `ODBMDL_1`; - [ ] `ODBMDL_2`; - [ ] `ODBMDL_3`; - [ ] `ODBMDL_4`; - [ ] `ODBMDL_5`; - [ ] `ODBMGRP`; - [ ] `ODBMIR`; - [ ] `ODBMVINF`; - [ ] `ODBNC_1`; - [ ] `ODBNC_2`; - [ ] `ODBNODE`; - [ ] `ODBOPHIS4_1`; - [ ] `ODBOPHIS4_10`; - [ ] `ODBOPHIS4_11`; - [ ] `ODBOPHIS4_2`; - [ ] `ODBOPHIS4_3`; - [ ] `ODBOPHIS4_4`; - [ ] `ODBOPHIS4_5`; - [ ] `ODBOPHIS4_6`; - [ ] `ODBOPHIS4_7`; - [ ] `ODBOPHIS4_8`; - [ ] `ODBOPHIS4_9`; - [ ] `ODBPARAIF`; - [ ] `ODBPARANUM`; - [ ] `ODBPDFNFIL`; - [ ] `ODBPDFSDIR`; - [ ] `ODBPM`; - [ ] `ODBPMCADR`; - [ ] `ODBPMCALM`; - [ ] `ODBPMCERR`; - [ ] `ODBPMCINF`; - [ ] `ODBPMCTITLE`; - [ ] `ODBPMINF`; - [ ] `ODBPOFS`; - [ ] `ODBPOS`; - [ ] `ODBPRFCNF`; - [ ] `ODBPRO`; - [ ] `ODBPRS`; - [ ] `ODBPSER`; - [ ] `ODBPTIME`; - [ ] `ODBPTLINF`; - [ ] `ODBRMTDT`; - [ ] `ODBROFS`; - [ ] `ODBROT`; - [ ] `ODBRSTRM`; - [ ] `ODBSCL`; - [ ] `ODBSD`; - [ ] `ODBSEQ`; - [ ] `ODBSETIF`; - [ ] `ODBSETNUM`; - [ ] `ODBSINFO`; - [ ] `ODBSLVST`; - [ ] `ODBSPDI`; - [ ] `ODBSPDLNAME`; - [ ] `ODBSPDO`; - [ ] `ODBSPEED`; - [ ] `ODBSPLOAD`; - [ ] `ODBSPN`; - [ ] `ODBSRCSLYT`; - [ ] `ODBSRCSST`; - [ ] `ODBST`; - [ ] `ODBSVLOAD`; - [ ] `ODBSYS`; - [ ] `ODBSYSC`; - [ ] `ODBSYSEX`; - [ ] `ODBSYSH`; - [ ] `ODBSYSS3`; - [ ] `ODBTG`; - [ ] `ODBTLIFE1`; - [ ] `ODBTLIFE2`; - [ ] `ODBTLIFE3`; - [ ] `ODBTLIFE4`; - [ ] `ODBTLIFE5`; - [ ] `ODBTLINF`; - [ ] `ODBTLINF2`; - [ ] `ODBTLINFO`; - [ ] `ODBTLUSE`; - [ ] `ODBTOFS`; - [ ] `ODBUP`; - [ ] `ODBUP3`; - [ ] `ODBUSEGR`; - [ ] `ODBUSEGRP`; - [ ] `ODBWVDT`; - [ ] `OPMSG`; - [ ] `OPMSG2`; - [ ] `OPMSG3`; - [ ] `PRGDIR`; - [ ] `PRGDIRTM`; - [ ] `PRGPNT`; - [ ] `SRAMADDR`.