![JAR search and dependency download from the Maven repository](/logo.png)
com.pi4j.library.pigpio.PiGpioPacket Maven / Gradle / Ivy
Show all versions of pi4j-library-pigpio Show documentation
package com.pi4j.library.pigpio;
/*-
* #%L
* **********************************************************************
* ORGANIZATION : Pi4J
* PROJECT : Pi4J :: LIBRARY :: JNI Wrapper for PIGPIO Library
* FILENAME : PiGpioPacket.java
*
* This file is part of the Pi4J project. More information about
* this project can be found here: https://pi4j.com/
* **********************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import com.pi4j.library.pigpio.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
/**
*
* typedef struct
* {
* uint32_t cmd;
* uint32_t p1;
* uint32_t p2;
* union
* {
* uint32_t p3;
* uint32_t ext_len;
* uint32_t res;
* };
* } cmdCmd_t;
*
* @author Robert Savage (http://www.savagehomeautomation.com)
* @version $Id: $Id
*/
public class PiGpioPacket {
private static final Logger logger = LoggerFactory.getLogger(PiGpioPacket.class);
private PiGpioCmd cmd;
private int p1 = 0;
private int p2 = 0;
private int p3 = 0;
private byte[] data = new byte[0];
/**
* Constructor for PiGpioPacket.
*/
public PiGpioPacket(){
}
/**
* Constructor for PiGpioPacket.
*
* @param cmd a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
*/
public PiGpioPacket(PiGpioCmd cmd){
this.cmd(cmd);
}
/**
* Constructor for PiGpioPacket.
*
* @param cmd a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
* @param p1 a int.
*/
public PiGpioPacket(PiGpioCmd cmd, int p1){
this.cmd(cmd).p1(p1);
}
/**
* Constructor for PiGpioPacket.
*
* @param cmd a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
* @param p1 a int.
* @param p2 a int.
*/
public PiGpioPacket(PiGpioCmd cmd, int p1, int p2){
this.cmd(cmd).p1(p1).p2(p2);
}
/**
* Constructor for PiGpioPacket.
*
* @param cmd a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
* @param p1 a int.
* @param p2 a int.
* @param data an array of {@link byte} objects.
*/
public PiGpioPacket(PiGpioCmd cmd, int p1, int p2, byte[] data){
this.cmd(cmd).p1(p1).p2(p2).data(data);
}
/**
* cmd.
*
* @return a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
*/
public PiGpioCmd cmd(){
return this.cmd;
}
/**
* cmd.
*
* @param cmd a {@link com.pi4j.library.pigpio.PiGpioCmd} object.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket cmd(PiGpioCmd cmd){
this.cmd = cmd;
return this;
}
/**
* p1.
*
* @return a int.
*/
public int p1(){
return this.p1;
}
/**
* p1.
*
* @param p1 a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket p1(int p1){
this.p1 = p1;
return this;
}
/**
* p2.
*
* @return a int.
*/
public int p2(){
return this.p2;
}
/**
* p2.
*
* @param p2 a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket p2(int p2){
this.p2 = p2;
return this;
}
/**
* p3.
*
* @return a int.
*/
public int p3(){
return this.p3;
}
/**
* p3.
*
* @param p3 a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
protected PiGpioPacket p3(int p3){
this.p3 = p3;
return this;
}
// the following methods are actaully returning the "P3" value as P3
// is a C union and used for multiple purposes depending on context
/**
* result.
*
* @return a int.
*/
public int result(){
return p3();
}
/**
* success.
*
* @return a boolean.
*/
public boolean success(){
return p3() >= 0;
}
/**
* hasData.
*
* @return a boolean.
*/
public boolean hasData(){
if(this.data == null) return false;
return this.data.length > 0;
}
/**
* dataLength.
*
* @return a int.
*/
public int dataLength(){
if(this.data == null) return 0;
return this.data.length;
}
/**
* data.
*
* @return an array of {@link byte} objects.
*/
public byte[] data(){
return this.data;
}
/**
* data.
*
* @param data a {@link java.lang.CharSequence} object.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(CharSequence data){
return this.data(data.toString().getBytes(StandardCharsets.US_ASCII));
}
/**
* data.
*
* @param data an array of {@link byte} objects.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(byte[] data) {
return data(data, data.length);
}
/**
* data.
*
* @param data an array of {@link byte} objects.
* @param length a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(byte[] data, int length) {
return data(data, 0, data.length);
}
/**
* data.
*
* @param data an array of {@link byte} objects.
* @param offset a int.
* @param length a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(byte[] data, int offset, int length){
// check for valid data
if(data != null && data.length > 0 && length > 0) {
this.p3 = length;
this.data = Arrays.copyOfRange(data, offset, offset+length);
}
else{
this.p3 = 0;
this.data = new byte[0];
}
return this;
}
/**
* data.
*
* @param value a int.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(int value){
// check for valid value
if(value > 0) {
this.p3 = 4; // 4 bytes length
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(value);
this.data = buffer.array();
}
else{
this.p3 = 0;
this.data = new byte[0];
}
return this;
}
/**
* data.
*
* @param value a byte.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
*/
public PiGpioPacket data(byte value){
// check for valid value
if(value > 0) {
this.p3 = 4; // 4 bytes length
this.data = new byte[] { value, 0, 0, 0 }; // little endian
}
else{
this.p3 = 0;
this.data = new byte[0];
}
return this;
}
/**
* dataToString.
*
* @return a {@link java.lang.String} object.
*/
public String dataToString(){
if(data == null) return null;
if(data.length == 0) return "";
return new String(data, StandardCharsets.US_ASCII);
}
/**
* decode.
*
* @param stream a {@link java.io.InputStream} object.
* @return a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
* @throws IOException if an error occurs accessing {@code stream}.
*/
public static PiGpioPacket decode(InputStream stream) throws IOException {
// read only header bytes
byte[] header = stream.readNBytes(16);
ByteBuffer rx = ByteBuffer.wrap(header);
rx.order(ByteOrder.LITTLE_ENDIAN);
// parse packet parameters from raw received bytes
PiGpioCmd cmd = PiGpioCmd.from(rx.getInt()); // CMD <4 bytes :: 0-3>
int p1 = rx.getInt(); // P1 <4 bytes :: 4-7>
int p2 = rx.getInt(); // P2 <4 bytes :: 8-11>
int p3 = rx.getInt(); // P3 <4 bytes :: 12-15>
// create new packet
PiGpioPacket packet = new PiGpioPacket(cmd, p1, p2)
.p3(p3); // set RAW P3 value
int remaining = bytesToRead(packet, stream);
if(remaining > 0) {
var temp = stream.readNBytes(remaining);
packet.data(temp);
}
return packet;
}
/**
* The packet may indicate the number of bytes to expect from the stream.
*
* E.g. I2C packets provide this value via {@link PiGpioPacket#p3}
*
* @param packet the packet being read
* @param stream incoming data
* @return the number of bytes to expect to read from the input stream
* @throws IOException
*/
static int bytesToRead(PiGpioPacket packet, InputStream stream) throws IOException {
switch (packet.cmd) {
case I2CRI:
case I2CRD:
return packet.p3;
default:
return stream.available();
}
}
/**
*
encode.
*
* @param packet a {@link com.pi4j.library.pigpio.PiGpioPacket} object.
* @return an array of {@link byte} objects.
*/
public static byte[] encode(PiGpioPacket packet){
// create byte array and byte buffer using LITTLE ENDIAN for the ARM platform
byte[] bytes = new byte[16 + packet.dataLength()];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(ByteOrder.LITTLE_ENDIAN);
// place packet values into structured data bytes
buffer.putInt(packet.cmd().value()); // CMD
buffer.putInt((packet.p1())); //
buffer.putInt((packet.p2())); //
buffer.putInt((packet.p3())); //
if(packet.data != null && packet.data.length > 0) {
buffer.put(packet.data()); //
}
// return byte array
return bytes;
}
/** {@inheritDoc} */
@Override
public String toString(){
//if(this.data != null && this.data.length > 0)
if(p3() > 0)
return String.format("CMD=%s(%d); P1=%d; P2=%d; P3=%d; PAYLOAD=[0x%s]", cmd().name(), cmd().value(), p1(), p2(), p3(), StringUtil.toHexString(data()));
else
return String.format("CMD=%s(%d); P1=%d; P2=%d; P3=%d", cmd().name(), cmd().value(), p1(), p2(), p3());
}
}