diff --git a/pi4j-core/src/main/java/com/pi4j/internal/IOCreator.java b/pi4j-core/src/main/java/com/pi4j/internal/IOCreator.java index 94c417375..197a115fb 100644 --- a/pi4j-core/src/main/java/com/pi4j/internal/IOCreator.java +++ b/pi4j-core/src/main/java/com/pi4j/internal/IOCreator.java @@ -34,6 +34,8 @@ import com.pi4j.io.i2c.I2C; import com.pi4j.io.i2c.I2CConfig; import com.pi4j.io.i2c.I2CConfigBuilder; +import com.pi4j.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireConfig; import com.pi4j.io.pwm.Pwm; import com.pi4j.io.pwm.PwmConfig; import com.pi4j.io.pwm.PwmConfigBuilder; @@ -146,6 +148,16 @@ default Serial create(SerialConfig config) { return create(config, Serial.class); } + /** + * Creates a new {@link OneWire} instance using the specified configuration. + * + * @param config the {@link com.pi4j.io.onewire.OneWireConfig} object containing the configuration settings. + * @return a new {@link OneWire} object configured as specified. + */ + default OneWire create(OneWireConfig config) { + return create(config, OneWire.class); + } + /** *

create.

* diff --git a/pi4j-core/src/main/java/com/pi4j/internal/ProviderAliases.java b/pi4j-core/src/main/java/com/pi4j/internal/ProviderAliases.java index 95d216fda..58ddab489 100644 --- a/pi4j-core/src/main/java/com/pi4j/internal/ProviderAliases.java +++ b/pi4j-core/src/main/java/com/pi4j/internal/ProviderAliases.java @@ -31,6 +31,7 @@ import com.pi4j.io.gpio.digital.DigitalInputProvider; import com.pi4j.io.gpio.digital.DigitalOutputProvider; import com.pi4j.io.i2c.I2CProvider; +import com.pi4j.io.onewire.OneWireProvider; import com.pi4j.io.pwm.PwmProvider; import com.pi4j.io.serial.SerialProvider; import com.pi4j.io.spi.SpiProvider; @@ -282,4 +283,15 @@ default T getI2CProvider() throws ProviderException{ default T getSerialProvider() throws ProviderException{ return this.serial(); } + + /** + *

1-Wire

+ * + * @param a T object. + * @return a T object. + * @throws ProviderException if any. + */ + default T oneWire() throws ProviderException { + return this.provider(IOType.ONE_WIRE); + } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/IOType.java b/pi4j-core/src/main/java/com/pi4j/io/IOType.java index 0acaf09a2..c7102a53f 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/IOType.java +++ b/pi4j-core/src/main/java/com/pi4j/io/IOType.java @@ -32,6 +32,10 @@ import com.pi4j.io.i2c.I2CConfig; import com.pi4j.io.i2c.I2CConfigBuilder; import com.pi4j.io.i2c.I2CProvider; +import com.pi4j.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireConfigBuilder; +import com.pi4j.io.onewire.OneWireProvider; import com.pi4j.io.pwm.Pwm; import com.pi4j.io.pwm.PwmConfig; import com.pi4j.io.pwm.PwmConfigBuilder; @@ -62,7 +66,8 @@ public enum IOType { I2C(I2CProvider.class, com.pi4j.io.i2c.I2C.class, I2CConfig.class, I2CConfigBuilder.class), SPI(SpiProvider.class, Spi.class, I2CConfig.class, I2CConfigBuilder.class), @Deprecated(forRemoval = true) - SERIAL(SerialProvider.class, Serial.class, SerialConfig.class, SerialConfigBuilder.class); + SERIAL(SerialProvider.class, Serial.class, SerialConfig.class, SerialConfigBuilder.class), + ONE_WIRE(OneWireProvider.class, OneWire.class, OneWireConfig.class, OneWireConfigBuilder.class); private Class providerClass; private Class ioClass; diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWire.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWire.java new file mode 100644 index 000000000..c84609389 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWire.java @@ -0,0 +1,83 @@ +package com.pi4j.io.onewire; + +/* + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWire.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.context.Context; +import com.pi4j.io.IO; +import com.pi4j.io.IODataReader; +import com.pi4j.io.IODataWriter; + +/** + * Interface representing a 1-Wire I/O communication in the Pi4J library. + *

+ * This interface facilitates 1-Wire bus/device communications by providing + * methods for configuration, state management, and data interaction. + * It extends {@link IO}, {@link IODataWriter}, {@link IODataReader}, + * and {@link OneWireFileDataReaderWriter}, and supports auto-closing of resources. + *

+ */ +public interface OneWire + extends IO, OneWireFileDataReaderWriter { + + /** + * Creates a new configuration builder for a 1-Wire interface. + *

+ * This static method provides a convenient way to construct + * a {@link OneWireConfigBuilder} object. + *

+ * + * @param context the {@link Context} associated with this configuration. + * @return a {@link OneWireConfigBuilder} instance to build the configuration. + */ + static OneWireConfigBuilder newConfigBuilder(Context context) { + return OneWireConfigBuilder.newInstance(context); + } + + /** + * Retrieves the 1-Wire device address for this interface instance. + *

+ * The device address is defined in the configuration and is used + * to identify the target 1-Wire device on the bus. + *

+ * + * @return a {@code String} representing the 1-Wire device address. + */ + default String device() { + return config().device(); + } + + /** + * Retrieves the 1-Wire device address for this interface instance. + *

+ * This method serves as an alias for {@link #device()}. + *

+ * + * @return a {@code String} representing the 1-Wire device address. + */ + default String getDevice() { + return device(); + } +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireBase.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireBase.java new file mode 100644 index 000000000..a736b1238 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireBase.java @@ -0,0 +1,57 @@ +package com.pi4j.io.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireBase.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.io.IOBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for managing 1-Wire communication. + * + *

This abstract class provides core functionality and lifecycle management + * for 1-Wire communication interfaces within the Pi4J library. It is intended + * to be extended by specific 1-Wire implementations.

+ * + *

The class integrates with the Pi4J I/O framework and ensures + * consistent behavior across all supported 1-Wire providers.

+ */ +public abstract class OneWireBase extends IOBase implements OneWire { + + /** Logger instance for debugging and tracing operations. */ + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Constructs a new {@code OneWireBase} instance. + * + * @param provider the {@link OneWireProvider} used to manage 1-Wire communication. + * @param config the {@link OneWireConfig} specifying configuration settings for this instance. + */ + public OneWireBase(OneWireProvider provider, OneWireConfig config) { + super(provider, config); + logger.trace("Created OneWireBase instance with config: {}", config); + } +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfig.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfig.java new file mode 100644 index 000000000..57362d361 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfig.java @@ -0,0 +1,79 @@ +package com.pi4j.io.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireConfig.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.context.Context; +import com.pi4j.io.IOConfig; + +/** + * Interface defining the configuration settings for a 1-Wire interface in the Pi4J library. + *

+ * This interface extends {@link IOConfig} and provides additional configuration options + * specific to 1-Wire devices. + *

+ */ +public interface OneWireConfig extends IOConfig { + + /** + * Key used for accessing the device configuration property. + */ + String DEVICE_KEY = "device"; + + /** + * Retrieves the device ID associated with this configuration. + *

+ * The device ID is a unique identifier used to specify the target 1-Wire device. + *

+ * + * @return a {@link String} representing the device ID. + */ + String device(); + + /** + * Retrieves the device ID associated with this configuration. + *

+ * This method serves as an alias for {@link #device()} for convenience. + *

+ * + * @return a {@link String} representing the device ID. + */ + default String getDevice() { + return device(); + } + + /** + * Creates a new builder instance for configuring a 1-Wire interface. + *

+ * The builder provides a fluent API for constructing a {@link OneWireConfig} object. + *

+ * + * @param context the {@link Context} associated with this configuration. + * @return a {@link OneWireConfigBuilder} instance for building the configuration. + */ + static OneWireConfigBuilder newBuilder(Context context) { + return OneWireConfigBuilder.newInstance(context); + } +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfigBuilder.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfigBuilder.java new file mode 100644 index 000000000..f84bf39f4 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireConfigBuilder.java @@ -0,0 +1,69 @@ +package com.pi4j.io.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireConfigBuilder.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.config.ConfigBuilder; +import com.pi4j.context.Context; +import com.pi4j.io.IOConfigBuilder; +import com.pi4j.io.onewire.impl.DefaultOneWireConfigBuilder; + +/** + * Builder interface for configuring 1-Wire interfaces in the Pi4J library. + *

+ * This interface extends {@link IOConfigBuilder} and {@link ConfigBuilder}, + * providing a fluent API to construct and customize 1-Wire configuration settings. + *

+ */ +public interface OneWireConfigBuilder extends + IOConfigBuilder, + ConfigBuilder { + + /** + * Creates a new instance of {@link OneWireConfigBuilder}. + *

+ * This factory method provides a convenient way to initialize + * a 1-Wire configuration builder within the given {@link Context}. + *

+ * + * @param context the {@link Context} for the application environment. + * @return a {@link OneWireConfigBuilder} instance for building configurations. + */ + static OneWireConfigBuilder newInstance(Context context) { + return DefaultOneWireConfigBuilder.newInstance(context); + } + + /** + * Specifies the device ID for the 1-Wire interface. + *

+ * The device ID uniquely identifies the target 1-Wire device + * and is a required configuration parameter. + *

+ * + * @param device a {@link String} representing the device ID. + * @return the {@link OneWireConfigBuilder} instance, for chaining. + */ + OneWireConfigBuilder device(String device); +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireFileDataReaderWriter.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireFileDataReaderWriter.java new file mode 100644 index 000000000..bf523a800 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireFileDataReaderWriter.java @@ -0,0 +1,86 @@ +package com.pi4j.io.onewire; + +/* + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireFileDataReaderWriter.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.io.exception.IOException; + +import java.util.List; + +public interface OneWireFileDataReaderWriter { + /** + * Read the entire content of a file on the device. + * + * @param fileName The name of the file to read. + * @return The file content as List. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + List readFile(String fileName) throws IOException; + + /** + * Read a single line from a file on the device. + * + * @param fileName The name of the file to read. + * @return The first line of the file content as a string. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + String readFirstLine(String fileName) throws IOException; + + /** + * Read the entire content of a file on the device. + * + * @param fileName The name of the file to read. + * @return The file content as array of bytes. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + byte[] readFileAsBytes(String fileName) throws IOException; + + /** + * Write a single byte to a file on the device. + * + * @param fileName The name of the file to write to. + * @param value The byte value to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + void writeFile(String fileName, byte value) throws IOException; + + /** + * Write multiple bytes to a file on the device. + * + * @param fileName The name of the file to write to. + * @param values The byte array to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + void writeFile(String fileName, byte[] values) throws IOException; + + /** + * Write a string to a file on the device. + * + * @param fileName The name of the file to write to. + * @param content The string content to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + void writeFile(String fileName, String content) throws IOException; +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProvider.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProvider.java new file mode 100644 index 000000000..06dd89073 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProvider.java @@ -0,0 +1,121 @@ +package com.pi4j.io.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireProvider.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.provider.Provider; + +/** + * Interface for defining a 1-Wire Provider in the Pi4J library. + *

+ * The {@link OneWireProvider} interface is responsible for creating and managing + * instances of 1-Wire devices. It serves as a factory and configurator, enabling + * the creation of 1-Wire devices based on various parameters like device ID, custom ID, + * name, and description. + *

+ */ +public interface OneWireProvider extends Provider { + + /** + * Creates a new 1-Wire device using a pre-configured {@link OneWireConfigBuilder}. + *

+ * This method is useful for building and creating 1-Wire devices when a + * configuration builder instance is already available. + *

+ * + * @param builder the configuration builder used to define the 1-Wire device. + * @param the type of the 1-Wire device to create. + * @return an instance of the created 1-Wire device. + */ + default T create(OneWireConfigBuilder builder) { + return (T) create(builder.build()); + } + + /** + * Creates a new 1-Wire device with a specified device ID and custom ID. + *

+ * This method provides a simpler way to create 1-Wire devices without + * requiring additional metadata like name or description. + *

+ * + * @param device the 1-Wire device address as a {@link String}. + * @param id a unique identifier for the 1-Wire device as a {@link String}. + * @param the type of the 1-Wire device to create. + * @return an instance of the created 1-Wire device. + */ + default T create(String device, String id) { + var config = OneWire.newConfigBuilder(context()) + .device(device) + .id(id) + .build(); + return (T) create(config); + } + + /** + * Creates a new 1-Wire device with a specified device ID, custom ID, and name. + *

+ * This method allows for the creation of 1-Wire devices with an associated + * human-readable name for easier identification. + *

+ * + * @param device the 1-Wire device address as a {@link String}. + * @param id a unique identifier for the 1-Wire device as a {@link String}. + * @param name a human-readable name for the device as a {@link String}. + * @param the type of the 1-Wire device to create. + * @return an instance of the created 1-Wire device. + */ + default T create(String device, String id, String name) { + var config = OneWire.newConfigBuilder(context()) + .device(device) + .id(id) + .name(name) + .build(); + return (T) create(config); + } + + /** + * Creates a new 1-Wire device with a specified device ID, custom ID, name, and description. + *

+ * This method provides the most detailed way to create a 1-Wire device, + * including an optional description for additional metadata. + *

+ * + * @param device the 1-Wire device address as a {@link String}. + * @param id a unique identifier for the 1-Wire device as a {@link String}. + * @param name a human-readable name for the device as a {@link String}. + * @param description a descriptive text for the device as a {@link String}. + * @param the type of the 1-Wire device to create. + * @return an instance of the created 1-Wire device. + */ + default T create(String device, String id, String name, String description) { + var config = OneWire.newConfigBuilder(context()) + .device(device) + .id(id) + .name(name) + .description(description) + .build(); + return (T) create(config); + } +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProviderBase.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProviderBase.java new file mode 100644 index 000000000..a58a2966a --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/OneWireProviderBase.java @@ -0,0 +1,68 @@ +package com.pi4j.io.onewire; + +import com.pi4j.provider.ProviderBase; + +/* + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : OneWireProviderBase.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% + */ + +/** + * Abstract base class for implementing OneWire providers. + * This class serves as a foundation for creating concrete implementations + * of the OneWireProvider interface, managing shared functionality and + * configuration for OneWire communication. + */ +public abstract class OneWireProviderBase + extends ProviderBase + implements OneWireProvider { + + /** + * Default constructor. + * Initializes the base class without any specific identifier or name. + */ + public OneWireProviderBase(){ + super(); + } + + /** + * Constructor with an identifier. + * Initializes the base class with a unique identifier for the provider. + * + * @param id a {@link String} representing the unique identifier of the provider. + */ + public OneWireProviderBase(String id){ + super(id); + } + + /** + * Constructor with an identifier and name. + * Initializes the base class with a unique identifier and a human-readable name. + * + * @param id a {@link String} representing the unique identifier of the provider. + * @param name a {@link String} representing the human-readable name of the provider. + */ + public OneWireProviderBase(String id, String name){ + super(id, name); + } +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfig.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfig.java new file mode 100644 index 000000000..bf6ef0526 --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfig.java @@ -0,0 +1,101 @@ +package com.pi4j.io.onewire.impl; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : DefaultOneWireConfig.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.config.exception.ConfigMissingRequiredKeyException; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.impl.IOConfigBase; +import com.pi4j.util.StringUtil; + +import java.util.Map; + +/** + * Default implementation of the {@link OneWireConfig} interface. + *

+ * This class represents the configuration settings for a 1-Wire device + * and ensures that the required properties are properly initialized. + *

+ */ +public class DefaultOneWireConfig + extends IOConfigBase + implements OneWireConfig { + + // Private field to store the device address + protected String device = null; + + /** + * Private constructor to prevent instantiation without properties. + *

+ * This ensures that the configuration is always initialized + * with the required settings from a property map. + *

+ */ + private DefaultOneWireConfig() { + super(); + } + + /** + * Constructs a new {@link DefaultOneWireConfig} instance with the provided properties. + *

+ * This constructor validates the presence of required properties, such as + * the device address, and sets default values for optional properties if they are missing. + *

+ * + * @param properties a {@link Map} containing configuration keys and values. + * @throws ConfigMissingRequiredKeyException if the required "device" key is missing. + */ + protected DefaultOneWireConfig(Map properties) { + super(properties); + + // Load the (required) DEVICE property for 1-Wire + if (properties.containsKey(DEVICE_KEY)) { + this.device = String.valueOf(properties.get(DEVICE_KEY)); + } else { + throw new ConfigMissingRequiredKeyException(DEVICE_KEY); + } + + // Set default values for optional properties if missing + this.id = StringUtil.setIfNullOrEmpty(this.id, "1-Wire-" + this.device(), true); + this.name = StringUtil.setIfNullOrEmpty(this.name, "1-Wire-" + this.device(), true); + this.description = StringUtil.setIfNullOrEmpty(this.description, "1-Wire-" + this.device(), true); + } + + /** + * Retrieves the device address for this 1-Wire configuration. + *

+ * The device address is a unique identifier for the 1-Wire device + * and is a required configuration property. + *

+ * + * @return a {@link String} representing the 1-Wire device address. + */ + @Override + public String device() { + return this.device; + } + + // Additional methods for 1-Wire configuration can be added here as needed. +} diff --git a/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfigBuilder.java b/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfigBuilder.java new file mode 100644 index 000000000..269b7302e --- /dev/null +++ b/pi4j-core/src/main/java/com/pi4j/io/onewire/impl/DefaultOneWireConfigBuilder.java @@ -0,0 +1,78 @@ +package com.pi4j.io.onewire.impl; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: LIBRARY :: Java Library (CORE) + * FILENAME : DefaultOneWireConfigBuilder.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.context.Context; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireConfigBuilder; +import com.pi4j.io.impl.IOConfigBuilderBase; + +/** + *

DefaultOneWireConfigBuilder class.

+ * This class is used to build and configure 1-Wire device configurations. + */ +public class DefaultOneWireConfigBuilder + extends IOConfigBuilderBase + implements OneWireConfigBuilder { + + /** + * PRIVATE CONSTRUCTOR + * This constructor ensures that the builder can only be created through the static method newInstance(). + */ + protected DefaultOneWireConfigBuilder(Context context){ + super(context); + } + + /** + * Static method to create a new instance of DefaultOneWireConfigBuilder. + * + * @param context The Pi4J context used for this configuration. + * @return A new instance of OneWireConfigBuilder. + */ + public static OneWireConfigBuilder newInstance(Context context) { + return new DefaultOneWireConfigBuilder(context); + } + + /** {@inheritDoc} */ + @Override + public OneWireConfig build() { + // Return a new OneWireConfig instance with the resolved properties + return new DefaultOneWireConfig(getResolvedProperties()); + } + + /** {@inheritDoc} */ + @Override + public OneWireConfigBuilder device(String device) { + // Set the device ID for 1-Wire devices in the configuration properties + this.properties.put(OneWireConfig.DEVICE_KEY, device); + return this; + } + + /** + * Additional configuration options specific to 1-Wire devices can be added here. + * For example, you might add methods to set 1-Wire device-specific parameters. + */ +} diff --git a/pi4j-core/src/main/java/com/pi4j/provider/Providers.java b/pi4j-core/src/main/java/com/pi4j/provider/Providers.java index c3d531f1c..cae5e0051 100644 --- a/pi4j-core/src/main/java/com/pi4j/provider/Providers.java +++ b/pi4j-core/src/main/java/com/pi4j/provider/Providers.java @@ -35,6 +35,7 @@ import com.pi4j.io.gpio.digital.DigitalInputProvider; import com.pi4j.io.gpio.digital.DigitalOutputProvider; import com.pi4j.io.i2c.I2CProvider; +import com.pi4j.io.onewire.OneWireProvider; import com.pi4j.io.pwm.PwmProvider; import com.pi4j.io.serial.SerialProvider; import com.pi4j.io.spi.SpiProvider; @@ -105,6 +106,12 @@ public interface Providers extends Describable { * @return a {@link com.pi4j.provider.ProviderGroup} object. */ ProviderGroup serial(); + /** + *

1-Wire.

+ * + * @return a {@link com.pi4j.provider.ProviderGroup} object. + */ + ProviderGroup oneWire(); /** * Get all providers diff --git a/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultProviders.java b/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultProviders.java index ab85777ff..1c5c01ef8 100644 --- a/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultProviders.java +++ b/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultProviders.java @@ -31,6 +31,7 @@ import com.pi4j.io.gpio.digital.DigitalInputProvider; import com.pi4j.io.gpio.digital.DigitalOutputProvider; import com.pi4j.io.i2c.I2CProvider; +import com.pi4j.io.onewire.OneWireProvider; import com.pi4j.io.pwm.PwmProvider; import com.pi4j.io.serial.SerialProvider; import com.pi4j.io.spi.SpiProvider; @@ -117,6 +118,12 @@ public ProviderGroup serial() { return providers.serial(); } + /** {@inheritDoc} */ + @Override + public ProviderGroup oneWire() { + return providers.oneWire(); + } + /** {@inheritDoc} */ @Override public Map all() { diff --git a/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultRuntimeProviders.java b/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultRuntimeProviders.java index fc576d8cb..fb30e91b2 100644 --- a/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultRuntimeProviders.java +++ b/pi4j-core/src/main/java/com/pi4j/provider/impl/DefaultRuntimeProviders.java @@ -34,6 +34,7 @@ import com.pi4j.io.gpio.digital.DigitalInputProvider; import com.pi4j.io.gpio.digital.DigitalOutputProvider; import com.pi4j.io.i2c.I2CProvider; +import com.pi4j.io.onewire.OneWireProvider; import com.pi4j.io.pwm.PwmProvider; import com.pi4j.io.serial.SerialProvider; import com.pi4j.io.spi.SpiProvider; @@ -76,6 +77,7 @@ public class DefaultRuntimeProviders implements RuntimeProviders { private ProviderGroup _spi = new ProviderGroup<>(this, IOType.SPI); private ProviderGroup _i2c = new ProviderGroup<>(this, IOType.I2C); private ProviderGroup _serial = new ProviderGroup<>(this, IOType.SERIAL); + private ProviderGroup _oneWire = new ProviderGroup<>(this, IOType.ONE_WIRE); /** {@inheritDoc} */ @Override @@ -109,6 +111,10 @@ public class DefaultRuntimeProviders implements RuntimeProviders { @Override public ProviderGroup serial() { return _serial; } + /** {@inheritDoc} */ + @Override + public ProviderGroup oneWire() { return _oneWire; } + // static singleton instance /** *

newInstance.

diff --git a/pi4j-core/src/main/java/module-info.java b/pi4j-core/src/main/java/module-info.java index d1f75028f..5fe0e4a27 100644 --- a/pi4j-core/src/main/java/module-info.java +++ b/pi4j-core/src/main/java/module-info.java @@ -65,6 +65,7 @@ opens com.pi4j.boardinfo.datareader; exports com.pi4j.boardinfo.util.command; opens com.pi4j.boardinfo.util.command; + exports com.pi4j.io.onewire; // extensibility service interfaces uses com.pi4j.extension.Plugin; diff --git a/pi4j-test/src/main/java/com/pi4j/test/OneWireTest.java b/pi4j-test/src/main/java/com/pi4j/test/OneWireTest.java new file mode 100644 index 000000000..da478bf1c --- /dev/null +++ b/pi4j-test/src/main/java/com/pi4j/test/OneWireTest.java @@ -0,0 +1,98 @@ +package com.pi4j.test; + +import com.pi4j.Pi4J; +import com.pi4j.context.Context; +import com.pi4j.io.onewire.OneWire; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OneWireTest { + + private static final Logger logger = LoggerFactory.getLogger(OneWireTest.class); + + // Device IDs for DS18B20 and DS2413 + private static final String DS18B20_DEVICE_ID = "28-06219443087e"; + private static final String DS2413_DEVICE_ID = "3a-0000005eaee8"; + + // Desired resolution for DS18B20 + private static final String DS18B20_RESOLUTION = "10"; // Set to 10-bit precision + + // Value to set DS2413 state (0xf2 means State 1 ON, State 2 OFF) + private static final byte DS2413_STATE_VALUE = (byte) 0xf2; + + public static void main(String[] args) { + // Initialize Pi4J context + Context pi4j = Pi4J.newAutoContext(); + + try { + // Handle DS18B20 sensor + handleDS18B20(pi4j); + + // Handle DS2413 sensor + handleDS2413(pi4j); + } catch (Exception e) { + logger.error("An error occurred: {}", e.getMessage()); + } finally { + // Shutdown Pi4J context + pi4j.shutdown(); + } + } + + private static void handleDS18B20(Context pi4j) { + logger.info("Interacting with DS18B20 sensor..."); + + var ds18b20Config = OneWire.newConfigBuilder(pi4j) + .id("ds18b20") + .device(DS18B20_DEVICE_ID) + .build(); + + // Read and set temperature resolution for DS18B20 + try { + var ds18b20 = pi4j.create(ds18b20Config); + // Set resolution + ds18b20.writeFile("resolution", DS18B20_RESOLUTION); + logger.info("Set DS18B20 resolution to {} bits", DS18B20_RESOLUTION); + + // Read temperature + String temperature = ds18b20.readFirstLine("temperature"); + + // Parse and log temperature + try { + long tempValue = Long.parseLong(temperature); + logger.info("Temperature: {}°C", tempValue / 100); + } catch (NumberFormatException e) { + logger.error("Failed to parse temperature: {}", temperature); + } + } catch (Exception e) { + logger.error("Failed to interact with DS18B20 sensor: {}", e.getMessage()); + } + } + + private static void handleDS2413(Context pi4j) { + logger.info("Interacting with DS2413 sensor..."); + + var ds2413Config = OneWire.newConfigBuilder(pi4j) + .id("ds2413") + .device(DS2413_DEVICE_ID) + .build(); + + // Read and set state for DS2413 + try { + var ds2413 = pi4j.create(ds2413Config); + + // Read current state before setting new value + String stateBefore = ds2413.readFirstLine("state"); + logger.info("Current state before update: {}", stateBefore); + + // Set new state to 0xf2 (State 1 ON, State 2 OFF) + ds2413.writeFile("state", DS2413_STATE_VALUE); + logger.info("Set DS2413 state to 0xf2 (State 1 ON, State 2 OFF)"); + + // Read current state after setting new value + String stateAfter = ds2413.readFirstLine("state"); + logger.info("Current state after update: {}", stateAfter); + } catch (Exception e) { + logger.error("Failed to interact with DS2413 sensor: {}", e.getMessage()); + } + } +} diff --git a/pi4j-test/src/test/java/com/pi4j/test/io/onewire/OneWireRawDataTest.java b/pi4j-test/src/test/java/com/pi4j/test/io/onewire/OneWireRawDataTest.java new file mode 100644 index 000000000..d1e02ad58 --- /dev/null +++ b/pi4j-test/src/test/java/com/pi4j/test/io/onewire/OneWireRawDataTest.java @@ -0,0 +1,103 @@ +package com.pi4j.test.io.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: TESTING :: Unit/Integration Tests + * FILENAME : OneWireRawDataTest.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.onewire.OneWire; +import com.pi4j.plugin.mock.provider.onewire.MockOneWire; +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 java.util.List; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@TestInstance(Lifecycle.PER_CLASS) +public class OneWireRawDataTest { + + private Context pi4j; + + @BeforeEach + public void beforeTest() throws Pi4JException { + pi4j = Pi4J.newContextBuilder() + .autoDetectMockPlugins() + .autoDetectPlatforms() + .build(); + } + + @AfterEach + public void afterTest() { + try { + pi4j.shutdown(); + } catch (Pi4JException ignored) { /* do nothing */ } + } + + @Test + public void shouldWriteAndReadStringData() { + var content = "24000" + System.lineSeparator() + "48000"; + var oneWire = createMockOneWire("28-000008d6bac6"); + + oneWire.writeFile("content", content); + + var fileContent = oneWire.readFile("content"); + + assertNotNull(fileContent); + assertEquals(2, fileContent.size()); + assertEquals("24000", fileContent.get(0)); + assertEquals("48000", fileContent.get(1)); + assertEquals(content, String.join(System.lineSeparator(), fileContent)); + } + + @Test + public void shouldWriteAndReadByteData() { + var content = new byte[]{0x01, 0x20, 0x30}; + var oneWire = createMockOneWire("28-000008d6bac6"); + + oneWire.writeFile("content", content); + + var fileContent = oneWire.readFileAsBytes("content"); + + assertNotNull(fileContent); + assertEquals(3, fileContent.length); + assertArrayEquals(content, fileContent); + } + + private MockOneWire createMockOneWire(String deviceId) { + var config = OneWire.newConfigBuilder(pi4j) + .id("my-one-wire") + .name("My 1-Wire") + .device(deviceId) + .build(); + return (MockOneWire) pi4j.oneWire().create(config); + } +} diff --git a/pi4j-test/src/test/java/com/pi4j/test/platform/ManualPlatformsTest.java b/pi4j-test/src/test/java/com/pi4j/test/platform/ManualPlatformsTest.java index e8a6e7c62..d0a2f8b51 100644 --- a/pi4j-test/src/test/java/com/pi4j/test/platform/ManualPlatformsTest.java +++ b/pi4j-test/src/test/java/com/pi4j/test/platform/ManualPlatformsTest.java @@ -31,15 +31,6 @@ import com.pi4j.Pi4J; import com.pi4j.context.Context; import com.pi4j.exception.Pi4JException; -import com.pi4j.plugin.mock.platform.MockPlatform; -import com.pi4j.plugin.mock.provider.gpio.analog.MockAnalogInputProvider; -import com.pi4j.plugin.mock.provider.gpio.analog.MockAnalogOutputProvider; -import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalInputProvider; -import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalOutputProvider; -import com.pi4j.plugin.mock.provider.i2c.MockI2CProvider; -import com.pi4j.plugin.mock.provider.pwm.MockPwmProvider; -import com.pi4j.plugin.mock.provider.serial.MockSerialProvider; -import com.pi4j.plugin.mock.provider.spi.MockSpiProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/LinuxFsPlugin.java b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/LinuxFsPlugin.java index a21d2a379..d214be667 100644 --- a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/LinuxFsPlugin.java +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/LinuxFsPlugin.java @@ -32,11 +32,13 @@ import com.pi4j.extension.Plugin; import com.pi4j.extension.PluginService; import com.pi4j.plugin.linuxfs.internal.LinuxGpio; +import com.pi4j.plugin.linuxfs.internal.LinuxOneWire; +import com.pi4j.plugin.linuxfs.internal.LinuxPwm; import com.pi4j.plugin.linuxfs.provider.i2c.LinuxFsI2CProvider; import com.pi4j.plugin.linuxfs.provider.gpio.digital.LinuxFsDigitalInputProvider; import com.pi4j.plugin.linuxfs.provider.gpio.digital.LinuxFsDigitalOutputProvider; +import com.pi4j.plugin.linuxfs.provider.onewire.LinuxFsOneWireProvider; import com.pi4j.plugin.linuxfs.provider.pwm.LinuxFsPwmProvider; -import com.pi4j.plugin.linuxfs.internal.LinuxPwm; import com.pi4j.plugin.linuxfs.provider.spi.LinuxFsSpiProvider; import com.pi4j.provider.Provider; import org.slf4j.Logger; @@ -101,6 +103,13 @@ public class LinuxFsPlugin implements Plugin { public static final String I2C_PROVIDER_NAME = NAME + " I2C Provider"; public static final String I2C_PROVIDER_ID = ID + "-i2c"; + // 1-Wire Provider name and unique ID + public static final String ONE_WIRE_PROVIDER_NAME = NAME + " 1-Wire Provider"; + public static final String ONE_WIRE_PROVIDER_ID = ID + "-one-wire"; + +// // SPI Provider name and unique ID +// public static final String SPI_PROVIDER_NAME = NAME + " SPI Provider"; +// public static final String SPI_PROVIDER_ID = ID + "-spi"; // // Serial Provider name and unique ID // public static final String SERIAL_PROVIDER_NAME = NAME + " Serial Provider"; @@ -112,6 +121,7 @@ public class LinuxFsPlugin implements Plugin { public static String DEFAULT_GPIO_FILESYSTEM_PATH = LinuxGpio.DEFAULT_SYSTEM_PATH; public static String DEFAULT_PWM_FILESYSTEM_PATH = LinuxPwm.DEFAULT_SYSTEM_PATH; + public static String DEFAULT_ONE_WIRE_FILESYSTEM_PATH = LinuxOneWire.DEFAULT_SYSTEM_PATH; private Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -124,6 +134,7 @@ public void initialize(PluginService service) { // get Linux file system path for GPIO & PWM String gpioFileSystemPath = DEFAULT_GPIO_FILESYSTEM_PATH; String pwmFileSystemPath = DEFAULT_PWM_FILESYSTEM_PATH; + String oneWireFileSystemPath = DEFAULT_ONE_WIRE_FILESYSTEM_PATH; int pwmChip; if(BoardInfoHelper.usesRP1()) { @@ -158,7 +169,8 @@ public void initialize(PluginService service) { LinuxFsDigitalOutputProvider.newInstance(gpioFileSystemPath), LinuxFsPwmProvider.newInstance(pwmFileSystemPath, pwmChip), LinuxFsI2CProvider.newInstance(), - LinuxFsSpiProvider.newInstance() + LinuxFsSpiProvider.newInstance(), + LinuxFsOneWireProvider.newInstance(oneWireFileSystemPath) }; // register the LinuxFS I/O Providers with the plugin service diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/internal/LinuxOneWire.java b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/internal/LinuxOneWire.java new file mode 100644 index 000000000..1e80f7d4f --- /dev/null +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/internal/LinuxOneWire.java @@ -0,0 +1,76 @@ +package com.pi4j.plugin.linuxfs.internal; + +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + *

LinuxOneWire class.

+ * + * @see "https://www.kernel.org/doc/html/latest/driver-api/w1.html" + */ +public class LinuxOneWire { + + /** Constant DEFAULT_SYSTEM_PATH="/sys/bus/w1/devices" */ + public static final String DEFAULT_SYSTEM_PATH = "/sys/bus/w1/devices"; + + protected final String systemPath; + protected final String deviceId; + protected final String devicePath; + + /** + *

Constructor for LinuxOneWire.

+ * + * @param systemPath a {@link String} object. + * @param deviceId a {@link String} object. + */ + public LinuxOneWire(String systemPath, String deviceId) { + this.systemPath = systemPath; + this.deviceId = deviceId; + this.devicePath = Paths.get(systemPath, deviceId).toString(); + } + + /** + *

Constructor for LinuxOneWire.

+ * + * @param deviceId a {@link String} object. + */ + public LinuxOneWire(String deviceId) { + this(DEFAULT_SYSTEM_PATH, deviceId); + } + + /** + * Checks if the 1-Wire device is connected and accessible. + * + * @return {@code true} if the device is connected, {@code false} otherwise. + */ + public boolean isConnected() { + return Files.exists(Paths.get(devicePath)); + } + + /** + * Gets the Linux File System path for the 1-Wire system. + * + * @return The 1-Wire system path as a {@link String}. + */ + public String getSystemPath() { + return systemPath; + } + + /** + * Gets the Linux File System path for this 1-Wire device instance. + * + * @return The 1-Wire device path as a {@link String}. + */ + public String getDevicePath() { + return devicePath; + } + + /** + * Gets the device ID of this 1-Wire device. + * + * @return The device ID as a {@link String}. + */ + public String getDeviceId() { + return deviceId; + } +} diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWire.java b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWire.java new file mode 100644 index 000000000..7864ca7b9 --- /dev/null +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWire.java @@ -0,0 +1,218 @@ +package com.pi4j.plugin.linuxfs.provider.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: LinuxFS I/O Providers + * FILENAME : LinuxFsOneWire.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.io.exception.IOException; +import com.pi4j.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireBase; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireProvider; +import com.pi4j.plugin.linuxfs.internal.LinuxOneWire; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + + +/** + * The {@code LinuxFsOneWire} class provides an implementation for interacting with + * the OneWire filesystem on Linux devices. This class includes methods for reading + * and writing files in the OneWire device directory, validating file accessibility, + * and managing configuration through the {@code OneWireBase} superclass. + */ +public class LinuxFsOneWire extends OneWireBase implements OneWire { + + /** + * Reference to the LinuxOneWire instance managing device-specific functionality. + */ + protected final LinuxOneWire oneWire; + + /** + * Logger instance for logging events and debugging information. + */ + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * Constructs a new {@code LinuxFsOneWire} instance with the specified OneWire device, + * provider, and configuration. + * + * @param oneWire the {@link LinuxOneWire} instance representing the OneWire device. + * @param provider the {@link OneWireProvider} associated with this instance. + * @param config the {@link OneWireConfig} containing configuration details. + */ + public LinuxFsOneWire(LinuxOneWire oneWire, OneWireProvider provider, OneWireConfig config) { + super(provider, config); + this.oneWire = oneWire; + } + + /** + * Reads the entire content of a file as a list of lines. + * + * @param fileName the name of the file to read. + * @return a list of strings, where each string represents a line in the file. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + public List readFile(String fileName) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForRead(filePath); + + try { + return Files.readAllLines(filePath); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Reads the first line from a file. + * + * @param fileName the name of the file to read. + * @return the first line of the file as a string, or {@code null} if the file is empty. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + public String readFirstLine(String fileName) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForRead(filePath); + + try (BufferedReader reader = Files.newBufferedReader(filePath)) { + return reader.readLine(); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Reads the entire content of a file as a byte array. + * + * @param fileName the name of the file to read. + * @return a byte array containing the file's content. + * @throws IOException if the file does not exist, is not readable, or another I/O error occurs. + */ + @Override + public byte[] readFileAsBytes(String fileName) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForRead(filePath); + + try { + return Files.readAllBytes(filePath); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Writes a single byte to a file. + * + * @param fileName the name of the file to write to. + * @param value the byte value to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + public void writeFile(String fileName, byte value) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForWrite(filePath); + + try { + Files.write(filePath, new byte[]{value}); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Writes a byte array to a file. + * + * @param fileName the name of the file to write to. + * @param values the byte array to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + public void writeFile(String fileName, byte[] values) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForWrite(filePath); + + try { + Files.write(filePath, values); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Writes a string to a file. + * + * @param fileName the name of the file to write to. + * @param content the string content to write. + * @throws IOException if the file does not exist, is not writable, or another I/O error occurs. + */ + public void writeFile(String fileName, String content) throws IOException { + Path filePath = Paths.get(oneWire.getDevicePath(), fileName); + validateFileForWrite(filePath); + + try { + Files.writeString(filePath, content); + } catch (java.io.IOException e) { + throw new IOException(e); + } + } + + /** + * Validates that a file exists and is readable. + * + * @param filePath the path of the file to validate. + * @throws IOException if the file does not exist or is not readable. + */ + private void validateFileForRead(Path filePath) throws IOException { + if (!Files.exists(filePath)) { + throw new IOException("File " + filePath + " does not exist."); + } + if (!Files.isReadable(filePath)) { + throw new IOException("File " + filePath + " is not readable."); + } + } + + /** + * Validates that a file exists and is writable. + * + * @param filePath the path of the file to validate. + * @throws IOException if the file does not exist or is not writable due to permissions or other restrictions. + * On Linux, consider using 'sudo' if this issue persists. + */ + private void validateFileForWrite(Path filePath) throws IOException { + if (!Files.exists(filePath)) { + throw new IOException("File " + filePath + " does not exist."); + } + if (!Files.isWritable(filePath)) { + throw new IOException("File " + filePath + " is not writable. This may be due to permissions or access restrictions. " + + "On Linux, consider using 'sudo' to resolve this issue."); + } + } +} + diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProvider.java b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProvider.java new file mode 100644 index 000000000..c6b4deb89 --- /dev/null +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProvider.java @@ -0,0 +1,72 @@ +package com.pi4j.plugin.linuxfs.provider.onewire; + +/* + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: LinuxFS I/O Providers + * FILENAME : LinuxFsOneWireProvider.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.io.onewire.OneWireProvider; +import com.pi4j.plugin.linuxfs.LinuxFsPlugin; + +/** + * The {@code LinuxFsOneWireProvider} interface defines the provider for OneWire functionality + * based on the Linux filesystem. It serves as a bridge between the Pi4J framework and the + * OneWire devices accessed via the Linux file system. + */ +public interface LinuxFsOneWireProvider extends OneWireProvider { + + /** + * The name identifier for the Linux Filesystem OneWire provider. + * This name is used for logging, configuration, and identification purposes. + */ + String NAME = LinuxFsPlugin.ONE_WIRE_PROVIDER_NAME; + + /** + * The unique identifier for the Linux Filesystem OneWire provider. + * This ID is used internally by the Pi4J framework to differentiate providers. + */ + String ID = LinuxFsPlugin.ONE_WIRE_PROVIDER_ID; + + /** + * Creates a new instance of {@code LinuxFsOneWireProvider} with the specified + * filesystem path for OneWire devices. + * + * @param oneWireFileSystemPath the file system path where the OneWire devices are located. + * @return a new {@link LinuxFsOneWireProvider} instance configured with the specified path. + */ + static LinuxFsOneWireProvider newInstance(String oneWireFileSystemPath) { + return new LinuxFsOneWireProviderImpl(oneWireFileSystemPath); + } + + /** + * Creates a new instance of {@code LinuxFsOneWireProvider} using the default + * filesystem path for OneWire devices defined in {@link LinuxFsPlugin#DEFAULT_ONE_WIRE_FILESYSTEM_PATH}. + * + * @return a new {@link LinuxFsOneWireProvider} instance configured with the default path. + */ + static LinuxFsOneWireProvider newInstance() { + return new LinuxFsOneWireProviderImpl(LinuxFsPlugin.DEFAULT_ONE_WIRE_FILESYSTEM_PATH); + } +} diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProviderImpl.java b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProviderImpl.java new file mode 100644 index 000000000..3b2e54c42 --- /dev/null +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/com/pi4j/plugin/linuxfs/provider/onewire/LinuxFsOneWireProviderImpl.java @@ -0,0 +1,90 @@ +package com.pi4j.plugin.linuxfs.provider.onewire; + +/* + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: LinuxFS I/O Providers + * FILENAME : LinuxFsOneWireProviderImpl.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.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireProviderBase; +import com.pi4j.plugin.linuxfs.internal.LinuxOneWire; + +/** + * The {@code LinuxFsOneWireProviderImpl} class implements the {@link LinuxFsOneWireProvider} interface + * and serves as the concrete implementation for the OneWire provider based on the Linux filesystem. + *

+ * This provider manages the creation and configuration of OneWire instances that interact with + * the Linux filesystem for hardware communication. + */ +public class LinuxFsOneWireProviderImpl extends OneWireProviderBase implements LinuxFsOneWireProvider { + + /** + * The file system path where OneWire devices are located. + * This path is used to initialize and manage OneWire interactions. + */ + final String oneWireFileSystemPath; + + /** + * Constructs a new instance of {@code LinuxFsOneWireProviderImpl} with the specified filesystem path. + * + * @param oneWireFileSystemPath the path in the Linux filesystem where OneWire devices are located. + */ + public LinuxFsOneWireProviderImpl(String oneWireFileSystemPath) { + this.id = ID; // Assign the unique provider ID + this.name = NAME; // Assign the provider name + this.oneWireFileSystemPath = oneWireFileSystemPath; // Store the specified file system path + } + + /** + * Returns the priority of this provider. Providers with lower priority values + * are preferred during provider selection in the Pi4J framework. + * + * @return the priority value for this provider, default is 50. + */ + @Override + public int getPriority() { + return 50; + } + + /** + * Creates a new {@link OneWire} instance based on the provided configuration. + *

+ * This method initializes a filesystem-based OneWire instance using the provided + * configuration and registers it with the Pi4J context registry. + * + * @param config the {@link OneWireConfig} containing configuration details for the OneWire instance. + * @return a {@link OneWire} object representing the created OneWire instance. + */ + @Override + public OneWire create(OneWireConfig config) { + LinuxOneWire oneWire = new LinuxOneWire(this.oneWireFileSystemPath, config.device()); + LinuxFsOneWire fsOneWire = new LinuxFsOneWire(oneWire, this, config); + this.context.registry().add(fsOneWire); + return fsOneWire; + } +} + diff --git a/plugins/pi4j-plugin-linuxfs/src/main/java/module-info.java b/plugins/pi4j-plugin-linuxfs/src/main/java/module-info.java index a9bcdde63..64a280b7b 100644 --- a/plugins/pi4j-plugin-linuxfs/src/main/java/module-info.java +++ b/plugins/pi4j-plugin-linuxfs/src/main/java/module-info.java @@ -33,13 +33,14 @@ requires com.pi4j; requires com.pi4j.library.linuxfs; - requires jsch; requires com.sun.jna; + requires jsch; exports com.pi4j.plugin.linuxfs; exports com.pi4j.plugin.linuxfs.provider.gpio.digital; exports com.pi4j.plugin.linuxfs.provider.pwm; exports com.pi4j.plugin.linuxfs.provider.i2c; + exports com.pi4j.plugin.linuxfs.provider.onewire; exports com.pi4j.plugin.linuxfs.provider.spi; provides com.pi4j.extension.Plugin diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/Mock.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/Mock.java index 4fada79c6..d7b4dda07 100644 --- a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/Mock.java +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/Mock.java @@ -94,4 +94,10 @@ public class Mock { public static final String SERIAL_PROVIDER_NAME = NAME + " Serial Provider"; /** Constant SERIAL_PROVIDER_ID="ID + -serial" */ public static final String SERIAL_PROVIDER_ID = ID + "-serial"; + + // 1-Wire Provider name and unique ID + /** Constant ONE_WIRE_PROVIDER_NAME="NAME + Serial Provider" */ + public static final String ONE_WIRE_PROVIDER_NAME = NAME + " 1-Wire Provider"; + /** Constant ONE_WIRE_PROVIDER_ID="ID + -serial" */ + public static final String ONE_WIRE_PROVIDER_ID = ID + "-one-wire"; } diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/MockPlugin.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/MockPlugin.java index f5ca2beb1..5fd42bdae 100644 --- a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/MockPlugin.java +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/MockPlugin.java @@ -35,6 +35,7 @@ import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalInputProvider; import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalOutputProvider; import com.pi4j.plugin.mock.provider.i2c.MockI2CProvider; +import com.pi4j.plugin.mock.provider.onewire.MockOneWireProvider; import com.pi4j.plugin.mock.provider.pwm.MockPwmProvider; import com.pi4j.plugin.mock.provider.serial.MockSerialProvider; import com.pi4j.plugin.mock.provider.spi.MockSpiProvider; @@ -49,14 +50,15 @@ public class MockPlugin implements Plugin { private final Provider[] providers = { - MockAnalogInputProvider.newInstance(), - MockAnalogOutputProvider.newInstance(), - MockDigitalInputProvider.newInstance(), - MockDigitalOutputProvider.newInstance(), - MockPwmProvider.newInstance(), - MockI2CProvider.newInstance(), - MockSpiProvider.newInstance(), - MockSerialProvider.newInstance(), + MockAnalogInputProvider.newInstance(), + MockAnalogOutputProvider.newInstance(), + MockDigitalInputProvider.newInstance(), + MockDigitalOutputProvider.newInstance(), + MockPwmProvider.newInstance(), + MockI2CProvider.newInstance(), + MockSpiProvider.newInstance(), + MockSerialProvider.newInstance(), + MockOneWireProvider.newInstance() }; @Override @@ -64,7 +66,9 @@ public boolean isMock() { return true; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void initialize(PluginService service) { diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/platform/MockPlatform.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/platform/MockPlatform.java index 14e2d9abc..726fb459c 100644 --- a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/platform/MockPlatform.java +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/platform/MockPlatform.java @@ -36,6 +36,7 @@ import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalInputProvider; import com.pi4j.plugin.mock.provider.gpio.digital.MockDigitalOutputProvider; import com.pi4j.plugin.mock.provider.i2c.MockI2CProvider; +import com.pi4j.plugin.mock.provider.onewire.MockOneWireProvider; import com.pi4j.plugin.mock.provider.pwm.MockPwmProvider; import com.pi4j.plugin.mock.provider.serial.MockSerialProvider; import com.pi4j.plugin.mock.provider.spi.MockSpiProvider; @@ -87,6 +88,8 @@ protected String[] getProviders() { MockPwmProvider.ID, MockSpiProvider.ID, MockI2CProvider.ID, - MockSerialProvider.ID }; + MockSerialProvider.ID, + MockOneWireProvider.ID + }; } } diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWire.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWire.java new file mode 100644 index 000000000..320b36b77 --- /dev/null +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWire.java @@ -0,0 +1,198 @@ +package com.pi4j.plugin.mock.provider.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: Mock Platform & Providers + * FILENAME : MockOneWire.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.io.exception.IOException; +import com.pi4j.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireBase; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Mock implementation of the OneWire interface for testing and simulation purposes. + * This class provides methods to read and write to mock 1-Wire files. + */ +public class MockOneWire extends OneWireBase implements OneWire { + + private static final Logger logger = LoggerFactory.getLogger(MockOneWire.class); + + // Stores the content of "files" as a map, where each file's content is a Byte array. + protected final Map content = new HashMap<>(); + + /** + * Constructs a new {@code MockOneWire} instance. + * + * @param provider the {@link OneWireProvider} used to manage 1-Wire communication. + * @param config the {@link OneWireConfig} specifying configuration settings for this instance. + */ + public MockOneWire(OneWireProvider provider, OneWireConfig config) { + super(provider, config); + logger.debug("[{}::{}] :: CREATE(DEVICE={})", + provider.name(), this.id(), config.device()); + } + + /** + * Reads the entire content of a mock file and splits it into lines using the system's line separator. + * + * @param fileName the name of the file to read. + * @return a collection of strings, each representing a line from the file. + * @throws IOException if the file does not exist or cannot be read. + */ + @Override + public List readFile(String fileName) throws IOException { + byte[] input = getContentFile(fileName); + String contentString = new String(input, UTF_8); + logger.debug("[{}::{}] :: READ FILE ({}): {}", + provider.name(), this.id(), fileName, contentString); + return Arrays.asList(contentString.split(System.lineSeparator())); + } + + /** + * Reads the first line of a mock file. + * + * @param fileName the name of the file to read. + * @return the first line of the file, or an empty string if the file is empty or does not exist. + * @throws IOException if the file does not exist or cannot be read. + */ + @Override + public String readFirstLine(String fileName) throws IOException { + byte[] input = getContentFile(fileName); + String contentString = new String(input, UTF_8); + String[] lines = contentString.split(System.lineSeparator()); + String result = lines.length > 0 ? lines[0] : ""; + logger.debug("[{}::{}] :: READ FILE LINE ({}): {}", + provider.name(), this.id(), fileName, result); + return result; + } + + /** + * Reads the entire content of a mock file as a byte array. + * + * @param fileName the name of the file to read. + * @return a byte array containing the file's content, or an empty array if the file does not exist. + * @throws IOException if the file cannot be read. + */ + @Override + public byte[] readFileAsBytes(String fileName) throws IOException { + byte[] input = getContentFile(fileName); + logger.debug("[{}::{}] :: READ FILE AS BYTES ({}): 0x{}", + provider.name(), this.id(), fileName, Arrays.toString(input)); + return input; + } + + /** + * Writes a single byte to a mock file, overwriting any existing content. + * + * @param fileName the name of the file to write. + * @param value the byte to write to the file. + * @throws IOException if the file cannot be written. + */ + @Override + public void writeFile(String fileName, byte value) throws IOException { + content.put(fileName, new Byte[]{value}); + logger.debug("[{}::{}] :: WRITE FILE ({}): 0x{}", + provider.name(), this.id(), fileName, String.format("%02X", value)); + } + + /** + * Writes a byte array to a mock file, overwriting any existing content. + * + * @param fileName the name of the file to write. + * @param values the byte array to write to the file. + * @throws IOException if the file cannot be written. + */ + @Override + public void writeFile(String fileName, byte[] values) throws IOException { + content.put(fileName, toBoxed(values)); + logger.debug("[{}::{}] :: WRITE FILE ({}): 0x{}", + provider.name(), this.id(), fileName, Arrays.toString(values)); + } + + /** + * Writes a string to a mock file as UTF-8 encoded bytes, overwriting any existing content. + * + * @param fileName the name of the file to write. + * @param content the string content to write to the file. + * @throws IOException if the file cannot be written. + */ + @Override + public void writeFile(String fileName, String content) throws IOException { + byte[] byteArray = content.getBytes(UTF_8); + this.content.put(fileName, toBoxed(byteArray)); + logger.debug("[{}::{}] :: WRITE FILE ({}): {}", + provider.name(), this.id(), fileName, content); + } + + /** + * Retrieves the content of a mock file as a primitive byte array. + * + * @param fileName the name of the file to retrieve. + * @return the content of the file as a {@code byte[]} array, or an empty array if the file does not exist. + */ + private byte[] getContentFile(String fileName) { + return toPrimitive(content.getOrDefault(fileName, new Byte[0])); + } + + /** + * Converts a {@code Byte[]} array to a {@code byte[]} array. + * + * @param input the {@code Byte[]} array to convert. + * @return the converted {@code byte[]} array. + */ + private static byte[] toPrimitive(Byte[] input) { + byte[] result = new byte[input.length]; + IntStream + .range(0, input.length) + .forEach(i -> result[i] = input[i]); + return result; + } + + /** + * Converts a {@code byte[]} array to a {@code Byte[]} array. + * + * @param input the {@code byte[]} array to convert. + * @return the converted {@code Byte[]} array. + */ + private static Byte[] toBoxed(byte[] input) { + Byte[] result = new Byte[input.length]; + IntStream + .range(0, input.length) + .forEach(i -> result[i] = input[i]); + return result; + } +} diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProvider.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProvider.java new file mode 100644 index 000000000..2120a9a0d --- /dev/null +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProvider.java @@ -0,0 +1,46 @@ +package com.pi4j.plugin.mock.provider.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: Mock Platform & Providers + * FILENAME : MockSerialProvider.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.io.onewire.OneWireProvider; +import com.pi4j.plugin.mock.Mock; + +public interface MockOneWireProvider extends OneWireProvider { + /** Constant NAME="Mock.ONE_WIRE_PROVIDER_NAME" */ + String NAME = Mock.ONE_WIRE_PROVIDER_NAME; + /** Constant ID="Mock.ONE_WIRE_PROVIDER_ID" */ + String ID = Mock.ONE_WIRE_PROVIDER_ID; + /** + *

newInstance.

+ * + * @return a {@link MockOneWireProvider} object. + */ + static MockOneWireProvider newInstance() { + return new MockOneWireProviderImpl(); + } +} diff --git a/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProviderImpl.java b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProviderImpl.java new file mode 100644 index 000000000..70e97a6bd --- /dev/null +++ b/plugins/pi4j-plugin-mock/src/main/java/com/pi4j/plugin/mock/provider/onewire/MockOneWireProviderImpl.java @@ -0,0 +1,56 @@ +package com.pi4j.plugin.mock.provider.onewire; + +/*- + * #%L + * ********************************************************************** + * ORGANIZATION : Pi4J + * PROJECT : Pi4J :: PLUGIN :: Mock Platform & Providers + * FILENAME : MockOneWireProviderImpl.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.io.onewire.OneWire; +import com.pi4j.io.onewire.OneWireConfig; +import com.pi4j.io.onewire.OneWireProviderBase; + +public class MockOneWireProviderImpl extends OneWireProviderBase implements MockOneWireProvider { + + /** + *

Constructor for MockSerialProviderImpl.

+ */ + public MockOneWireProviderImpl() { + this.id = ID; + this.name = NAME; + } + + @Override + public OneWire create(OneWireConfig config) { + MockOneWire oneWire = new MockOneWire(this, config); + this.context.registry().add(oneWire); + return oneWire; + } + + @Override + public int getPriority() { + // if the mock is loaded, then we most probably want to use it for testing + return 1000; + } +} diff --git a/plugins/pi4j-plugin-mock/src/main/java/module-info.java b/plugins/pi4j-plugin-mock/src/main/java/module-info.java index 34d5fd4f9..6c74a46cb 100644 --- a/plugins/pi4j-plugin-mock/src/main/java/module-info.java +++ b/plugins/pi4j-plugin-mock/src/main/java/module-info.java @@ -38,6 +38,7 @@ exports com.pi4j.plugin.mock.provider.serial; exports com.pi4j.plugin.mock.provider.spi; exports com.pi4j.plugin.mock.provider.i2c; + exports com.pi4j.plugin.mock.provider.onewire; provides com.pi4j.extension.Plugin with com.pi4j.plugin.mock.MockPlugin;