drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Assign pi4j pins from text data?

Thu Feb 12, 2015 2:33 am

Hi,

I'm trying to make a pi4j project with text configurable pins to allow modification to the interface without having to recompile. Is it possible to do this?

For example I have a LimitSwitch sensor class with a single GpioPinDigitalInput pin field.

I then have an xml file with this data:

<pin name="pin" address="RaspiPin.GPIO_10" resistor="PULL_DOWN" /> where name is the name of the class field.
I was trying to assign the gpio.provisionDigitalInputPin() method using the values from the xml attributes using reflection.

I realise I may need to add a type attribute to take into account when a pin needs to be an input vs an output/digital vs analog but for now I'd like to get the code working with just digital inputs.

This is the code I have so far:

Code: Select all

public void setPins( Class<?> me, Element data ) {
        for( Element pinElem : data.getElementsByTag("pin") ) {
            if( pinElem.hasAttr("name") && pinElem.hasAttr("address") ) {
                Field pinField;
                try {
                    pinField = me.getField(pinElem.attr("name") );
                    if( pinField != null ) {
                        if( pinElem.hasAttr("resistor") ) {
                            pinField.set( this, Rover.gpio.provisionDigitalInputPin( pinElem.attr("address"), pinElem.attr("resistor") ) );                            
                        } else {
                            pinField.set( this, Rover.gpio.provisionDigitalInputPin( pinElem.attr("address") ) );
                        }
                    }
                } catch (NoSuchFieldException ex) {
                    Logger.getLogger(Module.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SecurityException ex) {
                    Logger.getLogger(Module.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                System.err.println("Invalid pin definition in module: " + data.attr("name") );
            }
        }
    }
Currently I'm getting the somewhat obvious error that you can't assign a pin from a String but am I on the right track? (Assuming this is even possible.)

EDIT:

Is it as simple as doing this?

GpioPinDigitalInput testPin = Rover.gpio.provisionDigitalInputPin( (Pin) Class.forName(pinElem.attr("address")).newInstance());

Thanks in advance.

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 10:13 am

OK so I figured it out for anyone who's interested.
Say you have an xml document that has a definition like:
<pin address="GPIO_04" name="triggerPin" type="digitalinput" resistor="pulldown" /> where name should be the same as the relevant class field e.g.

Code: Select all

class SomeGPIOInput {

    public GpioPinDigitalInput switchPin;

   public void setPins() {
      // Code below goes in here, this method would usually be in some sort of parent class and inherited by all sensors/inputs etc
   }
}
You can use code similar to this to dynamically assign the pins

Code: Select all

// Assuming the use of Jsoup for parsing of the XML.
// Assuming this code is being called from within the class that owns the pins itself
Class raspiPin = RaspiPin.class;
for( Element pinData : pinElems ) {
   String pin = pinData.attr("address");
   /* As the RaspiPin GPIO definitions are static we pass null as the get parameter because we don't need any specific instance to get a value back */
   Pin addrPin = (Pin) raspiPin.getField(pin).get(null);
   if( pinData.attr("type").equalsIgnoreCase("digitalinput") ) {
       GpioPinDigitalInput testPin = gpio.provisionDigitalInputPin( addrPin );
   } else {
      // You can probably work out how to do digital outputs and analogue pins from here
   }
   try {
        Field pinField = SomeGPIOInput.class.getField( pinData.attr("name") );
        pinField.set( this, testPin ); // If this is being called from an external configuration class you'll want to pass in the instance of your sensor class instead of "this".
   } catch( [VARIOUS_EXCEPTIONS_HERE] ) {
      // Do something with the errors.
   }
}
Obviously you should check the XML data is complete/correct before you start each iteration of the loop (by calling pinData.hasAttr("name") or pinData.hasAttr("address") etc) and there will be exceptions to be caught or thrown around the getting and setting of the pin field but I've left those out for readability (any decent IDE should tell you what exceptions need catching).

Hope this helps someone else. You can now use XML to change your Pi4J pins without having to recompile. I think it's kind of useful but probably not as useful as the time it took me to get it working.

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 10:24 am

Well done. :)

Only thing I wouldn't insist of doing is where you already have your class (SomeGPIOInput) - you can design special method like:

Code: Select all

public void setPin(String name, GpioPinDigitalInput pin) {
  if ("switchPin".equals(name)) { switchPin = pin; }
  if ("triggerPin".equals(name)) { triggerPin = pin; }
}
and avoid second set of reflection. Otherwise - that's pretty much it.

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 10:37 am

clicky wrote: and avoid second set of reflection. Otherwise - that's pretty much it.
Thanks, good point :)

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 11:01 am

You know what - even reflection of RaspiPin is not quite right. If you can to hold off your implementation and you don't mind taking the latest snapshot - I'll go tonight and add new method along the lines of:

public class RaspiPin {

public static Pin getPinByName(String name) { ... }
...
}

where name is same as in https://github.com/Pi4J/pi4j/blob/devel ... piPin.java for pin definitions. So, you'll need to replace ' ' with '_' in the name (and maybe call all pins with two digits, zero prefixed). Does that makes sense for you?

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 1:59 pm

I think it does :)

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 2:02 pm

If you don't mind building pi4j from source code - checkout develop branch and build it yourself. The method above is just pushed back in.

Alternatively - let me know how you created your project and we can think of something.

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 4:03 pm

Uuuh I just downloaded pi4j 0.0.5 and added the jar files as a library in Netbeans if that's what you mean? I did that because I'm developing on Windows then uploading to the Pi post compile.I can try building on the Pi then copying the jar files over to Windows.

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Wed Feb 18, 2015 4:07 pm

In that case I can send you 1.0-SNAPSHOT files so you can replace 0.0.5 ones with the latest.
I've just re-built it on my Pi (remotely).

Ideally I would like to see them in maven repo of some kind... (I'll be working on it now)

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Fri Feb 20, 2015 3:47 pm

Done (thanks to Robert). You can pick the latest from:
http://pi4j.com/download.html

There you'll find that com.pi4j.io.gpio.RaspiPin has static method getPinByName(String) where name is as defined in that class (check the source file) and is in format like:

"GPIO 0", "GPIO 1", ..., "GPIO 10", ...

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Fri Feb 20, 2015 3:58 pm

Cool thanks for that :) I'll give it a go in a little while.

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Sat Feb 21, 2015 11:59 pm

Hi,

Just trying it and I'm getting a weird error.

Code: Select all

Exception in thread "main" java.lang.ExceptionInInitializerError
        at com.drentsoft.rover.MotorChannelLoader.loadChannels(MotorChannelLoader.java:28)
        at com.drentsoft.rover.Rover.setup(Rover.java:115)
        at com.drentsoft.rover.Rover.<init>(Rover.java:47)
        at com.drentsoft.rover.Rover.main(Rover.java:262)
Caused by: java.lang.NullPointerException
        at com.pi4j.io.gpio.RaspiPin.createDigitalPin(RaspiPin.java:84)
        at com.pi4j.io.gpio.RaspiPin.<clinit>(RaspiPin.java:45)
        ... 4 more
I'm passing in an XML element in the form: <channel side="right" apin="GPIO 0" bpin="GPIO 1" />

The line that's throwing the error is:

Line 28:

Code: Select all

Pin aPin = RaspiPin.getPinByName( aPinName );
where aPinName has the value "GPIO 0" which I checked with a print statement just before the error gets thrown.

I'm calling

Code: Select all

gpio = GpioFactory.getInstance();
just before I call MotorChannelLoader.loadChannels() so I don't think it's because pi4j is uninitialised.

Any ideas what's going on?

Thanks

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 12:37 pm

Sorry - my mistake. I didn't try out the fix I had. I've sorted it out but give me a moment to test it. I'll post it here, sometime today, when it is ready.

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 2:17 pm

Much appreciated :)

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 5:29 pm

Robert has already picked it up and fixed it. You can try again. It should work now! O : )

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 5:40 pm

Cool that's fixed it! Thanks very much guys :)

drentsoft
Posts: 42
Joined: Thu May 31, 2012 7:13 pm
Location: Berkshire, England
Contact: Website

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 6:52 pm

Converted all the code to use getPinByName vs reflection, much more readable, thanks for doing that :) Now I just need to work on power regulation....

User avatar
clicky
Posts: 499
Joined: Thu Oct 25, 2012 7:34 am

Re: Assign pi4j pins from text data?

Sun Feb 22, 2015 7:11 pm

Glad we could help! :)
It makes far more sense having that extra simple method. Next time check the source out (from github would be the best, but source jar would work, too) and if you have improvements like that in mind - submit a change back to us! It is, after all, social, open source code, isn't it?

Return to “Java”