andrewjfox Posted August 30, 2012 Share Posted August 30, 2012 Hi , I've been using objects for ports and devices in an existing project but am still getting some behaviour which I don't understand I am trying to close and -reopen a ethernet connection as follows //Instatiate objects, and open connections define CTRL_PORT = 0define RADIO_PORT = 1class DeviceObj local iDevice local RxBuff local State function OnCreate() iDevice = new(CCommDevice) State = DEVICE_STATE_CLOSED endfunctionendclassglobal MyDeviceglobal MyPortfor(private i=0,i<MAX_READERS,i++) MyPort[i*2 + CTRL_PORT] = new(CCommEthernet) MyDevice[i*2 + CTRL_PORT] = new(DeviceObj) MyPort[i*2 + RADIO_PORT] = new(CCommEthernet) MyDevice[i*2 + RADIO_PORT] = new(DeviceObj) OpenConnection(i)endfor[/CODE]// functions to open & close connections[CODE]function OpenConnection(ReaderIndex) private pDevice private pPort try pDevice = MyDevice[ReaderIndex*2 + CTRL_PORT] if(pDevice.State == DEVICE_STATE_CLOSED) pPort = MyPort[ReaderIndex*2 + CTRL_PORT] pPort.Address = strAddressBase + DoubleToStr(DeviceAddress[ReaderIndex]) pPort.Port = CPORT pPort.Timeout = 1000 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + CTRL_PORT] pDevice.iDevice.ProtocolName = "NULL Protocol" pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_OPEN endif pDevice = MyDevice[ReaderIndex*2 + RADIO_PORT] if(pDevice.State == DEVICE_STATE_CLOSED) pPort = MyPort[ReaderIndex*2 + RADIO_PORT] pPort.Address = strAddressBase + DoubleToStr(DeviceAddress[ReaderIndex]) pPort.Port = RPORT pPort.Timeout = 1000 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + RADIO_PORT] pDevice.iDevice.ProtocolName = "NULL Protocol" pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_OPEN endif catch() Event.AddValue(Format("Error: Rdr%02d, ",ReaderIndex)+strLastError) endcatchendfunctionfunction CloseConnection(ReaderIndex) private pDevice private pPort //try pDevice = MyDevice[ReaderIndex*2 + CTRL_PORT] pPort = MyPort[ReaderIndex*2 + CTRL_PORT] pPort.Address = "" pPort.Port = 0 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + CTRL_PORT] pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_CLOSED pDevice = MyDevice[ReaderIndex*2 + RADIO_PORT] pPort = MyPort[ReaderIndex*2 + RADIO_PORT] pPort.Address = "" pPort.Port = 0 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + RADIO_PORT] pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_CLOSED //catch() // Event.AddValue(Format("Error: Rdr%02d, ",ReaderIndex)+strLastError) //endcatch endfunction[/CODE]When I call the CloseConnection function I get an error at the InitComm() functionCloseConnection(0)C1000 Channel or function not found: CloseConnection Line 15: Line 1My understanding is that the InitComm() call should be successful regardless of whether connection is open /closed. Do you have any ideas for me to try?Also I tried including the port object in my device objectclass DeviceObj local iDevice local RxBuff local State function OnCreate() iDevice = new(CCommDevice) State = DEVICE_STATE_CLOSED endfunctionendclassRegardsAndrew Link to comment Share on other sites More sharing options...
AzeoTech Posted August 30, 2012 Share Posted August 30, 2012 Hmm, I count line 15 as this line: pDevice = MyDevice[ReaderIndex*2 + RADIO_PORT] That error isn't an error initComm() would generate unless the object didn't have an initComm() function. Link to comment Share on other sites More sharing options...
andrewjfox Posted August 31, 2012 Author Share Posted August 31, 2012 In the sequence line numbering, line 15 is the initComm line. Is this one of those instances where, because I'm using objects, the error message is not pointing to where I think it's pointing? I had also meant to ask about including port object in my MyDevice object but accidentally submitted the post before finishing. As I started to mention, I tried including the port object in MyDevice object class DeviceObj Link to comment Share on other sites More sharing options...
AzeoTech Posted August 31, 2012 Share Posted August 31, 2012 Yes, this is one of the reasons OOP is not a documented feature. The line number specified is from the beginning of the member function, where the "function xxx" is line 1. Link to comment Share on other sites More sharing options...
andrewjfox Posted September 6, 2012 Author Share Posted September 6, 2012 Hi, after some more testing I'm pretty sure the problem occurs at the .InitComm() line As above I have 8 device objects instantiated thusly; class DeviceObj local iDevice local RxBuff local State function OnCreate() iDevice = new(CCommDevice) State = DEVICE_STATE_CLOSED endfunctionendclassglobal MyDeviceglobal MyPortNumReaders = 4for(private i=0,i<NumReaders,i++) MyPort[i*2 + CTRL_PORT] = new(CCommEthernet) MyDevice[i*2 + CTRL_PORT] = new(DeviceObj) MyPort[i*2 + RADIO_PORT] = new(CCommEthernet) MyDevice[i*2 + RADIO_PORT] = new(DeviceObj) OpenConnection(i) // additional stuff hereendfor[/CODE][CODE]function OpenConnection(ReaderIndex) private pDevice private pPort// try pDevice = MyDevice[ReaderIndex*2 + CTRL_PORT] //if(pDevice.State == DEVICE_STATE_CLOSED) pPort = MyPort[ReaderIndex*2 + CTRL_PORT] pPort.Address = strAddressBase + DoubleToStr(DeviceAddress[ReaderIndex]) pPort.Port = CPORT pPort.Timeout = 1000 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + CTRL_PORT] pDevice.iDevice.ProtocolName = "NULL Protocol" pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_OPEN //endif pDevice = MyDevice[ReaderIndex*2 + RADIO_PORT] //if(pDevice.State == DEVICE_STATE_CLOSED) pPort = MyPort[ReaderIndex*2 + RADIO_PORT] pPort.Address = strAddressBase + DoubleToStr(DeviceAddress[ReaderIndex]) pPort.Port = RPORT pPort.Timeout = 1000 pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + RADIO_PORT] pDevice.iDevice.ProtocolName = "NULL Protocol" pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_OPEN //endif// catch()// Event.AddValue(Format("Error: Rdr%02d, ",ReaderIndex)+strLastError)// endcatchendfunction[/CODE]when I try to close the connection using following I get an error at the InitComm(). (I stepped through the sequence and the error definitely occurs when trying to execute the InitComm() line)[CODE]//function CloseConnection(ReaderIndex)private ReaderIndex = 1 private pDevice private pPort// try pDevice = MyDevice[ReaderIndex*2 + CTRL_PORT] pPort = MyPort[ReaderIndex*2 + CTRL_PORT] pPort.Address = "" pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + CTRL_PORT] ? MyDevice[].iDevice.Address ? MyDevice[].iDevice.Port pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_CLOSED pDevice = MyDevice[ReaderIndex*2 + RADIO_PORT] pPort = MyPort[ReaderIndex*2 + RADIO_PORT] pPort.Address = "" pDevice.iDevice.PortObject = MyPort[ReaderIndex*2 + RADIO_PORT] pDevice.iDevice.InitComm() pDevice.State = DEVICE_STATE_CLOSED// catch()// Event.AddValue(Format("Error: Rdr%02d, ",ReaderIndex)+strLastError)// endcatch//endfunction[/CODE]if, however, I replace the linepDevice.iDevice.InitComm()withMyDevice[ReaderIndex*2 + CTRL_PORT].iDevice.InitComm()it works ok.I know that the objects can be funny about using brackets on both sides, is it possible that for object function calls I need to use the actual object, MyDevice[2].iDevice.InitComm() rather than a pointer like pDevice.iDevice.InitComm()RegardsAndrew Link to comment Share on other sites More sharing options...
AzeoTech Posted September 6, 2012 Share Posted September 6, 2012 I'd be more apt to think that the second version (the one that works) isn't doing what you think it is. Instead of initing [readerIndex*2 + CTRL_PORT] its doing [0] because of a bug in how DAQFactory parses it. In fact, to get around this bug (which may be fixed, I don't remember), I often do what you did with pDevice, so I doubt that is the problem, though anything is possible. Are you using a USB -> Serial converter? Can you create a blank document, then try creating a normal device for that port (not dynamically), then see if initcomm() works on it using device.myDevice.initComm(). Link to comment Share on other sites More sharing options...
andrewjfox Posted September 7, 2012 Author Share Posted September 7, 2012 -bug in parsing ? Is it a problem using calculations in indexes in general, or only for objects? Can I use a calculated variable to solve eg private index = readerindex*2 + CTRL_PORT, then MyDevice[index]. How do I assign the object pointer if there is a problem with the indexing ie pDevice = MyDevice[???] -the devices are TCP, does initcomm attempt to open the TCP connection, and will it fail gracefully if it can't make the connection? I will put a test file together to try and isolate the problem as suggested Andrew Link to comment Share on other sites More sharing options...
andrewjfox Posted September 8, 2012 Author Share Posted September 8, 2012 Have done a few quick tests, as suggested. Created blank document and new devices using configuration wizard Device1Ctrl, Device1Radio, Device2Ctrl and Device2Radio Tried opening and closing first using Device.Device1Ctrl.InitComm(), etc then using private pDevice = Device.Device1Ctrl and pDevice.InitComm() following is output from attached test doc "comms_test.ctrl". Opening connections Closing connections Reopening connections with ptrs 09/08/12 13:43:56.941 C1000 Channel or function not found: startup Line 44 - Uncaught error in sequence startup using pDevice.InitComm(), at least on my system, throws an error. If this is the case then it might also explain why I am getting irregular errors when calling .Read & .Write functions using ptrs. It works sometimes, but not others. Up till know I have been assuming the end devices are causing all the problems. If ptrs only work in some cases, I need to know the guidelines for usage. Please I need a practical fix/workaround asap, . Eagerly awaiting reply, Andrew comms_test.ctl Link to comment Share on other sites More sharing options...
AzeoTech Posted September 14, 2012 Share Posted September 14, 2012 The sample you did doesn't work because although device.myDevice looks like an object, its not a user object so can't be assigned to another variable. You can only do this with comm objects created dynamically using new(). Perhaps that's your problem? Are you trying to reference devices created in with "New Serial / Ethernet device"? Link to comment Share on other sites More sharing options...
andrewjfox Posted September 14, 2012 Author Share Posted September 14, 2012 My apologies, I misunderstood the intention of your post #6. No, in the actual application, all of the devices are created dynamically. In the test doc (comms_test.ctl) I'm opening connections to the same, real, devices as in the actual application. My concern is not that one or the other method of referencing object functions doesn't work, but that it appears to be inconsistent, sometimes working, but not others, and I don't see how this is device dependent since a function (any function) can only succeed or fail after it's been called. It shouldn't throw an exception before attempting to call the function, on the expectation that the device comms may or may not fail, should it? Which method will work 100% of the time - indexed objects ie MyDevice[index].Device.InitComm() - or can I use pointer reference such as pDevice = MyDevice[index].Device, and pDevice.InitComm() Link to comment Share on other sites More sharing options...
AzeoTech Posted September 14, 2012 Share Posted September 14, 2012 Remember, DAQFactory is an interpretted language. This means a function can fail without being called if DAQFactory can't find the function. DAQFactory doesn't look up the functions at compile time, it does it at runtime. This is why you can create a function that references non-existant channels or other objects and compile it, and then add the channels or other objects later. Anyhow, there is a bug in some versions of DAQFactory that makes it so you can't have more than one [] or () in the function specification. This means that x[index].foo() won't work, though x[index].myVar will. The workaround is what you described second: z = x[index] z.foo() Link to comment Share on other sites More sharing options...
andrewjfox Posted September 15, 2012 Author Share Posted September 15, 2012 This brings us back to the original post, when I do this the function can't be found See above for more details but basically I have several dynamically created objects MyDevice[], each containing a device object, iDevice which is instatiated using the OnCreate function of the parent object, iDevice = new(CComDevice). The whole object is then referenced using a pointer. private pDevice = MyDevice[index] then calling the InitComm function using pDevice.iDevice.InitComm(), which fails with error C1000 Channel or function not found calling MyDevice[index].iDevice.InitComm() works ok, however you suggest that the indexing is wrong, please explain further. I've changed the application in the (numerous) field systems so that it's using the indexing method MyDevice[index].iDevice.InitComm(), however from the content of this thread I'm not confident that this is working correctly either, it's just not throwing exceptions. I'm having comms problems in the field but so far I've been unable to determine if it's DF comms issues or the physical devices. I've already tested that InitComm isn't failing because of the physical device, there must be a software issue, perhaps something to do with the pointer referencing. Andrew Link to comment Share on other sites More sharing options...
andrewjfox Posted September 20, 2012 Author Share Posted September 20, 2012 Sorry to hassle you guys again, but you're suggestions aren't working and I'm still having trouble understanding what's going on with objects and InitComm() Have been doing some testing to try and demonstrate what I'm seeing and have attached the following EchoServer.exe Echo server is a basic TCP server on ports 1515 & 1516 that displays messages when clients connect/disconnect and echos any data received back to client Test.ctl - This is my test doc, it opens TCP connections using dynamic comm devices to local 127.0.0.1 and ports 1515 & 1516 You'll see that towards the end I have setup 2 options for closing the connection however, OPTION = 0, trying to clear TCP address by writing to MyDevice.iDevice.Address = "", however this approach throws an error when it gets to InitComm() which should be closing the connection. From looking at the server console it does appear to close the connection before throwing the error OPTION = 1, clear the port object address, then assign the port object to the device, this has no errors, but doesn't close the connection. When I write to port after it is suppossedly closed, the echo works fine, almost as if it re-opens the connection even though the address should be "". I'm doing all the things you've suggested in regards referencing objects using pointers, and clearing the port address before calling InitComm() to close the connection, but either approach I take doesn't work correctly Please have a look and let me know if the problems is something I've done, or don't understand or other. Test.zip Test.zip Link to comment Share on other sites More sharing options...
AzeoTech Posted September 20, 2012 Share Posted September 20, 2012 It appears that the port doesn't like that you set address to "". Try setting Port to -1 instead and see if that gives you the desired result. Link to comment Share on other sites More sharing options...
andrewjfox Posted September 24, 2012 Author Share Posted September 24, 2012 Thanks, that seems to work bit better. When I close the connection the only error is when I try to call .Write later which makes sense. I do still have a problem in regards modifying the port parameters When I instatiate the port object MyPort[index] = new(CCommEthernet) then assign values MyPort[index].Address = "127.0.0.1" MyPort[index].Port = 1515 then assign port to device pDevice.PortObject = MyPort[index] This all works ok first time. If I want to change port values do I change the port object then reassign MyPort[index].Port = -1 then pDevice.Portobject = MyPort[index] OR change device values directly pDevice.Port = -1 When I change Port to -1 to close connection then it doesn't assign value to device eg MyPort[index].Port = -1 pDevice.Portobject = MyPort[index] ? pDevice.Port // displays 1515, value of port hasn't changed versus pDevice.Port = -1 ? pDevice.Port // displays 4294967295 I had thought that assigning port object to the device is just like assigning a pointer, rather than a param copy, so any changes to the port object would be reflected in the device params. Regards Andrew Link to comment Share on other sites More sharing options...
AzeoTech Posted September 25, 2012 Share Posted September 25, 2012 I can't really say. This is why this is an undocumented feature. You have to experiment to see what works. OOP is generally undocumented, but has only a couple issues. Using internal objects as user oop objects however has a few extra issues, and this I guess is one. The other that I can think of is that ToJson() and fromJson() don't work. 4294967295 is -1 by the way. Port is an unsigned long, so -1 gets translated to the biggest unsigned value an unsigned long can hold. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.