FanucAdapter¶
Introduction¶
FanucAdapter is an application that can be used to get data from Fanuc Series30 devices. It provides data readings from the connected Fanuc controller utilizing Focas½ library. It can serve multiple requests coming from multiple applications or threads.
FanucAdapter Details¶
FanucAdapter provides basically two types of data sources. First type is the memory address of a specific memory region. The allowed request format for this kind of data is given in the following table. It should be kept in mind that value_type is the enumerated values representing the type of the data. By utilizing this field, the reader side can perform the correct type-casting operation. A detailed explanation of memory reading functionality is provided in PMC read functionality usage
$DATASOURCE | Type | "value_type" |
---|---|---|
PMC/MEM/MEM_REGION/PARAMETER | unsigned char | 3 |
The second type is the predefined data sources made available through special focas library function calls. The list of the provided data sources is given in the following table:
# | $DATASOURCE | Type | "value_type" |
---|---|---|---|
1 | SYSTEM_INFO | string | 11 |
2 | RUN_STATUS | int | 6 |
3 | MOTION_STATUS | int | 6 |
4 | ALARM_STATUS | int | 6 |
5 | MACHINE_PART_COUNT | int | 6 |
6 | CYCLE_TIME_MIN | int | 6 |
7 | CYCLE_TIME_MSEC | int | 6 |
8 | ACT_FEED_RATE | double | 10 |
9 | ACT_SPINDLE | double | 10 |
10 | ABSOLUTE_AXIS_{x} | double | 10 |
11 | MACHINE_AXIS_{x} | double | 10 |
12 | RELATIVE_AXIS_{x} | double | 10 |
13 | DISTANCE_AXIS_{x} | double | 10 |
14 | SERVO_LOADMETER_{y} | double | 10 |
15 | SERVO_LOADPERCENTAGE_{y} | double | 10 |
16 | SERVO_LOADCURRENT_{y} | double | 10 |
17 | SPINDLE_LOADMETER_{z} | double | 10 |
18 | SPINDLE_MOTORSPEED_{z} | double | 10 |
19 | SPINDLE_SPEED_{z} | double | 10 |
20 | EXEC_PRG_NAME | string | 11 |
21 | TOOL_NUM | double | 10 |
22 | TOOL_GROUP_NUM | int | 6 |
23 | TOOL_USEORDER_NUM | int | 6 |
24 | ACT_TOOL_EDGE | double | 10 |
25 | CONVERTED_SPINDLE_SPEED | double | 10 |
26 | SPECIFIED_SURFACE_SPEED | double | 10 |
27 | CLAMP_MAX_SPINDLE_SPEED | double | 10 |
28 | PATH_NUMBER | int | 10 |
29 | PATH_NUMBER_MAX | int | 10 |
30 | MAINBOARD_ID | string | 11 |
31 | CPU_ID | string | 11 |
32 | SPINDLE_COUNT | int | 10 |
33 | SPINDLE_NAMES | string | 11 |
34 | TOOL_COUNT_CURR_GROUP | double | 10 |
35 | MODAL_DATA_M | double | 10 |
36 | MODAL_INFO_M | string | 11 |
37 | MODAL_DATA_S | double | 10 |
38 | MODAL_INFO_S | string | 11 |
39 | MODAL_DATA_T | double | 10 |
40 | MODAL_INFO_T | string | 11 |
41 | TOOL_TYPE_{t} | double | 10 |
42 | H_CODE_{t} | int | 6 |
43 | D_CODE_{t} | int | 6 |
44 | TOOL_EDGE_{t} | int | 6 |
45 | G_CODE_{t} | int | 6 |
46 | W_CODE_{t} | int | 6 |
47 | TOOL_GNO_{t} | int | 6 |
48 | TOOL_GRP_{t} | int | 6 |
49 | TOOL_RESERVED1_{t} | double | 10 |
50 | TOOL_RESERVED2_{t} | double | 10 |
51 | ACT_PRG_NUM | int | 6 |
52 | ACT_MAIN_PRG_NUM | int | 6 |
53 | AUT_STATUS | int | 6 |
54 | ALARM_LAST_MSG_{t} | string | 11 |
55 | ALARM_LAST_NUM_{t} | double | 10 |
Note-1: {x} is the axis number [1…MAX_AXIS] i.e. ABSOLUTE_AXIS_3
Note-2: {y} is the servo number [1…MAX_AXIS] i.e. SERVO_LOADMETER_2
Note-3: {z} is the spindle number [1…MAX_SPINDLE] i.e. SPINDLE_SPEED_1
Note-4: {t} is the tool number i.e. TOOL_TYPE_1
Description of Parameters¶
In this section, the pre-defined data sources are explained including their respective sample readings. Moreover, the corresponding focas library function name is provided for those demanding more information.
1. System Info¶
It returns the system info composed of model, version and max axis information of the system as follows;
31 M G41Z 32
Fanuc 31i-B has 32 supported axes. Please refer to cnc_sysinfo function of Focas Library.
2. Run Status¶
It returns the run status as one of the following options;
# | Status |
---|---|
0 | STOP |
1 | HOLD |
2 | START |
3 | MSTR(jog mdi) |
4 | RESTART(not blinking) |
5 | PRSR(program restart) |
6 | NSRC(sequence number search) |
7 | RESTART(blinking) |
8 | RESET |
9 | (Not used) |
10 | (Not used) |
11 | (Not used) |
12 | (Not used) |
13 | HPCC(during RISC operation) |
Please refer to cnc_statinfo function of Focas Library.
3. Motion Status¶
It returns the motion status as one of the following options;
# | Status |
---|---|
0 | * |
1 | MOTION |
2 | DWELL |
3 | WAIT (waiting:only TT) |
Please refer to cnc_statinfo function of Focas Library.
4. Alarm Status¶
It returns the alarm status of CNC. Please refer to cnc_alarm2 function of Focas Library.
5. Machine Part Count¶
It returns the number of current part in progress.
6. Cycle Time - Parameters 6 and 7¶
Has two parts: minute and millisecond [0…60000). Please refer to cnc_rdparam_ext function of Focas Library.
7. Dynamic Data - Parameters 8 to 13¶
Depending on the currently controlled axis count, those parameters return run-time values on request. The values are sampled together and it is beneficial to read them together. Please refer to cnc_rddynamic2 function of Focas Library.
8. Axis Data - Parameters 14 to 19¶
Depending on the currently controlled axis and spindle count, those parameters return run-time values on request. Please refer to cnc_rdaxisdata function of Focas Library.
9. Executed Program Name¶
Parameter 20 returns the name of the program being executed. "//CNC_MEM/USER/PATH1/SAMPLE"
is an example program name returned from the fanuc controller.
Tool Data 1 - Parameter 21 to 24¶
Returns the tool information of the current tool (number, group number, useorder number, edge number).
Speeds - Parameter 25 to 27¶
Returns the tool speed data (converted spindle speed, specified surface speed, maximum spindle speed).
Path Data - Parameter 28 and 29¶
PATH_NUMBER returns the current path the adapter is reading from. PATH_NUMBER_MAX returns the number of available (configured) paths.
Hardware Data - Parameter 30 and 31¶
Returns the hardware id for the requested source as string.
Spindle Data - Parameter 32 and 33¶
SPINDLE_COUNT returns the number of spindles for the requested path context. SPINDLE_NAMES returns the names of all spindles in the requested path context.
Tool count current Group - Parameter 34¶
Returns the amount of tools in the current tool group.
Modal Data - Parameter 35 to 40¶
Returns the given modal data. MODAL_DATA_M/S/T returns the last issued M/S/T-command MODAL_INFO_M/S/T returns additional information like "is positive", "is negative", "has decimal point", "no decimal point", "in present block", or "no present block".
Tool Data 2 - Parameter 41 to 50¶
Returns the requested number of tool management data beginning from the specified index. Example: TOOL_TYPE_2_C4 In this example, the tool type is read from tool 2 to 5. (4 values in total). Unlike the other parameters that can be read as an array, an index must always be specified for these data sources (TOOL_TYPE_1). The usage of (TOOL_TYPE) is not permitted and will lead to an error!
Reading all axis/servo/spindle data at once¶
In order to receive all the axes/spindle/servo data in one request, you should provide the data source string without the trailing underscore and axes/spindle/servo number. The following table shows the corresponding data sources;
# | $DATASOURCE | Type | "value_type" |
---|---|---|---|
1 | ABSOLUTE_AXIS | double | 10 |
2 | MACHINE_AXIS | double | 10 |
3 | RELATIVE_AXIS | double | 10 |
4 | DISTANCE_AXIS | double | 10 |
5 | SERVO_LOADMETER | double | 10 |
6 | SERVO_LOADPERCENTAGE | double | 10 |
7 | SERVO_LOADCURRENT | double | 10 |
8 | SPINDLE_LOADMETER | double | 10 |
9 | SPINDLE_MOTORSPEED | double | 10 |
10 | SPINDLE_SPEED | double | 10 |
For instance, if the controlled axis count is 3 and ABSOLUTE_AXIS is requested as the data source, the value in the response will be an array containing 3 different axis readings as ["123.456", "456.789", "789.123"]
.
Reading information from specific path¶
Some datasources return data in context of the CNC path. To specify the path context the path number can be added to the parameter as a prefix, separated by a vertical line, like "pathnumber|". Example: 1|ABSOLUT_AXIS_1 (this will return the absolute position of axis 1 from path 1). This functionality is supported both in the parameter service and subscription service.
Read data in a specific range¶
FanucAdapter allows to access slices of arrays to improve the performance of the data transmission. To use this feature the parameter request has to be extended by an index and a count, like this: TOOL_TYPE_5_C5. In this example, the slice will contain a value array starting at tool 5 and containing the 4 following tools. In the event that the number of data to read is greater than the number of actually existing data, the maximum number is read and returned. This method can be used for all parameters that are read as an array.
PMC read functionality usage¶
FanucAdapter provides PMC memory reading support in one of the formats below. Please refer to section PMC memory read for details.
Formats |
---|
PMC/MEM/MEM_REGION/PARAMETER |
PMC/MEM/MEM_REGION/PARAMETER.$BIT |
PMC/MEM/MEM_REGION/PARAMETER#$LENGTH |
Note-1: $MEM_REGION represents the memory region letters (A, B, C, D). Please refer to table below for details.
Note-2: $PARAMETER represents the parameter start address. Please refer to table below for details.
Note-3: $BIT represents the bit number (0..7) when boolean value is requested.
Note-4: $LENGTH represents the number of bytes requested.
The referenceable range of Series 0i-F, 30i/31i/32i/35i-B, PMi-A are given in the following table. It is important to declare that the content of the table is generated by referring the user manual handed over with focas library.
IDcode | Kind of PMC address | 1st to 5th path PMC | DSC PMC | |||
---|---|---|---|---|---|---|
$MEM_REGION | $PARAMETER | $PARAMETER | $PARAMETER | $PARAMETER | $PARAMETER | |
PMC Memory-A | PMC Memory-B | PMC Memory-C | PMC Memory-D | |||
0 | G (Output signal from PMC to CNC) | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 |
1 | F (Input signal to PMC from CNC) | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 1000-1767 2000-2767 3000-3767 4000-4767 5000-5767 6000-6767 7000-7767 8000-8767 9000-9767 | 0-767 |
2 | Y (Output signal from PMC to machine) | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 |
3 | X (Input signal to PMC from machine) | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 200-327 400-527 600-727 1000-1127 | 0-127 |
4 | A (Message display) *Display request | 0-249 | 0-249 | 0-499 | 0-749 | 0-249 |
A (Message displsy) Display status | 9000-9249 | 9000-9249 | 9000-9499 | 9000-9749 | 9000-9249 | |
5 | R (Internal relay) | 0-1499 | 0-7999 | 0-15999 | 0-59999 | 0-1499 |
R (System relay) | 9000-9499 | 9000-9499 | - | - | 9000-9499 | |
6 | T (Timer) *Variable timer | 0-79 | 0-499 | 0-999 | 0-999 | 0-79 |
T (Timer) *Variable timer precision | 9000-9079 | 9000-9499 | 9000-9999 | 9000-9999 | 9000-9079 | |
7 | K (Keep relay) *User range | 0-19 | 0-99 | 0-199 | 0-299 | 0-19 |
K (Keep relay) *System range | 900-999 | 900-999 | 900-999 | 900-999 | 900-999 | |
8 | C (Counter) *Changeable counter | 0-79 | 0-399 | 0-799 | 0-1199 | 0-79 |
C (Counter) *Fixed counter | 5000-5039 | 5000-5199 | 5000-5399 | 5000-5599 | 5000-5039 | |
9 | D (Data table) | 0-2999 | 0-9999 | 0-19999 | 0-59999 | 0-2999 |
10 | M (Input signal from other PMC path) | 0-767 | 0-767 | 0-767 | 0-767 | - |
11 | N (Output signal to other PMC path) | 0-767 | 0-767 | 0-767 | 0-767 | - |
12 | E (Extra relay) | 0-9999 | 0-9999 | 0-9999 | 0-9999 | - |
13 | Z (System relay) | - | - | 0-499 | 0-499 | - |
Client App Development Guide¶
Data Access Services¶
Subscriptionservice¶
With the subscription service, previously defined variables can be subscribed to and will be published continually. The available variables are listed in the table above. All subscribed variables are provided cyclically as a payload on the DataBus and can be read via "consumer". More information can be found in chapter subscription-service. The default publishing cycle is 100 ms. It can be adjusted in the specific config section of the metaconfig. Values >= 100 ms are allowed. If the supplied value is smaller than this, the default value will be used. "min": 100, "max": 2147483647, "default": 100
Example configuration of metaconfig for subscription service¶
In order to be able to use the subscription service, you must make the following settings in the Metaconfig of your app, in addition to the implementation in the code described in chapter [...].
"datasourceConfig": {
"requiredDatasource": [
{
"datasourceId": "FS30_NCU1",
"type": "FANUC",
"services": {
"subscription-service/v1":{
"subscriptions":[
{
"messageId":"fanuc_lf_data",
"messageName":"userdata",
"quality":"lf",
"datapoints":[
{
"address": "ALARM_STATUS"
},
{
"address": "ACT_FEED_RATE"
}
]
}
]
}
}
}
]
}
Parameterservice¶
With the prameter service, previously defined variables can be read by synchronous request/response communication. More information can be found in chapter parameter-serice
Example configuration of metaconfig for parameter service¶
The client application should be configured correctly. In the following code snippet, a minimal required data source configuration details are written for utilizing parameter service of FanucAdapter.
"datasourceConfig": {
"requiredDatasource": [
{
"datasourceId": "FS30_NCU1",
"type": "FANUC",
"services": {
"parameter-service/v1": {
"access": [
{
"accessType": "r",
"datapoints": [
{
"address": ""
}
]
}
]
}
}
}
]
}
Read Methods¶
Single parameter read¶
For requesting a single data source from the adapter, the following code snippet could be utilized. This is an example for parameter-service read. It is important to note that all the reader application codes are provided in C++ language. For other supported language examples, AppSDK documentation should be examined.
std::vector<std::string> dataSourceNames;
dsaapiNS::DataSourceAccess::GetDataSourceNames("FANUC", dataSourceNames);
std::shared_ptr<dsaapiNS::DataSource> ncu = nullptr;
dsaapiNS::DataSourceAccess::GetDataSource(dataSourceNames[0], ncu);
auto parameterServices = ncu->GetParameterServices();
auto paramDef = std::make_shared<dsaapiNS::ParameterDefinition>($DATASOURCE);
parameterServices[0]->ReadParameter(paramDef);
Note: For example $DATASOURCE is "ACT_FEED_RATE".
The result of the request including the data readings could be extracted by using the following code snippet.
auto pvo = paramDef->GetValueObject();
auto values = pvo.GetValues(); // Return std::vector<std::pair<std::string, int>>
std::string returnedValueAsString = values[0].first; // i.e. "-12.03"
int returnedValueType = values[0].second; // i.e. 10
Multi parameter read¶
For reading multi parameter, ReadParameters()
method should be called. For detailed information, please refer to the AppSDK documentation.
PMC memory read¶
Client app can read PMC memory via suppling following patterns for AppSDK ReadParameter function (Multi read ReadParameters is not supported for PMC read).
PMC/MEM/MEM_REGION/PARAMETER
This pattern reads $PARAMETER in the $MEM_REGION region one byte.
Examples:
PMC/MEM/R/1700 from R memory region.
PMC/MEM/D/1500 from D memory region.
Possible Return Values (in the same order above):
["FF"]
["7C"]
PMC/MEM/MEM_REGION/PARAMETER.$BIT
This pattern reads bit number $BIT from address $PARAMETER of the $MEM_REGION and returns.
Note: Valid range for $BIT is 0-7.
Examples:
PMC/MEM/R/1700.0 => Reads 0th bit of address 1700 from R memory region.
PMC/MEM/D/1500.7 => Reads 7th bit of address 1500 from D memory region.
Possible Return Values (in the same order above, single bit value only, LSb first, encoded as string):
["1"]
["0"]
PMC/MEM/MEM_REGION/PARAMETER#$LENGTH
This pattern reads $LENGTH number of bytes starting from address $PARAMETER of the $MEM_REGION and returns it in the format described below.
Examples:
PMC/MEM/R/1700#3 => Reads 1700, 1701, 1702 from R memory region.
PMC/MEM/D/1500#2 => Reads 1500, 1501 from D memory region.
Possible Return Values (in the same order above, LSB first):
["01", "AA", "3F"]
["E1", "24"]
All of these patterns return an object which contains return code and value object. Value object contains value type and value(s) as array of string.
The raw JSON object returned by the function call "ReadParameter" for "PMC/MEM/R/1700#4" address parameter is as follows:
{
"return_code": 0, /* 0:success, 1:error */
"return_value": {
"value_type": 3, /* 0:Invalid, 1:Bool, 3:Uchar, 6:Long, 10:Double, 11:String */
"value": ["FF", "AA", "01", "89"] /* return values are HEX as string.*/
}
}
Note-1: Comments are reference only, not valid JSON file.
Note-2: For further details about return codes and value types please refer the AppSDK documents.
For the example above, "value"
is a string array that contains "FF", "AA", "01", "89"
data. Field "value_type"
indicates the type of this hex values. For this request, it is received as 3 (UChar)
. So cast the data to individual unsigned bytes i.e. 0xFF
or cast to 0x8901AAFF
in order to use it as uint32_t
depending on the application needs.
The following C++ code snippet shows how to access individual values from AppSDK.
auto pvo = paramDef->GetValueObject();
auto values = pvo.GetValues(); // returns std::vector<std::pair<std::string, int>>
Developers check the type of return value and size then must cast the return values correspondingly. For example values[2] in the example above, is equal to "01" as string.
This function supports only PMC Memory-D as a PMC memory region. For valid range of $PARAMETER check related documents from Fanuc Focas Library. For example for R memory region valid range is 0-59999. Below table is a copy of this info from library documents.
Appendix¶
Configuration Details for FanucReader App¶
The following parts provide detailed information about the FanucReader client application that is available for installation on Insights Hub.
The provided example reader app polls hard-coded parameters in loop with 1 second intervals. To override the poll time interval (seconds), use the following setting (optional) in specificConfig
section of reader app meta config.
"specificConfig": {
"FanucPollTime": 0.5
}
Example reader app which is provided as demo kit, optionally reads FanucSingleReadParameters
and FanucMultiReadParameters
arrays written inside specificConfig
section of its meta config. If these arrays are provided, the reader app requests the parameters that are found in the arrays only, in a cyclic order, with FanucPollTime
intervals, instead of requesting the hard-coded parameters in its code. If you want to use default values which are hard-coded, these fields should be removed in the reader app meta config completely.
An example usage of the mentioned fields are shown below.
"specificConfig": {
"FanucSingleReadParameters": [
"PMC/MEM/R/1700",
"PMC/MEM/R/1700.3",
"PMC/MEM/R/1700.5",
"PMC/MEM/R/1700#3",
"SYSTEM_INFO",
"RUN_STATUS",
"EXEC_PRG_NAME",
"ALARM_STATUS",
"ACT_FEED_RATE",
"ACT_SPINDLE",
"ABSOLUTE_AXIS_1",
"ABSOLUTE_AXIS_2",
"ABSOLUTE_AXIS_3",
"MACHINE_AXIS_1",
"MACHINE_AXIS_2",
"MACHINE_AXIS_3",
"RELATIVE_AXIS_1",
"RELATIVE_AXIS_2",
"RELATIVE_AXIS_3",
"DISTANCE_AXIS_1",
"DISTANCE_AXIS_2",
"DISTANCE_AXIS_3",
"SERVO_LOADMETER_1",
"SERVO_LOADMETER_2",
"SERVO_LOADMETER_3",
"SERVO_LOADPERCENTAGE_1",
"SERVO_LOADPERCENTAGE_2",
"SERVO_LOADPERCENTAGE_3",
"SERVO_LOADCURRENT_1",
"SERVO_LOADCURRENT_2",
"SERVO_LOADCURRENT_3",
"SPINDLE_LOADMETER_1",
"SPINDLE_MOTORSPEED_1",
"SPINDLE_SPEED_1",
"MACHINE_PART_COUNT",
"CYCLE_TIME_MIN",
"CYCLE_TIME_MSEC"
],
"FanucMultiReadParameters": [
"PMC/MEM/R/1700",
"PMC/MEM/R/1700.3",
"PMC/MEM/R/1700.5",
"PMC/MEM/R/1700#3",
"SYSTEM_INFO",
"RUN_STATUS",
"EXEC_PRG_NAME",
"ALARM_STATUS",
"ACT_FEED_RATE",
"ACT_SPINDLE",
"ABSOLUTE_AXIS_1",
"ABSOLUTE_AXIS_2",
"ABSOLUTE_AXIS_3",
"MACHINE_AXIS_1",
"MACHINE_AXIS_2",
"MACHINE_AXIS_3",
"RELATIVE_AXIS_1",
"RELATIVE_AXIS_2",
"RELATIVE_AXIS_3",
"DISTANCE_AXIS_1",
"DISTANCE_AXIS_2",
"DISTANCE_AXIS_3",
"SERVO_LOADMETER_1",
"SERVO_LOADMETER_2",
"SERVO_LOADMETER_3",
"SERVO_LOADPERCENTAGE_1",
"SERVO_LOADPERCENTAGE_2",
"SERVO_LOADPERCENTAGE_3",
"SERVO_LOADCURRENT_1",
"SERVO_LOADCURRENT_2",
"SERVO_LOADCURRENT_3",
"SPINDLE_LOADMETER_1",
"SPINDLE_MOTORSPEED_1",
"SPINDLE_SPEED_1",
"MACHINE_PART_COUNT",
"CYCLE_TIME_MIN",
"CYCLE_TIME_MSEC"
]
}
For instance, to request only ACT_SPINDLE with 0.5 second intervals, use the following JSON content with the sample reader app.
"specificConfig": {
"FanucPollTime": 0.5,
"FanucSingleReadParameters": ["ACT_SPINDLE"],
"FanucMultiReadParameters": []
}
Example Apps¶
This chapter is designed as a guide for developing a reader application that is compatible with AppSDK. Even though examples are in C++, notice that there are other available language options. Please refer to AppSDK documentation for further details.
Using subscriptionservice¶
Sample metaconfig¶
{
"databusConfig": {
"permissions":[
{
"source": "fanuc_lf_data",
"quality": "quality_all",
"permission": "read"
}
],
"credentials":{
"username":"",
"password":""
}
},
"datasourceConfig": {
"requiredDatasource": [
{
"datasourceId": "FS30_NCU1",
"type": "FANUC",
"services": {
"subscription-service/v1":{
"subscriptions":[
{
"messageId":"fanuc_lf_data",
"messageName":"userdata",
"quality":"lf",
"datapoints":[
{
"address": "ALARM_STATUS"
},
{
"address": "ABSOLUTE_AXIS_1"
},
{
"address": "MAINBOARD_ID"
},
{
"address": "PATH_NUMBER"
},
{
"address": "2|PATH_NUMBER"
},
{
"address": "PATH_NUMBER_MAX"
}
]
}
]
}
}
}
]
}
}
Sample programm¶
#include "EdgeAPI.h"
#include "Logging.h"
#include "EdgeStatus.h"
#include "Databus.h"
int main()
{
// inititalize Edge API
app_sdk::edge_api::Initialize();
// Create logger instance name has to by unique
auto logger = app_sdk::log_api::CreateLoggerInstance("fanucsubscriptionconsumer");
logger->AddAppender(app_sdk::log_api::LoggerAppenderType::CONSOLE);
// Get databus instance
sinumerik_edge::databus::DataBus &bus = sinumerik_edge::databus::DataBus::getInstance();
logger->Error(std::to_string(bus.getDataBusState()));
// Create a list of message ID's for consumer
// This is according to messageName in metaconfig or appconfig in section subscription-service/v1
std::vector<std::string> consumerIdList = {"userdata"};
// Creating the consumer and register it to the databus.
sinumerik_edge::databus::Consumer consumer(consumerIdList);
sinumerik_edge::databus::Status status;
status = bus.registerConsumer(consumer);
// Check if consumer is registered succsessfully
if(status != sinumerik_edge::databus::Status_OK)
{
logger->Error("Failed to register consumer");
exit(1);
}
else
{
logger->Info("Registered consumer");
}
// Trying to get results
// loops through as long as consumer works as expected
logger->Info("Trying to get results!");
sinumerik_edge::databus::MessageStruct result;
do
{
// Get data from consumer
result = consumer.pop();
// Check if data read was successful
logger->Info("Result State: " + std::to_string(result.getStatus()));
// Print result
logger->Info("POP RESULT: " + result.getMessageId() + "," + result.getPayload());
} while(result.getStatus() == sinumerik_edge::databus::Status_OK);
return 0;
}
Note: "userdata" added to "consumerIdList" is related to "messageName":"userdata" in metaconfig.
This is the output generated by the sample app:
POP RESULT: userdata,
{
"header" : {
"body" : {
"datapoint" : [
{
"address" : "ALARM_STATUS",
"content" : {
"value" : ["0"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.860295"
},
{
"address" : "ABSOLUTE_AXIS_1",
"content" : {
"value" : ["0"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.860295"
},
{
"address" : "MAINBOARD_ID",
"content" : {
"value" : ["Group: 256 HWID: 256 ID1: 0033c400 ID2: 00000000"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.866075"
},
{
"address" : "PATH_NUMBER",
"content" : {
"value" : ["1"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.858684"
},
{
"address" : "PATH_NUMBER_MAX",
"content" : {
"value" : ["2"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.858684"
},
{
"address" : "2|PATH_NUMBER",
"content" : {
"value" : ["2"]
},
"period_ms" : -1,
"quality_mode" : "lf",
"timestamp" : "2021-06-22 13:33:32.884626"
}
]
},
"key" : "dataobject",
"message_type" : "dataobject",
"source_id" : "fanuc_adapter"
}
}
Using parameterservice¶
Note-1: The below code sample ignores most of the error and exception handling for simplicity.
Note-2: The metaconfig for paramter-service is not parameter dependent, the example prameter-service configuration above can be used.
//////////////////////////////////////////////////////////////////////////////////////////
///
/// @brief FanucReader Client to test FanucAdapter
/// @file fanucreader.cpp
/// @date 2020
/// @copyright Copyright (c) Siemens AG 2020 All Rights Reserved.
///
//////////////////////////////////////////////////////////////////////////////////////////
#include "Databus.h"
#include "EdgeAPI.h"
#include "EdgeStatus.h"
#include "Logging.h"
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
#include <chrono>
#include <vector>
using namespace std;
// Abbreviations for namespaces
namespace edgeapiNS = app_sdk::edge_api;
namespace dsaapiNS = app_sdk::dsa_api;
std::string getTypeAsString(const int &valueType) {
static const std::vector<std::string> typeNames = {
"invalid",
"Bool",
"Char",
"UChar",
"Int",
"UInt",
"Long",
"ULong",
"LongLong",
"ULongLong",
"Double",
"String",
"ValueArray",
"DateTime",
};
return typeNames[valueType];
}
void PrintResponse(std::vector<std::shared_ptr<dsaapiNS::ParameterDefinition>>, std::shared_ptr<app_sdk::log_api::Logger>);
void PrintResponse(std::shared_ptr<dsaapiNS::ParameterDefinition>, std::shared_ptr<app_sdk::log_api::Logger>);
int main() {
// Initialize EdgeAPI for logger with config
edgeapiNS::Initialize();
auto logger = app_sdk::log_api::CreateLoggerInstance("fanucreaderapp");
logger->AddAppender(app_sdk::log_api::LoggerAppenderType::JOURNAL);
// Below is parameter services common
dsaapiNS::DataSourceAccess::Initialize();
// Below is Fanuc datasource list to be tested
std::vector<std::string> parametersForSingleRead = {
"ACT_FEED_RATE",
"ACT_SPINDLE",
"ABSOLUTE_AXIS",
"PMC/MEM/R/1700#2",
"MACHINE_PART_COUNT",
"CYCLE_TIME_MIN",
"CYCLE_TIME_MSEC",
"EXEC_PROG_NAME",
};
// Define a parameter vector to be used for Multi Read call of AppSDK
std::vector<std::string> parametersForMultiRead = parametersForSingleRead;
auto singleParameterCount = parametersForSingleRead.size();
// Default polling interval.
double pollingInterval = 1.00;
auto ret = edgeapiNS::GetAppSpecificConfigSection("/FanucPollTime");
if (ret.first.Success()) {
pollingInterval = std::stod(ret.second); // Can throw exception.
}
// Using AppSDK get data source section of run time config of this app
// First parameter is type of data source.
std::vector<std::string> dataSourceNames;
dsaapiNS::DataSourceAccess::GetDataSourceNames("FANUC", dataSourceNames);
auto defaultDataSource = dataSourceNames[0];
logger->Info("FANUC Data source name:" + defaultDataSource);
// Obtain the ncu object to issue the requests.
std::shared_ptr<dsaapiNS::DataSource> ncu = nullptr;
dsaapiNS::DataSourceAccess::GetDataSource(defaultDataSource, ncu);
// Using datasource ncu obtain parameter services which will communicate through adapterframework.
auto parameterServices = ncu->GetParameterServices();
// Get the first parameter service, others maybe reserved for future usage.
auto paramSVC = parameterServices[0];
logger->Info("FANUC Parameter service name is:" + paramSVC->GetName());
// Create empty vector of parameter defitinion objects
std::vector<std::shared_ptr<app_sdk::dsa_api::ParameterDefinition>> multiParamDefs{};
// Filling the multiParamDefs vector.
for (const auto ¶meterName : parametersForMultiRead) {
auto paramDef = std::make_shared<dsaapiNS::ParameterDefinition>(parameterName);
multiParamDefs.push_back(paramDef);
}
// The request number.
size_t requestIndex = 0;
// loop contains both single and multi parameter read in the order
while (true) {
// Single Parameters
if(requestIndex < singleParameterCount) {
// Create parameter definition object with its address. (supplied by dataTypes)
auto paramDef = std::make_shared<dsaapiNS::ParameterDefinition>(parametersForSingleRead[requestIndex]);
// Try to read parameter with service and parameter definition.
logger->Info("------------ Single Read " + std::to_string(requestIndex) + " ------------");
auto res = paramSVC->ReadParameter(paramDef);
if (res.Success()) {
// Print the result.
PrintResponse(paramDef, logger);
} else {
// Print error code and message
logger->Info("FANUC ReadParameter Error-" + std::to_string(res.GetCode()) + ": " + res.GetMessage());
}
// Advance the index.
++requestIndex;
}
// Multi Parameters
else {
// Try to read parameter with service and parameter definition.
auto res = paramSVC->ReadParameters(multiParamDefs);
logger->Info("------------ Multi Read ------------");
if (res.Success()) {
// Print all results.
PrintResponse(multiParamDefs, logger);
} else {
// Print error code and message
logger->Info("FANUC ReadParameters Error-" + std::to_string(res.GetCode()) + ": " + res.GetMessage());
}
// Reset the index.
requestIndex = 0;
}
// Some arbitrary delay for fun.
std::this_thread::sleep_for(std::chrono::duration<double>(pollingInterval));
}
// Should not reach here.
return EXIT_FAILURE;
}
void PrintResponse(std::vector<std::shared_ptr<dsaapiNS::ParameterDefinition>> response,
std::shared_ptr<app_sdk::log_api::Logger> logger) {
for (size_t i = 0; i < response.size(); ++i) {
auto& paramDef = response[i];
auto pvo = paramDef->GetValueObject();
auto values = pvo.GetValues();
logger->Info("Parameter: " + paramDef->GetParamName());
if(!values.empty()) {
logger->Info(" value_type: " + getTypeAsString(values[0].second));
}
// Loop through all values
for (const auto &val : values) {
logger->Info(" value: " + val.first);
}
}
}
void PrintResponse(std::shared_ptr<dsaapiNS::ParameterDefinition> response,
std::shared_ptr<app_sdk::log_api::Logger> logger) {
std::vector<std::shared_ptr<dsaapiNS::ParameterDefinition>> responseVector = { response };
PrintResponse(responseVector, logger);
}
Below is an example output of the code above, working in parallel with FanucAdapter.
------------ Single Read 0 ------------
Parameter: ACT_FEED_RATE
value_type: Double
value: 0
------------ Single Read 1 ------------
Parameter: ACT_SPINDLE
value_type: Double
value: 1001
------------ Single Read 2 ------------
Parameter: ABSOLUTE_AXIS
value_type: Double
value: -40.969
value: -0.468
value: -102.863
------------ Single Read 3 ------------
Parameter: PMC/MEM/R/1700#2
value_type: UChar
value: 25
value: 28
------------ Single Read 4 ------------
Parameter: MACHINE_PART_COUNT
value_type: Long
value: 3
------------ Single Read 5 ------------
Parameter: CYCLE_TIME_MIN
value_type: Long
value: 9023
------------ Single Read 6 ------------
Parameter: CYCLE_TIME_MSEC
value_type: Long
value: 11952
------------ Single Read 7 ------------
Parameter: EXEC_PRG_NAME
value_type: String
value: //CNC_MEM/USER/PATH1/SAMPLE
------------ Multi Read ------------
Parameter: ACT_FEED_RATE
value_type: Double
value: 0
Parameter: ACT_SPINDLE
value_type: Double
value: 1001
Parameter: ABSOLUTE_AXIS
value_type: Double
value: -40.969
value: -0.468
value: -102.863
Parameter: PMC/MEM/R/1700#2
value_type: UChar
value: 25
value: 28
Parameter: MACHINE_PART_COUNT
value_type: Long
value: 3
Parameter: CYCLE_TIME_MIN
value_type: Long
value: 9023
Parameter: CYCLE_TIME_MSEC
value_type: Long
value: 11952
Parameter: EXEC_PRG_NAME
value_type: String
value: //CNC_MEM/USER/PATH1/SAMPLE
Reference¶
For all references above, see Fanuc Focas ½ Library version 4.15 documentation
Also see:
Any questions left?
Except where otherwise noted, content on this site is licensed under the The Siemens Inner Source License - 1.1.