Skip to content

Commit

Permalink
Adding support for configurable ON/OFF states; #93
Browse files Browse the repository at this point in the history
  • Loading branch information
savageautomate committed Oct 26, 2021
1 parent 955480f commit 1c06841
Show file tree
Hide file tree
Showing 12 changed files with 777 additions and 21 deletions.
12 changes: 10 additions & 2 deletions pi4j-core/src/main/java/com/pi4j/io/gpio/digital/DigitalBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,15 @@ public DIGITAL_TYPE shutdown(Context context) throws ShutdownException {
/** {@inheritDoc} */
@Override
public boolean isOn() {
// TODO :: REVISIT STATE VS ON/OFF
return state().isHigh();
// the default ON state is HIGH
DigitalState onState = DigitalState.HIGH;

// get configured ON state
if(config().onState() != null){
onState = config().onState();
}

// return TRUE if the current state matches the configured ON state
return state().equals(onState);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,22 @@
* @version $Id: $Id
*/
public interface DigitalConfig<CONFIG_TYPE extends Config> extends GpioConfig<CONFIG_TYPE> {
// MARKER INTERFACE

/** Constant <code>ON_STATE_KEY="onstate"</code> */
String ON_STATE_KEY = "onstate";
/**
* <p>onState.</p>
*
* @return a {@link com.pi4j.io.gpio.digital.DigitalState} object.
*/
DigitalState onState();

/**
* <p>getOnState.</p>
*
* @return a {@link com.pi4j.io.gpio.digital.DigitalState} object.
*/
default DigitalState getOnState(){
return this.onState();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,11 @@
*/
public interface DigitalConfigBuilder<BUILDER_TYPE extends DigitalConfigBuilder, CONFIG_TYPE extends DigitalConfig>
extends GpioConfigBuilder<BUILDER_TYPE, CONFIG_TYPE> {
// MARKER INTERFACE
/**
* <p>pull.</p>
*
* @param state a {@link com.pi4j.io.gpio.digital.DigitalState} object.
* @return a {@link BUILDER_TYPE} object.
*/
BUILDER_TYPE onState(DigitalState state);
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,31 @@ public DigitalOutput shutdown(Context context) throws ShutdownException {
/** {@inheritDoc} */
@Override
public DigitalOutput on() throws IOException {
// TODO :: REVISIT STATE VS ON/OFF
return high();

// the default ON state is HIGH
DigitalState onState = DigitalState.HIGH;

// get configured ON state
if(config().onState() != null){
onState = config().onState();
}

// set the current state to the configured ON state
return state(onState);
}

/** {@inheritDoc} */
@Override
public DigitalOutput off() throws IOException {
// TODO :: REVISIT STATE VS ON/OFF
return low();
// the default OFF state is LOW
DigitalState offState = DigitalState.LOW;

// get configured ON state; then set OFF state to inverse of ON state
if(config().onState() != null){
offState = DigitalState.getInverseState(config().onState());
}

// set the current state to the configured OFF state
return state(offState);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import com.pi4j.io.gpio.digital.DigitalInput;
import com.pi4j.io.gpio.digital.DigitalInputConfig;
import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.io.gpio.digital.PullResistance;
import com.pi4j.io.impl.IOAddressConfigBase;
import com.pi4j.util.StringUtil;
Expand All @@ -53,6 +54,7 @@ private DefaultDigitalInputConfig(){
// private configuration properties
protected PullResistance pullResistance = PullResistance.OFF;
protected Long debounce = DigitalInput.DEFAULT_DEBOUNCE;
protected DigitalState onState = DigitalState.HIGH;

/**
* PRIVATE CONSTRUCTOR
Expand All @@ -76,6 +78,11 @@ protected DefaultDigitalInputConfig(Map<String,String> properties){
if(properties.containsKey(DEBOUNCE_RESISTANCE_KEY)){
this.debounce = Long.parseLong(properties.get(DEBOUNCE_RESISTANCE_KEY));
}

// load on-state value property
if(properties.containsKey(ON_STATE_KEY)){
this.onState = DigitalState.parse(properties.get(ON_STATE_KEY));
}
}

/** {@inheritDoc} */
Expand All @@ -87,4 +94,9 @@ public PullResistance pull() {
/** {@inheritDoc} */
@Override
public Long debounce() { return this.debounce; }

@Override
public DigitalState onState() {
return this.onState;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
* #L%
*/

import com.pi4j.io.gpio.digital.DigitalOutputConfig;
import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.io.gpio.digital.*;
import com.pi4j.io.impl.IOAddressConfigBase;
import com.pi4j.util.StringUtil;

Expand All @@ -45,6 +44,7 @@ public class DefaultDigitalOutputConfig
// private configuration properties
protected DigitalState shutdownState = null;
protected DigitalState initialState = null;
protected DigitalState onState = DigitalState.HIGH;

/**
* PRIVATE CONSTRUCTOR
Expand Down Expand Up @@ -75,6 +75,11 @@ protected DefaultDigitalOutputConfig(Map<String,String> properties){
if(properties.containsKey(SHUTDOWN_STATE_KEY)){
this.shutdownState = DigitalState.parse(properties.get(SHUTDOWN_STATE_KEY));
}

// load on-state value property
if(properties.containsKey(ON_STATE_KEY)){
this.onState = DigitalState.parse(properties.get(ON_STATE_KEY));
}
}

/** {@inheritDoc} */
Expand All @@ -95,4 +100,9 @@ public DefaultDigitalOutputConfig shutdownState(DigitalState state){
public DigitalState initialState() {
return this.initialState;
}

@Override
public DigitalState onState() {
return this.onState;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import com.pi4j.context.Context;
import com.pi4j.io.gpio.digital.DigitalConfig;
import com.pi4j.io.gpio.digital.DigitalConfigBuilder;
import com.pi4j.io.gpio.digital.DigitalOutputConfigBuilder;
import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.io.impl.IOAddressConfigBuilderBase;

/**
Expand All @@ -46,4 +48,11 @@ public abstract class DigitalConfigBuilderBase<BUILDER_TYPE extends DigitalConfi
protected DigitalConfigBuilderBase(Context context){
super(context);
}

/** {@inheritDoc} */
@Override
public BUILDER_TYPE onState(DigitalState state) {
this.properties.put(DigitalConfig.ON_STATE_KEY, state.toString());
return (BUILDER_TYPE)this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.pi4j.test.io.gpio.digital;

/*-
* #%L
* **********************************************************************
* ORGANIZATION : Pi4J
* PROJECT : Pi4J :: TESTING :: Unit/Integration Tests
* FILENAME : DigitalInputOffTest.java
*
* This file is part of the Pi4J project. More information about
* this project can be found here: https://pi4j.com/
* **********************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import com.pi4j.Pi4J;
import com.pi4j.context.Context;
import com.pi4j.exception.Pi4JException;
import com.pi4j.io.gpio.digital.DigitalInput;
import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalInput;
import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalInputProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestInstance(Lifecycle.PER_CLASS)
public class DigitalInputOffTest {

private static final Logger logger = LoggerFactory.getLogger(DigitalInputOffTest.class);

private Context pi4j;

@BeforeEach
public void beforeTest() throws Pi4JException {
// Initialize Pi4J with MOCK digital iput provider
pi4j = Pi4J.newContextBuilder().add(MockDigitalInputProvider.newInstance()).build();
}

@AfterEach
public void afterTest() {
try {
pi4j.shutdown();
} catch (Pi4JException e) { /* do nothing */ }
}

@Test
public void testIsOffDefault() {

// create GPIO digital input config
var config = DigitalInput.newConfigBuilder(pi4j)
.id("test-output")
.name("Test Digital Input")
.address(1)
.build();

// create GPIO digital input instance
var input = pi4j.din().create(config);

// set MOCK state to LOW
MockDigitalInput mockInput = (MockDigitalInput)input;
mockInput.mockState(DigitalState.LOW);

// ensure output is OFF and not ON
assertTrue(input.isOff());
assertFalse(input.isOn());
}

@Test
public void testIsOffHigh() {

// create GPIO digital input config
var config = DigitalInput.newConfigBuilder(pi4j)
.id("test-output")
.name("Test Digital Input")
.onState(DigitalState.HIGH)
.address(1)
.build();

// create GPIO digital input instance
var input = pi4j.din().create(config);

// set MOCK state to LOW
MockDigitalInput mockInput = (MockDigitalInput)input;
mockInput.mockState(DigitalState.LOW);

// ensure output is OFF and not ON
assertTrue(input.isOff());
assertFalse(input.isOn());
}

@Test
public void testIsOffLow() {

// create GPIO digital input config
var config = DigitalInput.newConfigBuilder(pi4j)
.id("test-output")
.name("Test Digital Input")
.onState(DigitalState.LOW)
.address(1)
.build();

// create GPIO digital input instance
var input = pi4j.din().create(config);

// set MOCK state to HIGH
MockDigitalInput mockInput = (MockDigitalInput)input;
mockInput.mockState(DigitalState.HIGH);

// ensure output is OFF and not ON
assertTrue(input.isOff());
assertFalse(input.isOn());
}

}
Loading

0 comments on commit 1c06841

Please sign in to comment.