commit 16/06/2025

This commit is contained in:
2025-06-16 17:46:54 +07:00
parent 501bca8487
commit fd1b53e3a8
6 changed files with 145 additions and 9 deletions

View File

@@ -1,7 +1,10 @@
import database.ContactInputData;
import database.Database;
import gpio.NanopiGpio;
import mqtt.MqttClient;
import org.tinylog.Logger;
import pa.VX3K;
import pa.VX3KPseudoContactInput;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
@@ -10,13 +13,21 @@ public class Main {
private static MqttClient mqttClient;
private static NanopiGpio gpio;
private static Database db;
private static VX3K vx3K;
// Application entry point
public static void main(String[] args) {
Logger.info("Application started");
// initialize config
config = new config();
// initialize database
db = new Database();
//db.contactInputDataList.forEach(System.out::println);
// initialize VX3K
vx3K = new VX3K(config.getVX3KTargetIP(), config.getVX3KTargetPort());
// Initialize the GPIO pins
gpio = new NanopiGpio();
// cek di https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo20
@@ -29,6 +40,10 @@ public class Main {
}, pinStatus -> {
// TODO Handle pin status updates here
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
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()),
@@ -39,7 +54,27 @@ public class Main {
Logger.error("Failed to publish pin status update.");
}
});
}
if (cib.isEnableEmail()){
// 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
}
}
},

View File

@@ -1,7 +1,17 @@
import com.google.gson.Gson;
public class Somecodes {
public static String currentdirectory = System.getProperty("user.dir");
public static Gson gson = new Gson();
}

View File

@@ -15,7 +15,6 @@ import java.util.List;
public class Database {
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 Database(){
CreateContactInputDataTable();
@@ -83,6 +82,8 @@ public class Database {
return loadedData;
}
/**
* Load ContactInputData into the contactInputDataList.
* @param loadedData List of ContactInputData objects loaded from the database.
@@ -90,6 +91,8 @@ public class Database {
@SuppressWarnings("ExtractMethodRecommender")
private void LoadContactInputDataList(List<ContactInputData> loadedData){
contactInputDataList.clear();
// Maximum number of contact input data
int maxContactInputData = 16;
for (int i = 1; i <= maxContactInputData; i++){
final int contactID = i;
ContactInputData cid = loadedData.stream()
@@ -151,6 +154,24 @@ public class Database {
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.
* @param contactID The ID of the ContactInputData entry to be cleared.

43
src/pa/VX3K.java Normal file
View 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"));
}
}
}

View File

@@ -0,0 +1,4 @@
package pa;
public record VX3KCommandResult(int command, boolean success, String message) {
}

View 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));
}
}