Jump to content

Trying to use PTRobot API DLLs for Primera


GPinzone
 Share

Recommended Posts

I'm trying to use AutoIt to control a Primera CD/DVD Duplicator. Primera released a couple of DLLs and documentation. I'm not a C programmer, so I'm a little stuck on how to set up some of the calls. For example, their documentation lists:

PTRobot_Initialize
///////////////////////////
//
//  PTRobot_Initialize
//
//  Description:
//      Function to initialize internal data structures of
//          the PTRobot module.
//  Params:
//      None
//  Notes:
//  Return:
//      PTROBOT_OK if Successful
//      PTROBOT_INTERNAL if an internal error occurred.
//      
///////////////////////////
DWORD WINAPI PTRobot_Initialize();

So I created a function in AutoIT:

Func PTRobot_Initialize()
  Local $result
  Local $err = @error

  $result = DllCall("PTRobot.dll", "int", "PTRobot_Initialize")

  msgbox(0, "", $result[0])

  Return $result
EndFunc

And it seems to work. However, more complex ones like:

PTRobot_EnumRobots
///////////////////////////
//
//  PTRobot_EnumRobots
//
//  Description:
//      Function to enumerate the Robots on the system.
//  Params:
//      phRobots    points to an array of HANDLEs to store
//                      the Robots found.
//      pdwNumRobots    points to a DWORD containing the number of HANDLEs
//                          in the phRobots array.  This value is an input
//                          and an output.  The user should specify the size
//                  (number of HANDLEs) of the phRobots array on input.
//                  The value of the pdwNumRobots on output will be the
//                       number of robots found.
//
//  Notes:
//    Both params will be updated upon successful completion of this
//      command.  phRobots will contain handles to robots connected to
//      this system. pdwNumRobots will will be updated with the number of 
//      robots found.
//      Also, note that the hDrives[] array in the PTRobotInfo will not be
//    valid until PTRobot_EnumDrives is called.
//
//  Return:
//      PTROBOT_OK if Successful
//      PTROBOT_INVALID_ROBOT if no robots found
//      PTROBOT_SEQUENCE if this command is called out of sequence
//      PTROBOT_INTERNAL if an internal error occurred
//      PTROBOT_OVERFLOW if the number of robots found is > the value in 
//                       pdwNumRobots
//
///////////////////////////
DWORD WINAPI PTRobot_EnumRobots(HANDLE * phRobots, DWORD * pdwNumRobots);

This one has me stumped.

Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

Please not that I'm no dllcall expert, and this is just an attempt at what I think it might be.

$aHwnd = DllStructCreate("hwnd[10]");array struct
$pHwnd = DllStructGetPtr($aHwnd);pointer to struct
$Dword = DllStructCreate("dword")
$pDword = DllStructGetPtr($Dword);pointer to dword

Func PTRobot_Initialize(ByRef $pHwnd, ByRef $pDword) ;I think ByRef is needed when you are expecting the params to be modified
  Local $result
  Local $err = @error
  $result = DllCall("PTRobot.dll", "int", "PTRobot_EnumRobots", "ptr", $pHwnd, "ptr", $pDword)
  msgbox(0, "", $result[0])
  Return $result
EndFunc

Like I say, dont take this as good code, its just an attempt.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Thanks to both of you for the help! Here's what I have so far:

$aHwnd = DllStructCreate("hwnd[10]");array struct
$pHwnd = DllStructGetPtr($aHwnd);pointer to struct
$Dword = DllStructCreate("dword")
DllStructSetData($Dword,1,10)
$pDword = DllStructGetPtr($Dword);pointer to dword

PTRobot_Initialize()
PTRobot_EnumRobots($pHwnd, $pDword)

Func PTRobot_Initialize()
  Local $result
  Local $err = @error

  $result = DllCall("PTRobot.dll", "int", "PTRobot_Initialize")

  msgbox(0, "", $result[0])

  Return $result
EndFunc

Func PTRobot_EnumRobots($pHwnd, $pDword)
  Local $result
  Local $err = @error
  $result = DllCall("PTRobot.dll", "int", "PTRobot_EnumRobots", "ptr", $pHwnd, "ptr", $pDword)
  msgbox(0, "", $result[0])
  Return $result
EndFunc

AutoIt still crashes on the PTRobot_EnumRobots function. I used DllStructSetData to set the value of the $Dword struct to 10. I'm not sure why it's giving me grief.

Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

Try this:

Global $hPTROBOTDLL = DllOpen("PTRobot.dll")
ConsoleWrite("$hPTROBOTDLL = " & $hPTROBOTDLL & @CRLF)

Local $tHandles = DllStructCreate("handle[100]")

; Initialize
Local $aCall = DllCall($hPTROBOTDLL, "dword", "PTRobot_Initialize")
ConsoleWrite("Initialize @error = " & @error & @CRLF)
ConsoleWrite("Initialize $aCall[0] = " & $aCall[0] & @CRLF)

ConsoleWrite("----------------------------" & @CRLF)

; EnumRobots
$aCall = DllCall($hPTROBOTDLL, "dword", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($tHandles), "dword*", 100)

ConsoleWrite("EnumRobots @error = " & @error & @CRLF)
ConsoleWrite("EnumRobots $aCall[0] = " & $aCall[0] & @CRLF)
ConsoleWrite("EnumRobots $aCall[1] = " & $aCall[1] & @CRLF)
ConsoleWrite("EnumRobots $aCall[2] = " & $aCall[2] & @CRLF)

edit: and post console output

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

edit: and post console output

C:\Program Files\ImgBurn>test2.exe
$hPTROBOTDLL = 1
Initialize @error = 0
Initialize $aCall[0] = 0
----------------------------
EnumRobots @error = 0
EnumRobots $aCall[0] = 0
EnumRobots $aCall[1] = 0x003B6E18
EnumRobots $aCall[2] = 1
Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

So, what's the problem?

Is there any problem more?

edit: function says there is one Robot, handle of which is at 0x003B6E18.

I rewrote the program based on your example:

Global $hPTROBOTDLL = DllOpen("PTRobot.dll")

PTRobot_Initialize()
PTRobot_EnumRobots()

Func PTRobot_Initialize()
  Local $result
  Local $err = @error

  $result = DllCall($hPTROBOTDLL, "int", "PTRobot_Initialize")

  ;msgbox(0, "", $result[0])

  Return $result[0]
EndFunc

Func PTRobot_EnumRobots()
  Local $result
  Local $err = @error

  Local $aHwnd = DllStructCreate("hwnd[10]")
  $result = DllCall($hPTROBOTDLL, "int", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($aHwnd), "dword*", 10)

  msgbox(0, "", $result[0])
  msgbox(0, "", $result[1])
  msgbox(0, "", $result[2])

  Return $result[0]
EndFunc

Now, this works without crashing. I noticed that if I just run the script without compiling it, I get 0x014F8238, but 0x003B7ED8 compiled, and both are different than yours. I'm wondering if this is the address of the pointer vs. the value?

Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

That's the address of the array of handles. It's irrelevant in value.

Handles are read from the $tHandles ($aHwnd from your code) structure:

Local $hHandle1 = DllStructGetData($tHandles, 1, 1) 
;...

Ah! So the address of the device I get from the array, but the number of devices are from the return value. I verified that it works both ways since the value is now consistent. Thank you!
Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

I believe I'm getting the hang of this now. I've used AutoIt before, but I never got in so deep that ever tried interacting with DLLs. Here's my update test program:

Global $hPTROBOTDLL = DllOpen("PTRobot.dll")
Global $RobotAddress

PTRobot_Initialize()
$RobotAddress = PTRobot_EnumRobots()

msgbox(0, "", $RobotAddress)

PTRobot_GetRobotStatus()

Func PTRobot_Initialize()
  Local $result
  Local $err = @error

  $result = DllCall($hPTROBOTDLL, "int", "PTRobot_Initialize")

  if $result[0] Then
    MsgBox(0,"DllCall Error","DllCall Failed: PTRobot_Initialize")
    exit
  EndIf

EndFunc

Func PTRobot_EnumRobots()
  Local $result
  Local $err = @error

  Local $hRobots = DllStructCreate("hwnd[10]")
  Local $dwNumRobots

  $result = DllCall($hPTROBOTDLL, "int", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($hRobots), "dword*", 10)

  if $result[0] Then
    MsgBox(0,"DllCall Error","DllCall Failed: PTRobot_EnumRobots")
    exit
  EndIf

  Local $dwNumRobots = $result[2]

  ;msgbox(0, "", DllStructGetData($hRobots, 1, 1))
  ;msgbox(0, "", $dwNumRobots)

  Return DllStructGetData($hRobots, 1, 1)
EndFunc

Func PTRobot_GetRobotStatus()
  Local $result
  Local $err = @error

  Local $hRobot = DllStructCreate("hwnd")
  DllStructSetData($hRobot,1,$RobotAddress)
  Local $dRobotStatus = DllStructCreate("dword dwSystemState;dword dwSystemError;dword dwCurrColorSpits;dword dwCurrBlackSpits;dword dwFullColorSpits;dword dwFullBlackSpits")

  $result = DllCall($hPTROBOTDLL, "int", "PTRobot_GetRobotStatus", "ptr", DllStructGetPtr($hRobot), "ptr", DllStructGetPtr($dRobotStatus))

  msgbox(0, "Status", $result[0])

  msgbox(0, "", "System State: " & DllStructGetData($dRobotStatus, "dwSystemState") & @CRLF & _
                "System Error: " & DllStructGetData($dRobotStatus, "dwSystemError"))

  Return $result[0]
EndFunc

Thankfully, it doesn't crash anymore. However, the new function "PTRobot_GetRobotStatus" is returning a value of 502, which is PTROBOT_INVALID_ROBOT. Is it possible something got messed up when I passed the address around between variables? Here's the documentation for the PTRobot_GetRobotStatus function for the DLL:

2.2.3   PTRobot_GetRobotStatus
///////////////////////////
//
//  PTRobot_GetRobotStatus
//
//  Description:
//      Function to get the current status for a particular
//          robot.
//  Notes: Do NOT call in too tight of a loop (e.g. do not call more often 
//       than every 500ms or so).
//  Params:
//      hRobot      Handle to the robot (from EnumRobots)
//          pRobotStatus    points to a PTRobotStatus structure. 
//  Notes:
//  Return:
//          PTROBOT_OK if Successful
//      PTROBOT_SEQUENCE if this command is called out of sequence
//      PTROBOT_INTERNAL if an internal error occurred
//      PTROBOT_INVALID_ROBOT if the robot handle is invalid
//
///////////////////////////
DWORD WINAPI PTRobot_GetRobotStatus(HANDLE hRobot, PTRobotStatus *pRobotStatus);
Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

First param for PTRobot_GetRobotStatus function is Robot handle. There is no need to make it more complex than it is.

Do you understand what I'm saying?

Oh for cry-not-loud. I was so used to passing a pointer, I didn't even catch that all I needed was to send it the handle. Sorry. :graduated:

Edited by CPinzone
Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

Well, I've actually gotten really far. I've been able to control the robot to pick up a disc from a bin and put it into the printer. The problem is sending the filename to print.

2.3.7   PTRobot_PrintFile
///////////////////////////
//
//  PTRobot_PrintFile
//
//  Description:
//      Function to print a Surething image (.STD), raster image (.JPG, .BMP, .TIF, //      etc.), or  .PRN file to the printer.
//  Params:
//      hRobot      Handle to the robot (from EnumRobots)
//      tszFile     File to print (.STD, .PRN, .JPG, .BMP)
//      dwPrintIndex    Print index for multiple print jobs.
//  Notes:
//      The dwPrintIndex is used when printing an .STD file with merge fields.  This
//          value represents which merge record to use for this print.
//  Return:
//          PTROBOT_OK if Successful
//      PTROBOT_SEQUENCE if this command is called out of sequence
//      PTROBOT_INTERNAL if an internal error occurred
//      PTROBOT_INVALID_ROBOT if the robot handle is invalid
//      PTROBOT_NO_PRINTER if the robot doesn't have a printer
//      PTROBOT_PRN_INVALID if the prn file is not valid for the printer
//      PTROBOT_PRINTFILE_NOT_FOUND if the file doesn't exist
//      PTROBOT_PRINTAPP_NOT_INSTALLED if the required print application is not 
//          installed.
//      
///////////////////////////
DWORD WINAPI PTRobot_PrintFile(HANDLE hRobot, TCHAR * tszFile, DWORD dwPrintIndex);

How do I use DllCall to send a string? The DLLCall documentation doesn't even list "char" as a valid datatype. (I had another function that needed an array of chars inside of a struct, but the only thing passed in DllCall was a pointer to that struct.) I tried:

$result = DllCall($hPTROBOTDLL, "int", "PTRobot_PrintFile", "hwnd", $RobotAddress, "char*", "C:\filename.prn", "dword", 0)

but that didn't work.

Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

Does that mean you've got the whole thing working now? That would be cool.

:graduated:

Yes. It's working great. I've been working on the error handling today. I'd like to release the code as a beta for people to use (assuming they have access to the DLL files from Primera). It certainly isn't polished as much as I'd like, but it works really well and handles errors like discs in the wrong place or the cover open. I didn't write it with multiple robots/burners in mind since I don't have that kind of configuration and can't test it. I use IMGBurn as the burning engine via command line. I know IMGBurn can work with the robot directly, but it wont print labels and doesn't handle certain error conditions.

What's a good place to submit it? Is SourceForge a good place?

Gerard J. Pinzonegpinzone AT yahoo.com
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...