package it.mazzoni.i2c;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import it.freedomotic.api.EventTemplate;
import it.freedomotic.api.Protocol;
import it.freedomotic.app.Freedomotic;
import it.freedomotic.events.ProtocolRead;
import it.freedomotic.exceptions.UnableToExecuteException;
import it.freedomotic.reactions.Command;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class i2c extends Protocol {
final int POLLING_WAIT;
private I2CDevice dev;
private I2CBus bus;
private GpioPinDigitalInput i2c_int;
private ArrayList<Board> boards;
private int DEV_NUMBER;
// address = dev_i2c_address: line_number
private String[] address = null;
public i2c() {
//every plugin needs a name and a manifest XML file
super("i2c", "/i2c/i2c-manifest.xml");
//read a property from the manifest file below which is in
//FREEDOMOTIC_FOLDER/plugins/devices/it.freedomotic.hello/hello-world.xml
POLLING_WAIT = configuration.getIntProperty("time-between-reads", 2000);
//POLLING_WAIT is the value of the property "time-between-reads" or 2000 millisecs,
//default value if the property does not exist in the manifest
setPollingWait(POLLING_WAIT); //millisecs interval between hardware device status reads
}
@Override
protected void onShowGui() {
/**
* uncomment the line below to add a GUI to this plugin the GUI can be
* started with a right-click on plugin list on the desktop frontend
* (it.freedomotic.jfrontend plugin)
*/
//bindGuiToPlugin(new HelloWorldGui(this));
}
@Override
protected void onHideGui() {
//implement here what to do when the this plugin GUI is closed
//for example you can change the plugin description
setDescription("My GUI is now hidden");
}
@Override
protected void onRun() {
Freedomotic.logger.info("I2C onRun() logs this message every "
+ "POLLINGWAIT=" + POLLING_WAIT + "milliseconds");
//at the end of this method the system waits POLLINGTIME
//before calling it again. The result is this log message is printed
//every 2 seconds (2000 millisecs)
}
@Override
protected void onStart() {
Freedomotic.logger.info("I2C plugin is started");
try {
bus = I2CFactory.getInstance(I2CBus.BUS_0);
} catch (IOException ex) {
Logger.getLogger(i2c.class.getName()).log(Level.SEVERE, null, ex);
}
// provision gpio pin #02 as an input pin with its internal pull down resistor enabled
// (configure pin edge to both rising and falling to get notified for HIGH and LOW state
// changes)
i2c_int = GpioFactory.getInstance().provisionDigitalInputPin(RaspiPin.GPIO_02, // PIN NUMBER
"MyButton", // PIN FRIENDLY NAME (optional)
PinPullResistance.PULL_DOWN); // PIN RESISTANCE (optional)
// create and register gpio pin listener
i2c_int.addListener(new GpioPinListenerDigital() {
@Override
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// display pin state on console
System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
// scan i2c Bus for changes
for (Board board : boards) {
try {
dev = bus.getDevice(board.getAddress());
int globVal = dev.read();
int val = 0;
for (int i = 0; i < 8; i++) {
val = (globVal >> i) & 0x0001; //extract i-pos bit of byte
if (board.setLineStatus(i, val)) {
String EVaddress = board.getAddress() + ":" + i;
notifyChangeEvent(EVaddress, val);
}
}
} catch (IOException ex) {
Logger.getLogger(i2c.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
DEV_NUMBER = configuration.getTuples().size();
int devAddr;
int devNum;
String alias;
for (int i = 0; i < DEV_NUMBER; i++) {
devAddr = configuration.getTuples().getIntProperty(i, "address", 0);
devNum = configuration.getTuples().getIntProperty(i, "line-number", 0);
alias = configuration.getTuples().getStringProperty(i, "alias", "");
boards.add(new Board(devAddr, devNum, alias));
}
}
@Override
protected void onStop() {
Freedomotic.logger.info("I2C plugin is stopped ");
try {
bus.close();
} catch (IOException ex) {
Logger.getLogger(i2c.class.getName()).log(Level.SEVERE, null, ex);
}
i2c_int.unexport();
boards.clear();
boards = null;
}
@Override
protected void onCommand(Command c) throws IOException, UnableToExecuteException {
Freedomotic.logger.info("I2C plugin receives a command called " + c.getName()
+ " with parameters " + c.getProperties().toString());
String delimiter = configuration.getProperty("address-delimiter");
address = c.getProperty("address").split(delimiter);
int line = Integer.parseInt(address[1]);
int value = 0;
if (c.getProperty("command").equals("TURN-ON")) {
value = 1;
} else if (c.getProperty("command").equals("TURN-OFF")) {
value = 0;
} else if (c.getProperty("command").equals("SWITCH")) {
value = -1;
}
for (Board board : boards) {
if ((board.getAddress() == Integer.parseInt(address[0])) || (board.getAlias().equals(address[0]))) {
short lineID = Short.parseShort(address[1]);
dev = bus.getDevice(board.getAddress());
dev.write(board.toBeWritten(line, value));
}
}
}
private void notifyChangeEvent(String device_address, int val) {
Freedomotic.logger.log(Level.INFO, "Sending I2C protocol read event for object address ''{0}''. It''s readed status is {1}", new Object[]{device_address, val});
//building the event
ProtocolRead event = new ProtocolRead(this, "i2c", device_address); //IP:PORT:RELAYLINE
if (val == 1) {
event.addProperty("isOn", "true");
} else {
event.addProperty("isOn", "false");
}
//adding some optional information to the event
//event.addProperty("boardIP", board.getIpAddress());
//event.addProperty("boardPort", new Integer(board.getPort()).toString());
//event.addProperty("relayLine", new Integer(relayLine).toString());
//publish the event on the messaging bus
this.notifyEvent(event);
}
@Override
protected boolean canExecute(Command c) {
//don't mind this method for now
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
protected void onEvent(EventTemplate event) {
//don't mind this method for now
throw new UnsupportedOperationException("Not supported yet.");
}
}