Difference between revisions of "KMAPI"
(→Advanced asynchronous message handling) |
(BackToTop button) |
||
(48 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | =Overview= | + | {{Languages|KMAPI}} |
+ | <div id="BackToTop" class="noprint" style="background-color:; position:fixed; bottom:32px; left:95%; z-index:9999; padding:0; margin:0;"> | ||
+ | <span style="color:blue; font-size:8pt; font-face:verdana,sans-serif; border:0.2em outset:#ceebf7; padding:0.1em; font-weight:bolder; -moz-border-radius:8px; "> | ||
+ | [[Image:TOP2.png|50px|link=#top]] </span></div> | ||
+ | |||
+ | =Overview= | ||
The KMAPI software package allows you to communicate with softMC from popular programming languages, such as Visual Basic over TCP/IP and UDP. The KMAPI provides complete access to the command line interface of your system across a TCP/IP connection. Fast access to frequently changing data, such as axis set-points and feedback, is provided via a UDP connection, also called UDP fast data. | The KMAPI software package allows you to communicate with softMC from popular programming languages, such as Visual Basic over TCP/IP and UDP. The KMAPI provides complete access to the command line interface of your system across a TCP/IP connection. Fast access to frequently changing data, such as axis set-points and feedback, is provided via a UDP connection, also called UDP fast data. | ||
+ | You can find the full KMAPI documentation [[:file: APIRef5.pdf|here]]. | ||
+ | |||
==Introduction== | ==Introduction== | ||
− | The KMAPI addresses several concerns when interfacing your program with | + | The KMAPI addresses several concerns when interfacing your program with KMAPI drives and controllers, including: |
− | |||
* sending commands (and receiving responses) | * sending commands (and receiving responses) | ||
* reading and setting amplifier or controller variables | * reading and setting amplifier or controller variables | ||
Line 20: | Line 26: | ||
Most KMAPI functions return an error code which indicates the success of the action requested by the programmer. Full text descriptions of the error are often associated with the error and can be accessed via KMAPI calls. | Most KMAPI functions return an error code which indicates the success of the action requested by the programmer. Full text descriptions of the error are often associated with the error and can be accessed via KMAPI calls. | ||
+ | ==Getting started== | ||
+ | The following C# code is a minimal console application which performs the following tasks: | ||
+ | * Initialize the library | ||
+ | * Create 'controller' - the software component used for communication | ||
+ | * send a command and read the response | ||
+ | * shut down the communication | ||
+ | |||
+ | The software is written in C# and uses the KMAPI.DLL to comunicate with the KMTCPIP.EXE communication server, an equivalent C++/C program will look pretty much the same but will have to use the KMAPI32.DLL. | ||
+ | |||
+ | Note: to use this: | ||
+ | # Add a reference to kmapi.dll to your project | ||
+ | # argument 1 should be of the form: "'''IP:10.4.20.55,5004'''" - 'IP:' as is, the IP address set to your mc, port can be 5001/4/ | ||
+ | # argument 2 is an MC command, try first with a simple command like "?ver" | ||
+ | |||
+ | <pre style="white-space:pre-wrap; width:50%; border:1px solid lightgrey; "> | ||
+ | using System; | ||
+ | using System.Collections.Generic; | ||
+ | using System.Linq; | ||
+ | using System.Text; | ||
+ | using System.Threading.Tasks; | ||
+ | |||
+ | namespace KMAPIDemo { | ||
+ | class Program { | ||
+ | private static IntPtr device = IntPtr.Zero; | ||
+ | |||
+ | static void Main(string[] args) { | ||
+ | if (args.Length != 2) | ||
+ | return; | ||
+ | string ipAddress = args[0]; | ||
+ | string cmdToExecute = args[1]; | ||
+ | // ******************************* | ||
+ | // *** initialize and connect *** | ||
+ | // ******************************* | ||
+ | int retVal = KMAPI.IKMInitialize(); // Initialize the API | ||
+ | if (retVal != 0) {// if fail | ||
+ | Console.WriteLine(string.Format("Error: Connection error (IKMInitialize): {0}", retVal)); | ||
+ | return; // fail | ||
+ | } | ||
+ | uint connectionType = 7; // COMM_TCPIP_DEDICATED = 7 - dedicated device => pre defined ip address | ||
+ | try { | ||
+ | device = KMAPI.IKMCreateController(KMAPI.PROD_GPMAC, | ||
+ | "someName", // dummy | ||
+ | connectionType, | ||
+ | 1, | ||
+ | ipAddress); | ||
+ | } catch (Exception e) { | ||
+ | KMAPI.IKMTerminate(); | ||
+ | Console.WriteLine(string.Format("Error: Connection error (IKMCreateController): {0}", e.Message)); | ||
+ | return; | ||
+ | } | ||
+ | if (device == IntPtr.Zero) { // if fail | ||
+ | KMAPI.IKMTerminate(); | ||
+ | Console.WriteLine("Error: Connection error (IKMCreateController): device = 0"); | ||
+ | return; | ||
+ | } | ||
+ | // ******************************* | ||
+ | // *** Execute some commands *** | ||
+ | // ******************************* | ||
+ | const int BuffSz = 100000; | ||
+ | char[] responseBuff = new char[BuffSz]; | ||
+ | retVal = KMAPI.IKMExecuteCmdResponse(device, cmdToExecute, responseBuff, BuffSz); | ||
+ | if (retVal != 0) // fail | ||
+ | Console.WriteLine("failed"); | ||
+ | else { | ||
+ | string response = new string(responseBuff); | ||
+ | int idx0 = response.IndexOf("\0"); | ||
+ | if (idx0 > 0) | ||
+ | response = response.Substring(0, idx0); | ||
+ | Console.WriteLine(string.Format("Command '{0}' => response '{1}'", cmdToExecute, response)); | ||
+ | } | ||
+ | // ***************** | ||
+ | // *** shut down *** | ||
+ | // ***************** | ||
+ | retVal = KMAPI.IKMDestroyDevice(device); // terminate KMAPI | ||
+ | if (retVal != 0) { // if fail | ||
+ | Console.WriteLine("Error when destroying device"); | ||
+ | return; // fail | ||
+ | } | ||
+ | device = IntPtr.Zero; | ||
+ | retVal = KMAPI.IKMTerminate(); | ||
+ | if (retVal != 0) { // if fail | ||
+ | Console.WriteLine("Error when terminating"); | ||
+ | return; // fail | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | <!-- | ||
==Initialization== | ==Initialization== | ||
Line 25: | Line 122: | ||
This ensures that the information which the KMAPI maintains internally about your application is correct.<br> | This ensures that the information which the KMAPI maintains internally about your application is correct.<br> | ||
No other KMAPI calls should be made before the KMAPI is initialized. | No other KMAPI calls should be made before the KMAPI is initialized. | ||
+ | --> | ||
==Error Messages== | ==Error Messages== | ||
Line 62: | Line 160: | ||
=Library Reference= | =Library Reference= | ||
+ | ==KMAPI Initialization== | ||
===KMInitialize=== | ===KMInitialize=== | ||
+ | |||
+ | |||
+ | Prepares the KMAPI for use: | ||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | !width = "80" align =left |C/C++ | ||
+ | !width = "250" align =left|'''KMErrorCode KMInitialize ( void )''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic | ||
+ | |'''KMInitialize() As Long''' | ||
+ | |- | ||
+ | |C# | ||
+ | |'''System.Int32 IKMInitialize ()''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |'''Return Value''' | ||
+ | |KM_ERR_OK if KMAPI is successfully initialized. KM_ERR_WINDOWS_API if the asynchronous message window can’t be created. <br> KM_ERR_MEM_LOCK if the application context was not successfully created. | ||
+ | |- | ||
+ | |'''Remarks''' ||The KMInitialize function must be called before any other KMAPI functions are called. | ||
+ | |- | ||
+ | |'''See Also''' || KMTerminate | ||
+ | |- | ||
+ | |'''Example'''|| See Example #1 | ||
+ | |} | ||
+ | |||
===KMTerminate=== | ===KMTerminate=== | ||
+ | |||
+ | Performs KMAPI cleanup required for proper application termination. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | !width = "80" align =left |C/C++ | ||
+ | !width = "250" align =left|'''KMErrorCode KMTerminate ( void )''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic | ||
+ | |'''KMTerminate() As Long''' | ||
+ | |- | ||
+ | |C# | ||
+ | |'''IKMInitialize ()''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |'''Return Value''' | ||
+ | |KM_ERR_OK if KMAPI is successfully terminated. KM_ERR_MEM_LOCK if the application context cannot be locked or removed. <br> KM_ERR_NO_CONTEXT if the application context cannot be found in the application context registry. | ||
+ | |- | ||
+ | |'''Remarks''' ||The KMTerminate function must be called before the application using the KMAPI terminates. | ||
+ | |- | ||
+ | |'''See Also''' || KMInitialize | ||
+ | |- | ||
+ | |'''Example'''|| See Example #1 | ||
+ | |} | ||
+ | |||
+ | ==Device Management== | ||
===KMCreateController=== | ===KMCreateController=== | ||
+ | |||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | !width = "80" align =left |C/C++ | ||
+ | !width = "600" align =left|'''KMDevice KMCreateController (KMProductType controllerProduct, LPSTR controllerName, KMCommType controllerCommType, short controllerID, LPSTR commOptions)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic | ||
+ | |'''KMCreateController (ByVal controllerProduct As Integer, ByVal controllerName$, ByVal controllerCommType As Integer, ByVal controllerID As Integer, ByVal commOptions$) As Long''' | ||
+ | |- | ||
+ | |C# | ||
+ | |'''System.IntPtr IKMCreateController (System.UInt32 controllerProduct, System.String controllerName, System.UInt32 controllerCommType, System.UInt32 controllerID, System.String commOptions)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''controllerProduct'' ||Type of controller to create | ||
+ | |- | ||
+ | |''controllerName'' || String name for the controller | ||
+ | |- | ||
+ | |''controllerCommType'' ||How the API should communicate with the controller (see communication type description) | ||
+ | |- | ||
+ | |''controllerID'' || What the controller’s address is | ||
+ | |- | ||
+ | |commOptions || COM port used by the controller | ||
+ | |- | ||
+ | |||
+ | |'''Return Value''' | ||
+ | |A handle referring to the controller. | ||
+ | |- | ||
+ | |'''Remarks''' ||See product type description for ''controllerProduct''. <br> ''controllerName'' is provided for user convenience and is not used internally by the KMAPI. <br> See communication type description for ''controllerCommType''. <br> ''commOptions'' is a general parameter that is intended for many uses. Presently, only connections of type COMM_TCPIP use this parameter. If COMM_TCPIP is selected then the ''commOptions'' parameter allows the user to specify what controller to connect to by IP address, controller name, serial number or DIP switch setting. <br> The format for ''commOptions'' is as follows: <br> | ||
+ | * “IP: xx.xx.xx.xx” where xx.xx.xx.xx is an IP address (e.g. “192.10.34.6”). | ||
+ | * “NM: yyyyy” where yyyyy is a name assigned by the user to the Sys.Name property of the controller. | ||
+ | * “SN: XXXXX-XXX” where XXXXX-XXX is the serial number assigned to the controller at the factory and printed on the model number label. | ||
+ | * “DP: XXXXXX” where XXXXXX is the value (in decimal) of the DIP switch setting on controllers that support. This is useful for user configuration of addresses. | ||
+ | When connecting via serial the IP address should is always be specified as 91.0.0.2. <br> If ''commOptions'' is not used, the parameter should be an empty string (“”). <br> '''KMCreateController''' allocates memory on behalf of the user. This memory must be freed before program termination via '''KMDestroyDevice'''. <br> The range for ''controllerDevice'' is 1 - 9. | ||
+ | |- | ||
+ | |'''See Also''' || ____ | ||
+ | |- | ||
+ | |'''Example'''|| See Example #1 | ||
+ | |} | ||
+ | |||
+ | ==Device Access== | ||
===KMExecuteCmd=== | ===KMExecuteCmd=== | ||
+ | |||
+ | |||
+ | Sends a command to a device. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMExecuteCmd (KMDevice device, LPSTR cmdStr)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMExecuteCmd (ByVal device As Long, ByVal cmdStr$) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMExecuteCmd (System.IntPtr device , System.String cmdStr)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''device'' || Handle for the device the command is being sent to. | ||
+ | |- | ||
+ | |''cndStr || The command to send. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||Sends the command ''cmdStr'' unmodified to the device specified by ''device''. Should be used with commands that do not have responses. | ||
+ | |- | ||
+ | |'''See Also''' || KMExecuteCmdResponse | ||
+ | |- | ||
+ | |'''Example'''|| See Example #1 | ||
+ | |} | ||
+ | |||
===KMExecuteCmdResponse=== | ===KMExecuteCmdResponse=== | ||
+ | |||
+ | |||
+ | Sends a command to a device and waits for a response. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMExecuteCmdResponse (KMDevice device, LPSTR cmdStr, LPSTR outStr, DWORD outSize)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMExecuteCmdResponse (ByVal device As Long, ByVal cmdStr$, ByVal outStr$, ByVal outSize As Long) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMExecuteCmdResponse (System.IntPtr device , System.String cmdStr , char[] outStr , System.UInt32 outSize)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''device'' || Handle for the device the command is being sent to. | ||
+ | |- | ||
+ | |''cndStr || The command to send. | ||
+ | |- | ||
+ | |''outStr'' || A buffer for the response. | ||
+ | |- | ||
+ | |''outSize'' || Size of the outStr buffer. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||Sends the command ''cmdStr'' unmodified to the device specified by ''device''. Should be used with commands that have responses. | ||
+ | |- | ||
+ | |'''See Also''' || KMExecuteCmd | ||
+ | |- | ||
+ | |'''Example'''|| See Example #1 | ||
+ | |} | ||
+ | |||
===Example #1=== | ===Example #1=== | ||
+ | |||
+ | This program shows how to initialize the KMAPI, create devices and access variables on each of the devices. | ||
+ | |||
+ | <big><big>'''C/C++'''</big></big> <br> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | /* Declare device handle */ | ||
+ | KMDevice devController; | ||
+ | KMDevice axisA1; | ||
+ | |||
+ | /* Declare variables */ | ||
+ | long valueL; | ||
+ | double valueD; | ||
+ | char valueS [100]; | ||
+ | |||
+ | /* Initialize the API */ | ||
+ | KMInitialize(); | ||
+ | |||
+ | /* Create a controller */ | ||
+ | devController - KMCreateController (PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); | ||
+ | |||
+ | /* Create axes */ | ||
+ | axisA1 - KMCreateSercosAxis ( PROD_SERVOSTAR, "A1", devController); | ||
+ | |||
+ | /* Move A1 */ | ||
+ | KMExecuteCmd ( devController, "MOVE A1 100"); | ||
+ | |||
+ | /* Get variables */ | ||
+ | KMVariableControllerGetLongValue (axisA1, "VCRUISE", &valueL); | ||
+ | KMVariableControllerGetDblValue (axisA1, "PFINAL", &valueD); | ||
+ | KMVariableControllerGetStringValue (axisA1, "AMAX", valueS, sizeof (valueS)); | ||
+ | |||
+ | /* Set variables */ | ||
+ | KMVariableControllerSetLongValue (axisA1, "VCRUISE", valueL); | ||
+ | KMVariableControllerSetDblValue (axisA1, "PFINAL", valueD); | ||
+ | KMVariableControllerGetStringValue (axisA1, "AMAX", valueS); | ||
+ | |||
+ | /* Destroy device table entries */ | ||
+ | KMDestroyDevice (axisA1); | ||
+ | KMDestroyDevice (devController); | ||
+ | |||
+ | /* Terminate the API */ | ||
+ | KMTerminate(); | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | |||
+ | |||
+ | <big><big>'''Visual Basic'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | 'Declare device handles | ||
+ | Dim devcontroller As Long | ||
+ | Dim axisA1 As Long | ||
+ | |||
+ | 'Declare variables | ||
+ | Dim valueL As Long | ||
+ | Dim valueD as Double | ||
+ | Dim errorL As Long | ||
+ | |||
+ | 'Initialize the API | ||
+ | errorL - KMInitialize() | ||
+ | |||
+ | 'Create a controller | ||
+ | devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") | ||
+ | |||
+ | 'Create axes | ||
+ | axisA1 - KMCreateSercosAxis( PROD_SERVOSTAR, "A1", devController) | ||
+ | |||
+ | 'Move A1 | ||
+ | errorL - KMExecuteCmd( devController, "MOVE A1 100"); | ||
+ | |||
+ | 'Get variables | ||
+ | errorL - KMVariablesControllerGetLongValue(axisA1, "VCRUISE", valueL) | ||
+ | errorL - KMVariablesControllerGetDblValue(axisA1, "PFINAL", valueD) | ||
+ | errorL - KMVariablesControllerGetStringValue(axisA1, "AMAX", valueS, Length(valueS)) | ||
+ | |||
+ | 'Set variables | ||
+ | errorL - KMVariablesControllerSetLongValue(axisA1, "VCRUISE", valueL) | ||
+ | errorL - KMVariablesControllerSetDblValue(axisA1, "PFINAL", valueD) | ||
+ | errorL - KMVariablesControllerSetStringValue(axisA1, "AMAX", valueS) | ||
+ | |||
+ | 'Destroy device table entries | ||
+ | errorL- KMDesroyDevice(axisA1) | ||
+ | errorL- KMDesroyDevice(devController) | ||
+ | |||
+ | 'Terminate the API | ||
+ | errorL - KMTerminate() | ||
+ | </pre> | ||
+ | |||
+ | |||
===KMGetFile=== | ===KMGetFile=== | ||
+ | |||
+ | |||
+ | Retrieve a file from a device. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMGetFile (KMDevice device, LPSTR cmdStr, LPSTR filename)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMGetFile (ByVal device As Long, ByVal cmdStr$, ByVal filename$) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMGetFile (System.IntPtr device, System.String cmdStr, System.String fileName)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''device'' || Handle for the device the file is being retrieved from. | ||
+ | |- | ||
+ | |''cmdStr'' || The command string to cause the device to send a file. | ||
+ | |- | ||
+ | |''filename'' || Filename to save file to on host computer. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||The filename (if there is one) in ''cmdStr'' and ''filename'' parameters do not have to match. | ||
+ | |- | ||
+ | |'''See Also''' || KMPutFile | ||
+ | |- | ||
+ | |'''Example'''|| See Example #2 | ||
+ | |} | ||
+ | |||
===KMPutFile=== | ===KMPutFile=== | ||
+ | |||
+ | Sends a file to a device. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMPutFile (KMDevice device, LPSTR cmdStr, LPSTR filename)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMPutFile(ByVal device As Long, ByVal cmdStr$, ByVal filename$) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMPutFile (System.IntPtr device, System.String cmdStr, System.String fileName)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''device'' || Handle for the device the file is being sent to. | ||
+ | |- | ||
+ | |''cmdStr || The command string to cause the device to retrieve a file. | ||
+ | |- | ||
+ | |''filename'' || Filename of file on host computer.. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||The filename (if there is one) in ''cmdStr'' and ''filename'' parameters do not have to match. | ||
+ | |- | ||
+ | |'''See Also''' || KMGetFile | ||
+ | |- | ||
+ | |'''Example'''|| See Example #2 | ||
+ | |} | ||
+ | |||
+ | ===Example #2=== | ||
+ | |||
+ | This program shows how to send and retrieve files to/from a device (controller or amplifier) via the KMAPI. | ||
+ | |||
+ | <big><big>'''C/C++'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | /* Declare device handles */ | ||
+ | KMDevice devController; | ||
+ | |||
+ | /* Initialize the API */ | ||
+ | KMInitialize(); | ||
+ | |||
+ | /* Create a controller */ | ||
+ | devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); | ||
+ | |||
+ | /* Get a file called "PROG1.PRG" from devController */ | ||
+ | KMGetFile(devController, "RETRIEVE PROG1.PRG", "C:\\PROG1.PRG"); | ||
+ | |||
+ | /* Send a file called "PROG2.PRG" to devController */ | ||
+ | KMPutFile(devController, "SEND PROG2.PRG", "C:\\PROG2.PRG"); | ||
+ | |||
+ | /* Destroy device table entries */ | ||
+ | KMDestroyDevice(devController); | ||
+ | |||
+ | /* Terminate the API */ | ||
+ | KMTerminate(); | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | |||
+ | |||
+ | <big><big>'''Visual Basic'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | 'Declare device handles | ||
+ | Dim devConroller As Long | ||
+ | |||
+ | 'Declare variables | ||
+ | Dim errorL As KMInitialize() | ||
+ | |||
+ | 'Create a controller | ||
+ | devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") | ||
+ | |||
+ | 'Get a file called "PROG1.PRG" from devController | ||
+ | errorL - KMGetFile(decController, "RETRIEVE PROG1.PRG", "C:\\PROG1.PRG") | ||
+ | |||
+ | 'Send a file called "PROG2.PRG" to devController | ||
+ | errorL - KMPutFile(devController, "SEND PROG2.PRG", "C:\\PROG2.PRG") | ||
+ | |||
+ | 'Destroy device table entries | ||
+ | errorL - KMDestroyDevice(devController) | ||
+ | |||
+ | 'Terminate the API | ||
+ | Dim errorL - KMTerminate() | ||
+ | |||
+ | </pre> | ||
+ | |||
==Error Handling== | ==Error Handling== | ||
+ | |||
+ | Error handling is one of the most important elements to creating a robust application. <br> | ||
+ | The KMAPI provides comprehensive error handling which allows the programmer to properly handle all situations. While using the KMAPI errors can occur at the following levels: | ||
+ | * Internal to the KMAPI | ||
+ | ** host computer runs out of memory | ||
+ | * Communication between the API and the device | ||
+ | ** device fails to respond in time | ||
+ | * Internal to the device | ||
+ | ** a move cannot be made due to a limit switch being open | ||
+ | |||
+ | |||
+ | Every function in the KMAPI returns a result, which is almost always of the type KMErrorCode (Long for Visual Basic users). Each error type is well identified in the error code. <br> | ||
+ | The following is an example of the proper method of handling errors returned from the KMAPI: <br> | ||
+ | |||
+ | |||
+ | |||
+ | <big><big>'''C/C++'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | if ( err !- KM_ERR_OK ) | ||
+ | { | ||
+ | Char strBuf[1024]; | ||
+ | KMErrorCode err2; | ||
+ | |||
+ | if (IS_DEVICE_ERROR(err) ) // the error is device related | ||
+ | { | ||
+ | // this next call will eventually be KMErrorGetDeviceMessage, | ||
+ | // but this function is not implemented yet. | ||
+ | err2 - KMErrorGetOriginalDeviceMessage (strBuf, sizeof(strBuf)); | ||
+ | // insert your code to print the error message here | ||
+ | if (err -- KM_ERR_OK) | ||
+ | { | ||
+ | // insert your code to print the error message here | ||
+ | } | ||
+ | else | ||
+ | printf("Error calling KMErrorGetOriginalDeviceMessage" | ||
+ | "[%08X].", err2); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | // the error is an API error so get the error message | ||
+ | // from the API | ||
+ | err2 - KMErrorGetMessage(err, strBuf, sizeof(strBuf)); | ||
+ | if (err2 -- KM_ERR_OK) | ||
+ | { | ||
+ | // insert your code to print the error message here | ||
+ | } | ||
+ | else | ||
+ | printf("Error calling KMErrorGetMessage [&08x].", err2); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | |||
+ | <big><big>'''Visual Basic'''</big></big> | ||
+ | |||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | Dim strBuf as String * 1024 | ||
+ | Dim err as Long | ||
+ | Dim err2 as Long | ||
+ | |||
+ | if err <> KM_ERR_OK Then | ||
+ | If IS_DEVICE_ERROR(err) Then ' the error is device related | ||
+ | ' This next call will eventually be KMErrorGetDeviceMessage, | ||
+ | ' but this function is not implemented yet. | ||
+ | err2 - KMErrorGetOriginalDeviceMessage(strBuf, 1024) | ||
+ | ' insert your code to print the error massage here | ||
+ | If ree2 - KM_ERR_OK Then | ||
+ | ' insert your code to print the error message here | ||
+ | Else | ||
+ | MsgBox "Error calling KMErrorGetOriginalDeviceMessage" | ||
+ | End If | ||
+ | Else | ||
+ | ' the error is an API error so get the error message | ||
+ | ' from the API | ||
+ | err2 - KMErrorGetMessage(err, strBuf, sizeof(strBuf)) | ||
+ | if err2 - KM_ERR_OK | ||
+ | ' insert your code to print the error message here | ||
+ | Else | ||
+ | MsgBox "Error calling KMErrorGetMessage" | ||
+ | End If | ||
+ | End If | ||
+ | End If | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | |||
+ | |||
===Error Codes=== | ===Error Codes=== | ||
+ | |||
+ | The following is a list of the error codes that can be returned by the KMAPI. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | !width = "150" bgcolor = A9A9A9| '''Error code''' | ||
+ | !width = "80" bgcolor = A9A9A9| '''Description''' | ||
+ | !width = "150" bgcolor = A9A9A9| '''Value (hex)''' | ||
+ | |||
+ | |- | ||
+ | |KM_ERR_OK | ||
+ | | | ||
+ | |H00000000 | ||
+ | |- | ||
+ | |KM_ERR_BAD | ||
+ | | | ||
+ | |HFFFFFFFF | ||
+ | |- | ||
+ | |KM_ERR_BAD_CRC | ||
+ | | | ||
+ | |H00800001 | ||
+ | |- | ||
+ | |KM_ERR_TIME_OUT | ||
+ | | | ||
+ | |H00800002 | ||
+ | |- | ||
+ | |KM_ERR_BAD_DEVICE_ID | ||
+ | | | ||
+ | |H00800003 | ||
+ | |- | ||
+ | |KM_ERR_DEVICE_NOT_INSTALLED | ||
+ | | | ||
+ | |H00800004 | ||
+ | |- | ||
+ | |KM_ERR_LOCK_FAILED | ||
+ | | | ||
+ | |H00800005 | ||
+ | |- | ||
+ | |KM_ERR_NO_DATA | ||
+ | | | ||
+ | |H00800006 | ||
+ | |- | ||
+ | |KM_ERR_ASYNC | ||
+ | | | ||
+ | |H00800008 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_SEND_MSG | ||
+ | | | ||
+ | |H00800009 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_ACK_NAK | ||
+ | | | ||
+ | |H0080000A | ||
+ | |- | ||
+ | |KM_ERR_FAIL_ACCEPT | ||
+ | | | ||
+ | |H0080000B | ||
+ | |- | ||
+ | |KM_ERR_FAIL_PROTOCOL | ||
+ | | | ||
+ | |H0080000C | ||
+ | |- | ||
+ | |KM_ERR_FAIL_RESPOND | ||
+ | | | ||
+ | |H0080000D | ||
+ | |- | ||
+ | |KM_ERR_UNKNOWN_MESSAGE | ||
+ | | | ||
+ | |H0080000E | ||
+ | |- | ||
+ | |KM_ERR_MEM_LOCK | ||
+ | | | ||
+ | |H0080000F | ||
+ | |- | ||
+ | |KM_ERR_FAIL_CREATE_FILE | ||
+ | | | ||
+ | |H00800010 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_OPEN_FILE | ||
+ | | | ||
+ | |H00800011 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_FIND_FILE | ||
+ | | | ||
+ | |H00800012 | ||
+ | |- | ||
+ | |KM_ERR_UNEXPECTED_EOF | ||
+ | | | ||
+ | |H00800013 | ||
+ | |- | ||
+ | |KM_ERR_NO_CONTEXT | ||
+ | | | ||
+ | |H00800014 | ||
+ | |- | ||
+ | |KM_ERR_MEM_ALLOC | ||
+ | | | ||
+ | |H00800015 | ||
+ | |- | ||
+ | |KM_ERR_INVALID_PRODUCT | ||
+ | | | ||
+ | |H00800016 | ||
+ | |- | ||
+ | |KM_ERR_SYSTEM | ||
+ | | | ||
+ | |H00800017 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_FIND_NAME | ||
+ | | | ||
+ | |H00800018 | ||
+ | |- | ||
+ | |KM_ERR_INVALID_TYPE | ||
+ | | | ||
+ | |H00800019 | ||
+ | |- | ||
+ | |KM_ERR_NO_DEFAULT | ||
+ | | | ||
+ | |H0080001A | ||
+ | |- | ||
+ | |KM_ERR_NO_MAX_MIN | ||
+ | | | ||
+ | |H0080001B | ||
+ | |- | ||
+ | |KM_ERR_BAD_IRQ_NUMBER | ||
+ | | | ||
+ | |H0080001C | ||
+ | |- | ||
+ | |KM_ERR_INVALID_FORMAT | ||
+ | | | ||
+ | |H0080001D | ||
+ | |- | ||
+ | |KM_ERR_NOT_IMPLEMENTED | ||
+ | | | ||
+ | |H0080001E | ||
+ | |- | ||
+ | |KM_ERR_FAIL_FIND_MSG | ||
+ | | | ||
+ | |H0080001F | ||
+ | |- | ||
+ | |KM_ERR_NOT_DEVICE | ||
+ | | | ||
+ | |H00800020 | ||
+ | |- | ||
+ | |KM_ERR_FAILED_OPEN_DEVICE | ||
+ | | | ||
+ | |H00800021 | ||
+ | |- | ||
+ | |KM_ERR_INVALID_VALUE | ||
+ | | | ||
+ | |H00800022 | ||
+ | |- | ||
+ | |KM_ERR_INVALID_DEVICE_CONTEXT | ||
+ | | | ||
+ | |H00800023 | ||
+ | |- | ||
+ | |KM_ERR_GROUP_MAX_EXCEEDED | ||
+ | | | ||
+ | |H00800024 | ||
+ | |- | ||
+ | |KM_ERR_AXIS_ALREADY_IN_GROUP | ||
+ | | | ||
+ | |H00800025 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_FIND_DEVICE | ||
+ | | | ||
+ | |H00800026 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_WRITE_FILE | ||
+ | | | ||
+ | |H00800027 | ||
+ | |- | ||
+ | |KM_ERR_FAIL_READ_FILE | ||
+ | | | ||
+ | |H00800028 | ||
+ | |- | ||
+ | |KM_ERR_CONFIG_ALREADY_EXISTS | ||
+ | | | ||
+ | |H00800029 | ||
+ | |- | ||
+ | |KM_ERR_DEVICE_ALREADY_EXISTS | ||
+ | | | ||
+ | |H0080002A | ||
+ | |- | ||
+ | |KM_ERR_FAIL_PRODUCT_DLL | ||
+ | | | ||
+ | |H0080002B | ||
+ | |- | ||
+ | |KM_ERR_WINDOWS_API | ||
+ | | | ||
+ | |H0080002C | ||
+ | |- | ||
+ | |KM_ERR_VARIABLE_NOT_FOUND | ||
+ | | | ||
+ | |H0080002D | ||
+ | |- | ||
+ | |KM_ERR_SERIAL_FRAMING | ||
+ | | | ||
+ | |H0080002E | ||
+ | |- | ||
+ | |KM_ERR_FAILED_CLOSE_DEVICE | ||
+ | | | ||
+ | |H0080002F | ||
+ | |- | ||
+ | |KM_ERR_FAIL_PRODUCT_DLL | ||
+ | | | ||
+ | |H00800030 | ||
+ | |- | ||
+ | |KM_ERR_SYNTAX_ERROR | ||
+ | | | ||
+ | |H00800100 | ||
+ | |- | ||
+ | |KM_ERR_SSMC_ERROR | ||
+ | | | ||
+ | |H00030027 | ||
+ | |- | ||
+ | |KM_ERR_SERVOSTAR_ERROR | ||
+ | | | ||
+ | |H00010027 | ||
+ | |- | ||
+ | |KM_ERR_SSMC_DRIVER_ERROR | ||
+ | | | ||
+ | |H00040027 | ||
+ | |||
+ | |} | ||
+ | |||
===KMErrorGetMessage=== | ===KMErrorGetMessage=== | ||
+ | |||
+ | Get text of the error message related to an error code. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMErrorGetMessage (KMErrorCode errCode, LPSTR buf, short bufLen)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMErrorGetMessage (ByVal errCode As Long, ByVal buf$, ByVal bufLen As Integer) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMErrorGetMessage (System.Int32 errCode, char[] buf, System.UInt32 bufLen)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''errCode'' || Error code to get the message for | ||
+ | |- | ||
+ | |''buf'' || Character array buffer to store error message in | ||
+ | |- | ||
+ | |''bufLen'' ||Length of ''buf'' array. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||The text returned is device dependent and is not translated in any way. <br> If more than one line of text is returned the lines will be separated with newline characters (‘\n’). | ||
+ | |- | ||
+ | |'''See Also''' || KMErrorGetDeviceMessage, KMErrorGetOriginalDeviceMessage | ||
+ | |- | ||
+ | |'''Example'''|| See Example #3 | ||
+ | |} | ||
+ | |||
===KMErrorGetDeviceMessage=== | ===KMErrorGetDeviceMessage=== | ||
+ | |||
+ | |||
+ | Get original text and error number of last device error. | ||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMErrorGetDeviceMessage (KMErrorCodePtr pErrCode, LPSTR buf, short bufLen)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMErrorGetDeviceMessage (pErrCode As Long, ByVal buf$, ByVal bufLen As Integer) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMErrorGetDeviceMessage (System.IntPtr pErrCode, char[] buf, System.UInt32 bufLen)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''pErrCode'' || Pointer to variable to store last error number in | ||
+ | |- | ||
+ | |''buf'' || Character array buffer for device error message | ||
+ | |- | ||
+ | |''bufLen'' ||Length of ''buf'' array. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||Last device error is stored on a per application context basis.<br> The text returned is device dependent and is not translated in any way. <br> If more than one line of text is returned the lines will be separated with newline characters (‘\n’). | ||
+ | |- | ||
+ | |'''See Also''' || KMErrorGetMessage, KMErrorGetOriginalDeviceMessage | ||
+ | |- | ||
+ | |'''Example'''|| See Example #3 | ||
+ | |} | ||
+ | |||
===KMErrorGetOriginalDeviceMessage=== | ===KMErrorGetOriginalDeviceMessage=== | ||
+ | |||
+ | |||
+ | Retrieves entire original error message from buffer. | ||
+ | |||
+ | |||
+ | {| border = "1" cellpadding = "2" cellspacing = "0" | ||
+ | |||
+ | |C/C++||'''KMErrorCode KMErrorGetOriginalDeviceMessage (LPSTR buf, short bufLen)''' | ||
+ | |||
+ | |- | ||
+ | |Visual Basic ||'''KMErrorGetOriginalDeviceMessage (ByVal buf$, ByVal bufLen As Integer) As Long''' | ||
+ | |- | ||
+ | |C# ||'''System.Int32 IKMErrorGetOriginalDeviceMessage (char[] buf, System.UInt32 bufLen)''' | ||
+ | |- | ||
+ | |} | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | {| border="0" cellpadding="10" cellspacing="1" | ||
+ | |||
+ | |''buf'' || Character array buffer to store error message in | ||
+ | |- | ||
+ | |''bufLen'' ||Length of ''buf'' array. | ||
+ | |- | ||
+ | |'''Return Value''' ||KM_ERR_OK if command is successfully transmitted | ||
+ | |- | ||
+ | |'''Remarks''' ||The text returned is the original error message that was generated and stored in the buffer | ||
+ | |- | ||
+ | |'''See Also''' || KMErrorGetMessage, KMErrorGetDeviceMessage | ||
+ | |- | ||
+ | |'''Example'''|| See Example #3 | ||
+ | |} | ||
+ | |||
===Example #3=== | ===Example #3=== | ||
+ | |||
+ | This program shows how to get the text descriptions associated with any error number or the last error that occurred. | ||
+ | |||
+ | <big><big>'''C/C++'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | |||
+ | /* Declare device handles */ | ||
+ | KMDevice devcontroller; | ||
+ | |||
+ | /* Declare error code variables */ | ||
+ | KMErrorCode err; | ||
+ | char strErrBuf[500]; | ||
+ | |||
+ | /* Initialize the API */ | ||
+ | KMIntialize(); | ||
+ | |||
+ | /* Create a controller */ | ||
+ | devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); | ||
+ | |||
+ | /* A statement that will cause an error */ | ||
+ | err - KMVariableGetLongValue(axisA1, "VCRUISE", &valuesL); | ||
+ | if (err !- KM_ERR_OK) /* do something if there was an error */ | ||
+ | { | ||
+ | KMErrorGetMessage(err, strErrBuf, sizeof(strErrBuf)); | ||
+ | printf ("The error message was: &s\n", strErrBuf); | ||
+ | } | ||
+ | |||
+ | /* Another way to get the last error */ | ||
+ | err - KMVariableGetLongValue(axisA1, "VCRUISE", &valueL); | ||
+ | KMErrorGetDeviceMessage(&err,strErrBuf, sizeof (strErrBuf)); | ||
+ | if (err !- KM_ERR_OK) /* do something if there was an error */ | ||
+ | { | ||
+ | printf("The error message was: %s\n", strErrBuf); | ||
+ | } | ||
+ | /* Destroy device table entries */ | ||
+ | KMDestroydevice (devcontroller); | ||
+ | |||
+ | /* Terminate the API */ | ||
+ | KMTerminate(); | ||
+ | |||
+ | </pre> | ||
+ | |||
+ | |||
+ | <big><big>'''Visual Basic'''</big></big> | ||
+ | <pre style="white-space:pre-wrap; width:40%; border:1px solid lightgrey; "> | ||
+ | ' Declare device handles | ||
+ | Dim devController As Long | ||
+ | |||
+ | 'Declare error code variables | ||
+ | Dim err As Long | ||
+ | Dim strErrbuf As String[10000] | ||
+ | |||
+ | 'Initialize the API | ||
+ | err - KMInitialize() | ||
+ | |||
+ | 'Create a controller | ||
+ | devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") | ||
+ | |||
+ | 'A statement that will cause an error | ||
+ | err - KMVariableGetLongValue(axisA1, "VCRUISE", valueL) | ||
+ | if err !- KM_ERR_OK then 'do something if there was an error | ||
+ | |||
+ | err- KMErrorGetMessage(err,strErrBuf, 10000) | ||
+ | print "The error message was: "; strErrBuf | ||
+ | |||
+ | End If | ||
+ | |||
+ | 'Another way to get the last error | ||
+ | err - KMVariableGetValue(axisA1, "VCRUISE", valueL) | ||
+ | err - KMErrorGetDeviceMessage(err, strErrBuf, 10000) | ||
+ | If err !- KM_ERR_OK Then 'do something if there was an error | ||
+ | |||
+ | Print "The error message was: "; strErrBuf | ||
+ | |||
+ | End If | ||
+ | |||
+ | 'Destroy device table entries | ||
+ | err - KMDestroyDevice(devController) | ||
+ | |||
+ | 'Terminate the API | ||
+ | err - KMTerminate() | ||
+ | |||
+ | </pre> |
Latest revision as of 13:47, 6 August 2017
Language: | English • 中文(简体) |
---|
Contents
Overview
The KMAPI software package allows you to communicate with softMC from popular programming languages, such as Visual Basic over TCP/IP and UDP. The KMAPI provides complete access to the command line interface of your system across a TCP/IP connection. Fast access to frequently changing data, such as axis set-points and feedback, is provided via a UDP connection, also called UDP fast data.
You can find the full KMAPI documentation here.
Introduction
The KMAPI addresses several concerns when interfacing your program with KMAPI drives and controllers, including:
- sending commands (and receiving responses)
- reading and setting amplifier or controller variables
- sending and retrieving files
- error handling
The KMAPI addresses these concerns by providing a library of functions which allow the user to describe their system in terms of devices (amplifiers, controllers, axes, groups) and then communicate with these devices individually.
Central to the KMAPI is the concept of a device table. The device table is a data store (database) which is managed by the KMAPI for the user.
The device table is populated with devices by the programmer, allowing the programmer to execute commands on any device in the device table. Most details of the communication techniques used are hidden allowing
the programmer to focus on high level programming instead of communication protocols.
General Information
The KMAPI is available for Windows NT and is compatible with a wide variety of 32-bit programming tools including Microsoft Visual Basic and Microsoft Visual C++.
The KMAPI is provided as a Windows DLL which makes it accessible from most Windows programming languages.
Most KMAPI functions return an error code which indicates the success of the action requested by the programmer. Full text descriptions of the error are often associated with the error and can be accessed via KMAPI calls.
Getting started
The following C# code is a minimal console application which performs the following tasks:
- Initialize the library
- Create 'controller' - the software component used for communication
- send a command and read the response
- shut down the communication
The software is written in C# and uses the KMAPI.DLL to comunicate with the KMTCPIP.EXE communication server, an equivalent C++/C program will look pretty much the same but will have to use the KMAPI32.DLL.
Note: to use this:
- Add a reference to kmapi.dll to your project
- argument 1 should be of the form: "IP:10.4.20.55,5004" - 'IP:' as is, the IP address set to your mc, port can be 5001/4/
- argument 2 is an MC command, try first with a simple command like "?ver"
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace KMAPIDemo { class Program { private static IntPtr device = IntPtr.Zero; static void Main(string[] args) { if (args.Length != 2) return; string ipAddress = args[0]; string cmdToExecute = args[1]; // ******************************* // *** initialize and connect *** // ******************************* int retVal = KMAPI.IKMInitialize(); // Initialize the API if (retVal != 0) {// if fail Console.WriteLine(string.Format("Error: Connection error (IKMInitialize): {0}", retVal)); return; // fail } uint connectionType = 7; // COMM_TCPIP_DEDICATED = 7 - dedicated device => pre defined ip address try { device = KMAPI.IKMCreateController(KMAPI.PROD_GPMAC, "someName", // dummy connectionType, 1, ipAddress); } catch (Exception e) { KMAPI.IKMTerminate(); Console.WriteLine(string.Format("Error: Connection error (IKMCreateController): {0}", e.Message)); return; } if (device == IntPtr.Zero) { // if fail KMAPI.IKMTerminate(); Console.WriteLine("Error: Connection error (IKMCreateController): device = 0"); return; } // ******************************* // *** Execute some commands *** // ******************************* const int BuffSz = 100000; char[] responseBuff = new char[BuffSz]; retVal = KMAPI.IKMExecuteCmdResponse(device, cmdToExecute, responseBuff, BuffSz); if (retVal != 0) // fail Console.WriteLine("failed"); else { string response = new string(responseBuff); int idx0 = response.IndexOf("\0"); if (idx0 > 0) response = response.Substring(0, idx0); Console.WriteLine(string.Format("Command '{0}' => response '{1}'", cmdToExecute, response)); } // ***************** // *** shut down *** // ***************** retVal = KMAPI.IKMDestroyDevice(device); // terminate KMAPI if (retVal != 0) { // if fail Console.WriteLine("Error when destroying device"); return; // fail } device = IntPtr.Zero; retVal = KMAPI.IKMTerminate(); if (retVal != 0) { // if fail Console.WriteLine("Error when terminating"); return; // fail } } } }
Error Messages
Most of the KMAPI functions return an error code. Successful KMAPI functions return KM_ERR_OK. Errors originate in the device itself or the KMAPI.
When the message originates within the KMAPI, an error number is returned which can be compared against the list of errors in the KMAPI header files (C/C++), or the global files (Visual Basic).
In addition the KMAPI also assigns a text message to the error which can be retrieved by calling KMErrorGetMessage. When the error originates in the device (drive or controller) the KMAPI “parses” the message and stores the relevant information including the error message and the error number as given by the device.
This information can be retrieved for the last error via KMErrorGetDeviceMessage similar to the Win32 KMAPI GetLastError function.
Finally, the text of the error message, as the device originally sent, can be retrieved via KMErrorGetOriginalDeviceMessage.
Sending/Retrieving Files
For the sending and retrieval of files the KMAPI provides users with two functions, KMPutFile and KMGetFile, respectively.
In addition to the device handle parameter, the path of the file and the actual command must be sent when calling either of these functions.
Advanced asynchronous message handling
Some controllers and drives generate messages not related to a specific command called asynchronous messages.
Some examples of asynchronous messages are overspeed warnings, limit switch closures and runtime error messages from softMC tasks.
When these messages are received the KMAPI converts them into Windows messages (events) which the programmer can request to have delivered to their application.
By default the KMAPI displays each asynchronous message in a modal dialog box (via the Win32 MessageBox function).
If the programmer wants to handle these messages differently the KMAsyncSetHandler KMAPI function allows a window to be registered as the destination for these messages.
KMAsyncGetHandler can be used to save the previous error handler to that the programmer can restore it on demand.
Like all Windows messages, WM_KM_ASYNC has two parameters, wParam and lParam.
lParam contains a handle to the buffer which contains the asynchronous message as received by the KMAPI.
The programmer can use KMAsyncGetMessage to get the asynchronous message from the KMAPI.
Asynchronous messages and Microsoft Visual Basic
Visual Basic does not provide an easy mechanism for directly handling Windows messages.
In order to overcome this limitation a custom control called KMAPI has been provided which has an event representing the receipt of an asynchronous message.
Placing this control on your form automatically initializes the KMAPI (KMInitialize) and registers the form for asynchronous messages.
Library Reference
KMAPI Initialization
KMInitialize
Prepares the KMAPI for use:
C/C++ | KMErrorCode KMInitialize ( void ) |
---|---|
Visual Basic | KMInitialize() As Long |
C# | System.Int32 IKMInitialize () |
Return Value | KM_ERR_OK if KMAPI is successfully initialized. KM_ERR_WINDOWS_API if the asynchronous message window can’t be created. KM_ERR_MEM_LOCK if the application context was not successfully created. |
Remarks | The KMInitialize function must be called before any other KMAPI functions are called. |
See Also | KMTerminate |
Example | See Example #1 |
KMTerminate
Performs KMAPI cleanup required for proper application termination.
C/C++ | KMErrorCode KMTerminate ( void ) |
---|---|
Visual Basic | KMTerminate() As Long |
C# | IKMInitialize () |
Return Value | KM_ERR_OK if KMAPI is successfully terminated. KM_ERR_MEM_LOCK if the application context cannot be locked or removed. KM_ERR_NO_CONTEXT if the application context cannot be found in the application context registry. |
Remarks | The KMTerminate function must be called before the application using the KMAPI terminates. |
See Also | KMInitialize |
Example | See Example #1 |
Device Management
KMCreateController
C/C++ | KMDevice KMCreateController (KMProductType controllerProduct, LPSTR controllerName, KMCommType controllerCommType, short controllerID, LPSTR commOptions) |
---|---|
Visual Basic | KMCreateController (ByVal controllerProduct As Integer, ByVal controllerName$, ByVal controllerCommType As Integer, ByVal controllerID As Integer, ByVal commOptions$) As Long |
C# | System.IntPtr IKMCreateController (System.UInt32 controllerProduct, System.String controllerName, System.UInt32 controllerCommType, System.UInt32 controllerID, System.String commOptions) |
controllerProduct | Type of controller to create |
controllerName | String name for the controller |
controllerCommType | How the API should communicate with the controller (see communication type description) |
controllerID | What the controller’s address is |
commOptions | COM port used by the controller |
Return Value | A handle referring to the controller. |
Remarks | See product type description for controllerProduct. controllerName is provided for user convenience and is not used internally by the KMAPI. See communication type description for controllerCommType. commOptions is a general parameter that is intended for many uses. Presently, only connections of type COMM_TCPIP use this parameter. If COMM_TCPIP is selected then the commOptions parameter allows the user to specify what controller to connect to by IP address, controller name, serial number or DIP switch setting. The format for commOptions is as follows:
When connecting via serial the IP address should is always be specified as 91.0.0.2. |
See Also | ____ |
Example | See Example #1 |
Device Access
KMExecuteCmd
Sends a command to a device.
C/C++ | KMErrorCode KMExecuteCmd (KMDevice device, LPSTR cmdStr) |
Visual Basic | KMExecuteCmd (ByVal device As Long, ByVal cmdStr$) As Long |
C# | System.Int32 IKMExecuteCmd (System.IntPtr device , System.String cmdStr) |
device | Handle for the device the command is being sent to. |
cndStr | The command to send. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | Sends the command cmdStr unmodified to the device specified by device. Should be used with commands that do not have responses. |
See Also | KMExecuteCmdResponse |
Example | See Example #1 |
KMExecuteCmdResponse
Sends a command to a device and waits for a response.
C/C++ | KMErrorCode KMExecuteCmdResponse (KMDevice device, LPSTR cmdStr, LPSTR outStr, DWORD outSize) |
Visual Basic | KMExecuteCmdResponse (ByVal device As Long, ByVal cmdStr$, ByVal outStr$, ByVal outSize As Long) As Long |
C# | System.Int32 IKMExecuteCmdResponse (System.IntPtr device , System.String cmdStr , char[] outStr , System.UInt32 outSize) |
device | Handle for the device the command is being sent to. |
cndStr | The command to send. |
outStr | A buffer for the response. |
outSize | Size of the outStr buffer. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | Sends the command cmdStr unmodified to the device specified by device. Should be used with commands that have responses. |
See Also | KMExecuteCmd |
Example | See Example #1 |
Example #1
This program shows how to initialize the KMAPI, create devices and access variables on each of the devices.
C/C++
/* Declare device handle */ KMDevice devController; KMDevice axisA1; /* Declare variables */ long valueL; double valueD; char valueS [100]; /* Initialize the API */ KMInitialize(); /* Create a controller */ devController - KMCreateController (PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); /* Create axes */ axisA1 - KMCreateSercosAxis ( PROD_SERVOSTAR, "A1", devController); /* Move A1 */ KMExecuteCmd ( devController, "MOVE A1 100"); /* Get variables */ KMVariableControllerGetLongValue (axisA1, "VCRUISE", &valueL); KMVariableControllerGetDblValue (axisA1, "PFINAL", &valueD); KMVariableControllerGetStringValue (axisA1, "AMAX", valueS, sizeof (valueS)); /* Set variables */ KMVariableControllerSetLongValue (axisA1, "VCRUISE", valueL); KMVariableControllerSetDblValue (axisA1, "PFINAL", valueD); KMVariableControllerGetStringValue (axisA1, "AMAX", valueS); /* Destroy device table entries */ KMDestroyDevice (axisA1); KMDestroyDevice (devController); /* Terminate the API */ KMTerminate();
Visual Basic
'Declare device handles Dim devcontroller As Long Dim axisA1 As Long 'Declare variables Dim valueL As Long Dim valueD as Double Dim errorL As Long 'Initialize the API errorL - KMInitialize() 'Create a controller devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") 'Create axes axisA1 - KMCreateSercosAxis( PROD_SERVOSTAR, "A1", devController) 'Move A1 errorL - KMExecuteCmd( devController, "MOVE A1 100"); 'Get variables errorL - KMVariablesControllerGetLongValue(axisA1, "VCRUISE", valueL) errorL - KMVariablesControllerGetDblValue(axisA1, "PFINAL", valueD) errorL - KMVariablesControllerGetStringValue(axisA1, "AMAX", valueS, Length(valueS)) 'Set variables errorL - KMVariablesControllerSetLongValue(axisA1, "VCRUISE", valueL) errorL - KMVariablesControllerSetDblValue(axisA1, "PFINAL", valueD) errorL - KMVariablesControllerSetStringValue(axisA1, "AMAX", valueS) 'Destroy device table entries errorL- KMDesroyDevice(axisA1) errorL- KMDesroyDevice(devController) 'Terminate the API errorL - KMTerminate()
KMGetFile
Retrieve a file from a device.
C/C++ | KMErrorCode KMGetFile (KMDevice device, LPSTR cmdStr, LPSTR filename) |
Visual Basic | KMGetFile (ByVal device As Long, ByVal cmdStr$, ByVal filename$) As Long |
C# | System.Int32 IKMGetFile (System.IntPtr device, System.String cmdStr, System.String fileName) |
device | Handle for the device the file is being retrieved from. |
cmdStr | The command string to cause the device to send a file. |
filename | Filename to save file to on host computer. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | The filename (if there is one) in cmdStr and filename parameters do not have to match. |
See Also | KMPutFile |
Example | See Example #2 |
KMPutFile
Sends a file to a device.
C/C++ | KMErrorCode KMPutFile (KMDevice device, LPSTR cmdStr, LPSTR filename) |
Visual Basic | KMPutFile(ByVal device As Long, ByVal cmdStr$, ByVal filename$) As Long |
C# | System.Int32 IKMPutFile (System.IntPtr device, System.String cmdStr, System.String fileName) |
device | Handle for the device the file is being sent to. |
cmdStr | The command string to cause the device to retrieve a file. |
filename | Filename of file on host computer.. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | The filename (if there is one) in cmdStr and filename parameters do not have to match. |
See Also | KMGetFile |
Example | See Example #2 |
Example #2
This program shows how to send and retrieve files to/from a device (controller or amplifier) via the KMAPI.
C/C++
/* Declare device handles */ KMDevice devController; /* Initialize the API */ KMInitialize(); /* Create a controller */ devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); /* Get a file called "PROG1.PRG" from devController */ KMGetFile(devController, "RETRIEVE PROG1.PRG", "C:\\PROG1.PRG"); /* Send a file called "PROG2.PRG" to devController */ KMPutFile(devController, "SEND PROG2.PRG", "C:\\PROG2.PRG"); /* Destroy device table entries */ KMDestroyDevice(devController); /* Terminate the API */ KMTerminate();
Visual Basic
'Declare device handles Dim devConroller As Long 'Declare variables Dim errorL As KMInitialize() 'Create a controller devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") 'Get a file called "PROG1.PRG" from devController errorL - KMGetFile(decController, "RETRIEVE PROG1.PRG", "C:\\PROG1.PRG") 'Send a file called "PROG2.PRG" to devController errorL - KMPutFile(devController, "SEND PROG2.PRG", "C:\\PROG2.PRG") 'Destroy device table entries errorL - KMDestroyDevice(devController) 'Terminate the API Dim errorL - KMTerminate()
Error Handling
Error handling is one of the most important elements to creating a robust application.
The KMAPI provides comprehensive error handling which allows the programmer to properly handle all situations. While using the KMAPI errors can occur at the following levels:
- Internal to the KMAPI
- host computer runs out of memory
- Communication between the API and the device
- device fails to respond in time
- Internal to the device
- a move cannot be made due to a limit switch being open
Every function in the KMAPI returns a result, which is almost always of the type KMErrorCode (Long for Visual Basic users). Each error type is well identified in the error code.
The following is an example of the proper method of handling errors returned from the KMAPI:
C/C++
if ( err !- KM_ERR_OK ) { Char strBuf[1024]; KMErrorCode err2; if (IS_DEVICE_ERROR(err) ) // the error is device related { // this next call will eventually be KMErrorGetDeviceMessage, // but this function is not implemented yet. err2 - KMErrorGetOriginalDeviceMessage (strBuf, sizeof(strBuf)); // insert your code to print the error message here if (err -- KM_ERR_OK) { // insert your code to print the error message here } else printf("Error calling KMErrorGetOriginalDeviceMessage" "[%08X].", err2); } else { // the error is an API error so get the error message // from the API err2 - KMErrorGetMessage(err, strBuf, sizeof(strBuf)); if (err2 -- KM_ERR_OK) { // insert your code to print the error message here } else printf("Error calling KMErrorGetMessage [&08x].", err2); } }
Visual Basic
Dim strBuf as String * 1024 Dim err as Long Dim err2 as Long if err <> KM_ERR_OK Then If IS_DEVICE_ERROR(err) Then ' the error is device related ' This next call will eventually be KMErrorGetDeviceMessage, ' but this function is not implemented yet. err2 - KMErrorGetOriginalDeviceMessage(strBuf, 1024) ' insert your code to print the error massage here If ree2 - KM_ERR_OK Then ' insert your code to print the error message here Else MsgBox "Error calling KMErrorGetOriginalDeviceMessage" End If Else ' the error is an API error so get the error message ' from the API err2 - KMErrorGetMessage(err, strBuf, sizeof(strBuf)) if err2 - KM_ERR_OK ' insert your code to print the error message here Else MsgBox "Error calling KMErrorGetMessage" End If End If End If
Error Codes
The following is a list of the error codes that can be returned by the KMAPI.
Error code | Description | Value (hex) |
---|---|---|
KM_ERR_OK | H00000000 | |
KM_ERR_BAD | HFFFFFFFF | |
KM_ERR_BAD_CRC | H00800001 | |
KM_ERR_TIME_OUT | H00800002 | |
KM_ERR_BAD_DEVICE_ID | H00800003 | |
KM_ERR_DEVICE_NOT_INSTALLED | H00800004 | |
KM_ERR_LOCK_FAILED | H00800005 | |
KM_ERR_NO_DATA | H00800006 | |
KM_ERR_ASYNC | H00800008 | |
KM_ERR_FAIL_SEND_MSG | H00800009 | |
KM_ERR_FAIL_ACK_NAK | H0080000A | |
KM_ERR_FAIL_ACCEPT | H0080000B | |
KM_ERR_FAIL_PROTOCOL | H0080000C | |
KM_ERR_FAIL_RESPOND | H0080000D | |
KM_ERR_UNKNOWN_MESSAGE | H0080000E | |
KM_ERR_MEM_LOCK | H0080000F | |
KM_ERR_FAIL_CREATE_FILE | H00800010 | |
KM_ERR_FAIL_OPEN_FILE | H00800011 | |
KM_ERR_FAIL_FIND_FILE | H00800012 | |
KM_ERR_UNEXPECTED_EOF | H00800013 | |
KM_ERR_NO_CONTEXT | H00800014 | |
KM_ERR_MEM_ALLOC | H00800015 | |
KM_ERR_INVALID_PRODUCT | H00800016 | |
KM_ERR_SYSTEM | H00800017 | |
KM_ERR_FAIL_FIND_NAME | H00800018 | |
KM_ERR_INVALID_TYPE | H00800019 | |
KM_ERR_NO_DEFAULT | H0080001A | |
KM_ERR_NO_MAX_MIN | H0080001B | |
KM_ERR_BAD_IRQ_NUMBER | H0080001C | |
KM_ERR_INVALID_FORMAT | H0080001D | |
KM_ERR_NOT_IMPLEMENTED | H0080001E | |
KM_ERR_FAIL_FIND_MSG | H0080001F | |
KM_ERR_NOT_DEVICE | H00800020 | |
KM_ERR_FAILED_OPEN_DEVICE | H00800021 | |
KM_ERR_INVALID_VALUE | H00800022 | |
KM_ERR_INVALID_DEVICE_CONTEXT | H00800023 | |
KM_ERR_GROUP_MAX_EXCEEDED | H00800024 | |
KM_ERR_AXIS_ALREADY_IN_GROUP | H00800025 | |
KM_ERR_FAIL_FIND_DEVICE | H00800026 | |
KM_ERR_FAIL_WRITE_FILE | H00800027 | |
KM_ERR_FAIL_READ_FILE | H00800028 | |
KM_ERR_CONFIG_ALREADY_EXISTS | H00800029 | |
KM_ERR_DEVICE_ALREADY_EXISTS | H0080002A | |
KM_ERR_FAIL_PRODUCT_DLL | H0080002B | |
KM_ERR_WINDOWS_API | H0080002C | |
KM_ERR_VARIABLE_NOT_FOUND | H0080002D | |
KM_ERR_SERIAL_FRAMING | H0080002E | |
KM_ERR_FAILED_CLOSE_DEVICE | H0080002F | |
KM_ERR_FAIL_PRODUCT_DLL | H00800030 | |
KM_ERR_SYNTAX_ERROR | H00800100 | |
KM_ERR_SSMC_ERROR | H00030027 | |
KM_ERR_SERVOSTAR_ERROR | H00010027 | |
KM_ERR_SSMC_DRIVER_ERROR | H00040027 |
KMErrorGetMessage
Get text of the error message related to an error code.
C/C++ | KMErrorCode KMErrorGetMessage (KMErrorCode errCode, LPSTR buf, short bufLen) |
Visual Basic | KMErrorGetMessage (ByVal errCode As Long, ByVal buf$, ByVal bufLen As Integer) As Long |
C# | System.Int32 IKMErrorGetMessage (System.Int32 errCode, char[] buf, System.UInt32 bufLen) |
errCode | Error code to get the message for |
buf | Character array buffer to store error message in |
bufLen | Length of buf array. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | The text returned is device dependent and is not translated in any way. If more than one line of text is returned the lines will be separated with newline characters (‘\n’). |
See Also | KMErrorGetDeviceMessage, KMErrorGetOriginalDeviceMessage |
Example | See Example #3 |
KMErrorGetDeviceMessage
Get original text and error number of last device error.
C/C++ | KMErrorCode KMErrorGetDeviceMessage (KMErrorCodePtr pErrCode, LPSTR buf, short bufLen) |
Visual Basic | KMErrorGetDeviceMessage (pErrCode As Long, ByVal buf$, ByVal bufLen As Integer) As Long |
C# | System.Int32 IKMErrorGetDeviceMessage (System.IntPtr pErrCode, char[] buf, System.UInt32 bufLen) |
pErrCode | Pointer to variable to store last error number in |
buf | Character array buffer for device error message |
bufLen | Length of buf array. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | Last device error is stored on a per application context basis. The text returned is device dependent and is not translated in any way. If more than one line of text is returned the lines will be separated with newline characters (‘\n’). |
See Also | KMErrorGetMessage, KMErrorGetOriginalDeviceMessage |
Example | See Example #3 |
KMErrorGetOriginalDeviceMessage
Retrieves entire original error message from buffer.
C/C++ | KMErrorCode KMErrorGetOriginalDeviceMessage (LPSTR buf, short bufLen) |
Visual Basic | KMErrorGetOriginalDeviceMessage (ByVal buf$, ByVal bufLen As Integer) As Long |
C# | System.Int32 IKMErrorGetOriginalDeviceMessage (char[] buf, System.UInt32 bufLen) |
buf | Character array buffer to store error message in |
bufLen | Length of buf array. |
Return Value | KM_ERR_OK if command is successfully transmitted |
Remarks | The text returned is the original error message that was generated and stored in the buffer |
See Also | KMErrorGetMessage, KMErrorGetDeviceMessage |
Example | See Example #3 |
Example #3
This program shows how to get the text descriptions associated with any error number or the last error that occurred.
C/C++
/* Declare device handles */ KMDevice devcontroller; /* Declare error code variables */ KMErrorCode err; char strErrBuf[500]; /* Initialize the API */ KMIntialize(); /* Create a controller */ devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, ""); /* A statement that will cause an error */ err - KMVariableGetLongValue(axisA1, "VCRUISE", &valuesL); if (err !- KM_ERR_OK) /* do something if there was an error */ { KMErrorGetMessage(err, strErrBuf, sizeof(strErrBuf)); printf ("The error message was: &s\n", strErrBuf); } /* Another way to get the last error */ err - KMVariableGetLongValue(axisA1, "VCRUISE", &valueL); KMErrorGetDeviceMessage(&err,strErrBuf, sizeof (strErrBuf)); if (err !- KM_ERR_OK) /* do something if there was an error */ { printf("The error message was: %s\n", strErrBuf); } /* Destroy device table entries */ KMDestroydevice (devcontroller); /* Terminate the API */ KMTerminate();
Visual Basic
' Declare device handles Dim devController As Long 'Declare error code variables Dim err As Long Dim strErrbuf As String[10000] 'Initialize the API err - KMInitialize() 'Create a controller devController - KMCreateController( PROD_SSMC, "Main controller", COMM_PLUGIN, 1, "") 'A statement that will cause an error err - KMVariableGetLongValue(axisA1, "VCRUISE", valueL) if err !- KM_ERR_OK then 'do something if there was an error err- KMErrorGetMessage(err,strErrBuf, 10000) print "The error message was: "; strErrBuf End If 'Another way to get the last error err - KMVariableGetValue(axisA1, "VCRUISE", valueL) err - KMErrorGetDeviceMessage(err, strErrBuf, 10000) If err !- KM_ERR_OK Then 'do something if there was an error Print "The error message was: "; strErrBuf End If 'Destroy device table entries err - KMDestroyDevice(devController) 'Terminate the API err - KMTerminate()