VeriStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Custom device with factory pattern : problem generating engine llb

Solved!
Go to solution

Hi !

I'm developping a custom device with the RT part adapting it's behaviour according to some parameters set in the configuration part (system explorer). 90% of the functions will all behave the same way; but only few functions will be specific according to these settings.

That is why I naturally made the custom device using OO with the purpose to use inheritance. So I have a Parent class which holds 90% of the running code and few childs overriding functions to adapt the 10% that is varying from one setting to another. Childs are instanciated using a factory pattern : one particular setting is determining the child object to load.

 

The problem comes when trying to build the engine LLB. Childs are loaded dynamically so I set theses classes to be always included. When I do so, LV says that it prevents collision renaming some functions. These fuctions are the overrides in my childs... Pointed VIs are then not embedded in the LLB (and therefore not deployed on my target).

If I don't add the childs to Always Included VIs, then the output of the build is the llb but the code never runs correctly : when deploying it says that RT engine VI is broken.

 

How can I do to make things working ? Is there a solution to force embedding the classes into the llb without LV saying that it prevents conflicts ? Or is there a way to deploy more files than only the engine llb ?

 

Thank you for your answers !

CLA, CTA, LV Champion
View Cyril Gambini's profile on LinkedIn
This post is made under CC BY 4.0 DEED licensing
0 Kudos
Message 1 of 11
(4,479 Views)
Solution
Accepted by topic author CyGa

llbs are basically like folders: you cannot have 2 files having the same name, so overrides/OOP don't work with llbs. This is why LabVIEW ditches you when building the llb.

Basically, when distributing plugins using the factory pattern, you build one core app/distro which contains the parent class and the core components, and then you distribute every single child class in its own llb, while making sure to exclude the parent class from those (if you explicitly don't, LV will try to add it because it's a dependency for the child).

Another possibility is to create packed libraries (.lvlibp), but that will compromise your current design.

 

In both case, make sure the children llb/lvlibp files are added as a dependency of the engine llb in the Custom Device XML file, otherwise VeriStand will not deploy them to the target.

 

Finally, generally speaking, OOP is rarely a great idea when developing custom devices (I'm the first one to be sad with that statement). But, then again, good luck 🙂

Regards,

Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.

Message 2 of 11
(4,418 Views)

Hi Eric,

Thank you for the answer !

It would have been better to know this BEFORE building the Custom Device. I haven't seen anywhere that this is not recommanded to use OOP when creating CusDevs.

Any way I'll try the lvlibp option. So that all childs to my main parent class can be a single lvlibp plugin...

Can you tell if I'm right :

  • lvlibp must only contain child override /unique functions (no dependencies of any kind (vi.lib, driverrs, etc..))
  • lvlibp should be in the Always included section of the llb

That's it ?

Another question that I have : must an overriden function have the same name that the parent source function ? If not, maybe I can just rename the override functions...

CLA, CTA, LV Champion
View Cyril Gambini's profile on LinkedIn
This post is made under CC BY 4.0 DEED licensing
0 Kudos
Message 3 of 11
(4,407 Views)

Any way I'll try the lvlibp option. So that all childs to my main parent class can be a single lvlibp plugin...

Can you tell if I'm right :

  • lvlibp must only contain child override /unique functions (no dependencies of any kind (vi.lib, driverrs, etc..))
  • lvlibp should be in the Always included section of the llb

 


In fact the real question is whether you will need to add more children classes in the future. If not, you can just bundle all your classes into one single lvlibp. Think scalibility 🙂

 

Another question that I have : must an overriden function have the same name that the parent source function ? If not, maybe I can just rename the override functions...


Yes. The LV compiler needs it to choose which override to execute at run-time. Basically all the other OOP languages I know work like this.

 

Good luck there 🙂

Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.

0 Kudos
Message 4 of 11
(4,397 Views)

Hi Eric,

 

I changed my program to build lvlips file for each plugin i'll use.

I'm at the point I should add these plugins into the xml file so that they are deployed on my target.

Would you have an XML example so that I'm sure that I'm not doing any wrong ?

 

original XML :

<CustomDeviceVI>
<SourceDistribution>
<Source>
<SupportedTarget>PharlapWindows</SupportedTarget>
<Source>
<Type>To Common Doc Dir</Type>
<Path>Custom Devices\Satellite\Satellite Engine.llb\Satellite RT Driver VI.vi</Path>
</Source>
<RealTimeSystemDestination>c:\ni-rt\VeriStand\Custom Devices\Satellite\Satellite Engine.llb\Satellite RT Driver VI.vi</RealTimeSystemDestination>
</Source>
</SourceDistribution>
</CustomDeviceVI>

CLA, CTA, LV Champion
View Cyril Gambini's profile on LinkedIn
This post is made under CC BY 4.0 DEED licensing
0 Kudos
Message 5 of 11
(4,369 Views)

You can put the .lvlibp files in the Dependencies section to have them deployed.  Here's an example from the Scan Engine and EtherCAT custom device:

  <CustomDeviceVI>
    <SourceDistribution>
      <Source>
        <SupportedTarget>PharlapWindows</SupportedTarget>
        <Source>
          <Type>To Common Doc Dir</Type>
          <Path>Custom Devices\Scan Engine\PharLap\Scan Engine RT Driver.vi</Path>
        </Source>
        <RealTimeSystemDestination>c:\ni-rt\NIVeriStand\Custom Devices\Scan Engine\Scan Engine RT Driver.vi</RealTimeSystemDestination>
      </Source>
      <Source>
        <SupportedTarget>VxWorks</SupportedTarget>
        <Source>
          <Type>To Common Doc Dir</Type>
          <Path>Custom Devices\Scan Engine\VxWorks\Scan Engine RT Driver.vi</Path>
        </Source>
        <RealTimeSystemDestination>c:\ni-rt\NIVeriStand\Custom Devices\Scan Engine\Scan Engine RT Driver.vi</RealTimeSystemDestination>
      </Source>
    </SourceDistribution>
  </CustomDeviceVI>
  <Dependencies>
    <Dependency>
      <SupportedTarget>PharlapWindows</SupportedTarget>
      <Source>
        <Type>To Common Doc Dir</Type>
        <Path>Custom Devices\Scan Engine\PharLap\Modules.lvlibp</Path>
      </Source>
      <RealTimeSystemDestination>c:\ni-rt\NIVeriStand\Custom Devices\Scan Engine\Modules.lvlibp</RealTimeSystemDestination>
    </Dependency>
    <Dependency>
    <Dependency>
      <SupportedTarget>VxWorks</SupportedTarget>
      <Source>
        <Type>To Common Doc Dir</Type>
        <Path>Custom Devices\Scan Engine\VxWorks\Modules.lvlibp</Path>
      </Source>
      <RealTimeSystemDestination>c:\ni-rt\NIVeriStand\Custom Devices\Scan Engine\Modules.lvlibp</RealTimeSystemDestination>
    </Dependency>
  </Dependencies>
0 Kudos
Message 6 of 11
(4,363 Views)

Hi Devin,

 

The XML you provided very looks like the one I had.

Except that I added ForceDownload tag (found this one in NIVS Help). Obviously with this tag the XML is considered not valid by VeriStand. As soon as I removed it, XML has been accepted...

Is it a bug somewhere or I was wrong using ForceDownload in the dependency section?

 

Eric,

My construction with the LVLIBP seems to work fine... on the developement side. I've got no error, llb is built and automatically embeds all lvlibp files in the construction folder. When deploying the engine.llb and lvlibp files are sent to the cRIO... But when lauching the RT Driver.vi here is the message I see : 

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
The VeriStand Gateway encountered an error while deploying the System Definition file.

Details:
Error 1003 occurred at Project Window.lvlib:Project Window.vi >> Project Window.lvlib:Command Loop.vi >> NI_VS Workspace ExecutionAPI.lvlib:NI VeriStand - Connect to System.vi

Possible reason(s):

LabVIEW: Le VI n'est pas exécutable. Cette erreur peut se produire si le VI est brisé ou s'il contient un sous-VI que LabVIEW ne trouve pas. Sélectionnez Fichier>>Ouvrir pour ouvrir le VI et vérifiez que vous pouvez l'exécuter.
=========================
NI VeriStand: Open VI Reference in NI VeriStand Engine.lvlib:Open Custom Device Driver VI Reference.vi->NI VeriStand Engine.lvlib:Launch Asynchronous Custom Device.vi->NI VeriStand Engine.lvlib:VeriStand Engine State Machine.vi->NI VeriStand Engine.lvlib:VeriStand Engine.vi->NI VeriStand Engine.lvlib:VeriStand Engine Wrapper (RT).vi<APPEND>
c:\ni-rt\VeriStand\Custom Devices\Satellite\Satellite Engine.llb\Satellite RT Driver VI.vi

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

It doesn't help a lot to understand what is going wronghere. Would you have any advice to help me debug this issue ?

I tried downloading the llb and lvlibp sent to the cRIO in a temp folder and open the RT driver VI : it opens fine without any error...

CLA, CTA, LV Champion
View Cyril Gambini's profile on LinkedIn
This post is made under CC BY 4.0 DEED licensing
0 Kudos
Message 7 of 11
(4,353 Views)

ForceDownload should be accepted.  My only thought is that maybe you have things in the wrong order.  The custom device XML is pretty particular about which order the tags appear in.  In the case of ForceDownload, it should appear under a Dependency, after the "RealTimeSystemDefinition" tag, and before any Version tag (if you have one).  When in doubt, take a look at the "Custom Device.xsd".  Here's a snippet with ForceDownload:

 

<xs:element name="Dependencies">
  <xs:complexType>
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Dependency">
        <xs:complexType>
          <xs:sequence>
            <xs:element minOccurs="0" name="SupportedTarget" type="Target" />
            <xs:element name="Source" type="Path" />
            <xs:element name="RealTimeSystemDestination" type="xs:string" />
            <xs:element minOccurs="0" default="false" name="ForceDownload" type="xs:boolean" />
            <xs:element minOccurs="0" name="Version" type="xs:string" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>
0 Kudos
Message 8 of 11
(4,345 Views)

Hi Devin,

 

Indeed my tag was misplaced. Works fine now !

 

Hi Eric,

lvlibp was not the good idea : my classes contains methods for both configuration (Windows side) and execution (RT side). As lvlibp contains only the compiled code, it was only containing the compiled code for the windows side (geenration side). Configuration was working fine but when deploying RT Driver VI was broken.

So I changed (again) my code to encapsulate each class as llb : child classes inherits from parent class generated after compiling the parent llb.

I added the llb as dependencies and forced the download (to be sure that the newest files are sent to the target). And it works like a charm : code in the llb are interpreted according to the side playing it (Windows or RT) and the factory patterns works.

 

Thank you for your help !

CLA, CTA, LV Champion
View Cyril Gambini's profile on LinkedIn
This post is made under CC BY 4.0 DEED licensing
Message 9 of 11
(4,333 Views)

CyGa,

I am trying to follow your exact solution but I am getting an error 1124 from "Get LV Class Default Value.vi" (factory pattern) when trying to load a child class from dependent LLB file.  The paths are correct.  Any idea why this is happening?

 

Thanks,

Eric 

CLA, CTA

 

0 Kudos
Message 10 of 11
(2,784 Views)