commit 16/06/2025
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
|
import database.ContactInputData;
|
||||||
import database.Database;
|
import database.Database;
|
||||||
import gpio.NanopiGpio;
|
import gpio.NanopiGpio;
|
||||||
import mqtt.MqttClient;
|
import mqtt.MqttClient;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
|
import pa.VX3K;
|
||||||
|
import pa.VX3KPseudoContactInput;
|
||||||
|
|
||||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
||||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
||||||
@@ -10,13 +13,21 @@ public class Main {
|
|||||||
private static MqttClient mqttClient;
|
private static MqttClient mqttClient;
|
||||||
private static NanopiGpio gpio;
|
private static NanopiGpio gpio;
|
||||||
private static Database db;
|
private static Database db;
|
||||||
|
private static VX3K vx3K;
|
||||||
// Application entry point
|
// Application entry point
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Logger.info("Application started");
|
Logger.info("Application started");
|
||||||
|
|
||||||
|
// initialize config
|
||||||
config = new config();
|
config = new config();
|
||||||
|
|
||||||
|
// initialize database
|
||||||
db = new Database();
|
db = new Database();
|
||||||
//db.contactInputDataList.forEach(System.out::println);
|
//db.contactInputDataList.forEach(System.out::println);
|
||||||
|
|
||||||
|
// initialize VX3K
|
||||||
|
vx3K = new VX3K(config.getVX3KTargetIP(), config.getVX3KTargetPort());
|
||||||
|
|
||||||
// Initialize the GPIO pins
|
// Initialize the GPIO pins
|
||||||
gpio = new NanopiGpio();
|
gpio = new NanopiGpio();
|
||||||
// cek di https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo20
|
// cek di https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo20
|
||||||
@@ -29,6 +40,10 @@ public class Main {
|
|||||||
}, pinStatus -> {
|
}, pinStatus -> {
|
||||||
// TODO Handle pin status updates here
|
// TODO Handle pin status updates here
|
||||||
Logger.info("Gpio {}, Description {}, status updated to {}", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus());
|
Logger.info("Gpio {}, Description {}, status updated to {}", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus());
|
||||||
|
|
||||||
|
ContactInputData cib = db.GetContactInputData(pinStatus.getDescription());
|
||||||
|
if (cib!=null){
|
||||||
|
if (cib.isEnableMQTT()){
|
||||||
// MQTT publish pin status update
|
// MQTT publish pin status update
|
||||||
if (mqttClient != null && mqttClient.isConnected()) mqttClient.Publish(config.getMQTT_Topic(), config.getMQTT_ClientID(),
|
if (mqttClient != null && mqttClient.isConnected()) mqttClient.Publish(config.getMQTT_Topic(), config.getMQTT_ClientID(),
|
||||||
String.format("Gpio %d, Description %s, Status %d", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus()),
|
String.format("Gpio %d, Description %s, Status %d", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus()),
|
||||||
@@ -39,7 +54,27 @@ public class Main {
|
|||||||
Logger.error("Failed to publish pin status update.");
|
Logger.error("Failed to publish pin status update.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (cib.isEnableEmail()){
|
||||||
// Email notification can be added here
|
// Email notification can be added here
|
||||||
|
}
|
||||||
|
if (cib.isEnableVX3K()){
|
||||||
|
// VX3K Broadcast here
|
||||||
|
VX3KPseudoContactInput cmd = new VX3KPseudoContactInput(cib.getVX3KFrameID(), cib.getVX3KContactID(), pinStatus.getStatus()==1);
|
||||||
|
vx3K.PseudoContactInput(cmd, result -> {
|
||||||
|
if (result.success()){
|
||||||
|
Logger.info("VX3K PseudoContactInput successfully executed.");
|
||||||
|
} else {
|
||||||
|
Logger.error("VX3K PseudoContactInput failed to execute, Message {}.", result.message());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (cib.isEnableModbus()){
|
||||||
|
// update Modbus Register here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class Somecodes {
|
public class Somecodes {
|
||||||
|
|
||||||
public static String currentdirectory = System.getProperty("user.dir");
|
public static String currentdirectory = System.getProperty("user.dir");
|
||||||
public static Gson gson = new Gson();
|
public static Gson gson = new Gson();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import java.util.List;
|
|||||||
public class Database {
|
public class Database {
|
||||||
|
|
||||||
private static final String DB_NAME = "jdbc:sqlite:database.sqlite";
|
private static final String DB_NAME = "jdbc:sqlite:database.sqlite";
|
||||||
private final int maxContactInputData = 16; // Maximum number of contact input data
|
|
||||||
public final List<ContactInputData> contactInputDataList = new ArrayList<>();
|
public final List<ContactInputData> contactInputDataList = new ArrayList<>();
|
||||||
public Database(){
|
public Database(){
|
||||||
CreateContactInputDataTable();
|
CreateContactInputDataTable();
|
||||||
@@ -83,6 +82,8 @@ public class Database {
|
|||||||
return loadedData;
|
return loadedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load ContactInputData into the contactInputDataList.
|
* Load ContactInputData into the contactInputDataList.
|
||||||
* @param loadedData List of ContactInputData objects loaded from the database.
|
* @param loadedData List of ContactInputData objects loaded from the database.
|
||||||
@@ -90,6 +91,8 @@ public class Database {
|
|||||||
@SuppressWarnings("ExtractMethodRecommender")
|
@SuppressWarnings("ExtractMethodRecommender")
|
||||||
private void LoadContactInputDataList(List<ContactInputData> loadedData){
|
private void LoadContactInputDataList(List<ContactInputData> loadedData){
|
||||||
contactInputDataList.clear();
|
contactInputDataList.clear();
|
||||||
|
// Maximum number of contact input data
|
||||||
|
int maxContactInputData = 16;
|
||||||
for (int i = 1; i <= maxContactInputData; i++){
|
for (int i = 1; i <= maxContactInputData; i++){
|
||||||
final int contactID = i;
|
final int contactID = i;
|
||||||
ContactInputData cid = loadedData.stream()
|
ContactInputData cid = loadedData.stream()
|
||||||
@@ -151,6 +154,24 @@ public class Database {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ContactInputData by ID
|
||||||
|
* @param contactID ID to get
|
||||||
|
* @return ContactInputData object if exists, or null if not exists
|
||||||
|
*/
|
||||||
|
public ContactInputData GetContactInputData(int contactID){
|
||||||
|
return contactInputDataList.stream().filter(x -> x.getContactID() == contactID).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get ContactInputData by description
|
||||||
|
* @param description Description to get
|
||||||
|
* @return ContactInputData if exists, or null if not exists
|
||||||
|
*/
|
||||||
|
public ContactInputData GetContactInputData(String description){
|
||||||
|
return contactInputDataList.stream().filter(x -> x.getDescription().equals(description)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the content of a specific ContactInputData entry in the database.
|
* Clear the content of a specific ContactInputData entry in the database.
|
||||||
* @param contactID The ID of the ContactInputData entry to be cleared.
|
* @param contactID The ID of the ContactInputData entry to be cleared.
|
||||||
|
|||||||
43
src/pa/VX3K.java
Normal file
43
src/pa/VX3K.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package pa;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class VX3K {
|
||||||
|
private final InetSocketAddress inetSocketAddress;
|
||||||
|
|
||||||
|
public VX3K(String ipaddress, int port){
|
||||||
|
this.inetSocketAddress = new InetSocketAddress(ipaddress, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PseudoContactInput(VX3KPseudoContactInput input, @NonNull Consumer<@NonNull VX3KCommandResult> callback){
|
||||||
|
|
||||||
|
try(SocketChannel channel = SocketChannel.open(inetSocketAddress)){
|
||||||
|
channel.write(input.getBuffer());
|
||||||
|
input.getBuffer().clear();
|
||||||
|
int read = channel.read(input.getBuffer());
|
||||||
|
if (read>0){
|
||||||
|
short command = input.getBuffer().getShort(0);
|
||||||
|
short responsecode = input.getBuffer().getShort(1);
|
||||||
|
if (command == input.getCommandID()){
|
||||||
|
if (responsecode == 0x0000){
|
||||||
|
callback.accept(new VX3KCommandResult(input.getCommandID(), true, "success"));
|
||||||
|
} else callback.accept(new VX3KCommandResult(input.getCommandID(), false , "Code:"+responsecode ));
|
||||||
|
} else callback.accept(new VX3KCommandResult(input.getCommandID(), false, "Invalid CommandID reply"));
|
||||||
|
} else callback.accept( new VX3KCommandResult(input.getCommandID(), false, "Read 0"));
|
||||||
|
} catch (Exception e){
|
||||||
|
Logger.error("PseudoContactInput failed, Message {}", e.getMessage());
|
||||||
|
callback.accept(new VX3KCommandResult(input.getCommandID(), false, "Exception"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
4
src/pa/VX3KCommandResult.java
Normal file
4
src/pa/VX3KCommandResult.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package pa;
|
||||||
|
|
||||||
|
public record VX3KCommandResult(int command, boolean success, String message) {
|
||||||
|
}
|
||||||
23
src/pa/VX3KPseudoContactInput.java
Normal file
23
src/pa/VX3KPseudoContactInput.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package pa;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class VX3KPseudoContactInput{
|
||||||
|
private final @Getter int CommandID;
|
||||||
|
private final @Getter ByteBuffer buffer;
|
||||||
|
public VX3KPseudoContactInput(int FrameID, int contactID, boolean isON){
|
||||||
|
final int length = 8 + 6; // 8 bytes header + 6 bytes payload
|
||||||
|
CommandID = 0x1001;
|
||||||
|
buffer = ByteBuffer.allocate(length);
|
||||||
|
buffer.putShort((short) CommandID);
|
||||||
|
buffer.putShort((short) 0);
|
||||||
|
buffer.putShort((short) length);
|
||||||
|
buffer.putShort((short) 0x8000);
|
||||||
|
buffer.putShort((short) FrameID);
|
||||||
|
buffer.putShort((short) contactID);
|
||||||
|
buffer.putShort((short)(isON ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user