commit 16/06/2025
This commit is contained in:
21
.idea/libraries/digitalpetri_modbus_master_tcp.xml
generated
21
.idea/libraries/digitalpetri_modbus_master_tcp.xml
generated
@@ -1,21 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="digitalpetri.modbus.master.tcp" type="repository">
|
|
||||||
<properties maven-id="com.digitalpetri.modbus:modbus-master-tcp:1.2.2" />
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/modbus-master-tcp-1.2.2.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/modbus-codec-1.2.2.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/modbus-core-1.2.2.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-buffer-4.1.105.Final.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-codec-4.1.105.Final.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-common-4.1.105.Final.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-transport-4.1.105.Final.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-resolver-4.1.105.Final.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/netty-channel-fsm-0.9.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/strict-machine-0.7.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/metrics-core-3.1.5.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/lib/slf4j-api-1.7.7.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
21
.idea/libraries/digitalpetri_modbus_tcp.xml
generated
Normal file
21
.idea/libraries/digitalpetri_modbus_tcp.xml
generated
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="digitalpetri.modbus.tcp" type="repository">
|
||||||
|
<properties maven-id="com.digitalpetri.modbus:modbus-tcp:2.1.0" />
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/modbus-tcp-2.1.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/modbus-2.1.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-buffer-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-common-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-codec-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-transport-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-handler-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-resolver-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-transport-native-unix-common-4.1.116.Final.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/netty-channel-fsm-1.0.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/strict-machine-1.0.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/slf4j-api-2.0.16.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
11
.idea/libraries/sun_mail_jakarta.xml
generated
Normal file
11
.idea/libraries/sun_mail_jakarta.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="sun.mail.jakarta" type="repository">
|
||||||
|
<properties maven-id="com.sun.mail:jakarta.mail:2.0.1" />
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jakarta.mail-2.0.1.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jakarta.activation-2.0.1.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
@@ -8,12 +8,13 @@
|
|||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="io.javalin" level="project" />
|
<orderEntry type="library" name="io.javalin" level="project" />
|
||||||
<orderEntry type="library" name="digitalpetri.modbus.master.tcp" level="project" />
|
|
||||||
<orderEntry type="library" name="projectlombok.lombok" level="project" />
|
<orderEntry type="library" name="projectlombok.lombok" level="project" />
|
||||||
<orderEntry type="library" name="google.code.gson" level="project" />
|
<orderEntry type="library" name="google.code.gson" level="project" />
|
||||||
<orderEntry type="library" name="tinylog.impl" level="project" />
|
<orderEntry type="library" name="tinylog.impl" level="project" />
|
||||||
<orderEntry type="library" name="tinylog.api" level="project" />
|
<orderEntry type="library" name="tinylog.api" level="project" />
|
||||||
<orderEntry type="library" name="hivemq.mqtt.client" level="project" />
|
<orderEntry type="library" name="hivemq.mqtt.client" level="project" />
|
||||||
<orderEntry type="library" name="xerial.sqlite.jdbc" level="project" />
|
<orderEntry type="library" name="xerial.sqlite.jdbc" level="project" />
|
||||||
|
<orderEntry type="library" name="sun.mail.jakarta" level="project" />
|
||||||
|
<orderEntry type="library" name="digitalpetri.modbus.tcp" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
BIN
lib/jakarta.activation-1.2.1.jar
Normal file
BIN
lib/jakarta.activation-1.2.1.jar
Normal file
Binary file not shown.
BIN
lib/jakarta.activation-2.0.1.jar
Normal file
BIN
lib/jakarta.activation-2.0.1.jar
Normal file
Binary file not shown.
BIN
lib/jakarta.mail-1.6.3.jar
Normal file
BIN
lib/jakarta.mail-1.6.3.jar
Normal file
Binary file not shown.
BIN
lib/jakarta.mail-2.0.1.jar
Normal file
BIN
lib/jakarta.mail-2.0.1.jar
Normal file
Binary file not shown.
BIN
lib/modbus-2.1.0.jar
Normal file
BIN
lib/modbus-2.1.0.jar
Normal file
Binary file not shown.
BIN
lib/modbus-slave-tcp-1.2.2.jar
Normal file
BIN
lib/modbus-slave-tcp-1.2.2.jar
Normal file
Binary file not shown.
BIN
lib/modbus-tcp-2.1.0.jar
Normal file
BIN
lib/modbus-tcp-2.1.0.jar
Normal file
Binary file not shown.
BIN
lib/netty-buffer-4.1.116.Final.jar
Normal file
BIN
lib/netty-buffer-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-channel-fsm-1.0.0.jar
Normal file
BIN
lib/netty-channel-fsm-1.0.0.jar
Normal file
Binary file not shown.
BIN
lib/netty-codec-4.1.116.Final.jar
Normal file
BIN
lib/netty-codec-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-common-4.1.116.Final.jar
Normal file
BIN
lib/netty-common-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-handler-4.1.105.Final.jar
Normal file
BIN
lib/netty-handler-4.1.105.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-handler-4.1.116.Final.jar
Normal file
BIN
lib/netty-handler-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-resolver-4.1.116.Final.jar
Normal file
BIN
lib/netty-resolver-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-transport-4.1.116.Final.jar
Normal file
BIN
lib/netty-transport-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-transport-native-unix-common-4.1.105.Final.jar
Normal file
BIN
lib/netty-transport-native-unix-common-4.1.105.Final.jar
Normal file
Binary file not shown.
BIN
lib/netty-transport-native-unix-common-4.1.116.Final.jar
Normal file
BIN
lib/netty-transport-native-unix-common-4.1.116.Final.jar
Normal file
Binary file not shown.
BIN
lib/slf4j-api-2.0.16.jar
Normal file
BIN
lib/slf4j-api-2.0.16.jar
Normal file
Binary file not shown.
BIN
lib/strict-machine-1.0.0.jar
Normal file
BIN
lib/strict-machine-1.0.0.jar
Normal file
Binary file not shown.
@@ -1,6 +1,8 @@
|
|||||||
import database.ContactInputData;
|
import database.ContactInputData;
|
||||||
import database.Database;
|
import database.Database;
|
||||||
import gpio.NanopiGpio;
|
import gpio.NanopiGpio;
|
||||||
|
import mail.SMTPSender;
|
||||||
|
import modbus.ModbusTCPServer;
|
||||||
import mqtt.MqttClient;
|
import mqtt.MqttClient;
|
||||||
import org.tinylog.Logger;
|
import org.tinylog.Logger;
|
||||||
import pa.VX3K;
|
import pa.VX3K;
|
||||||
@@ -14,6 +16,8 @@ public class Main {
|
|||||||
private static NanopiGpio gpio;
|
private static NanopiGpio gpio;
|
||||||
private static Database db;
|
private static Database db;
|
||||||
private static VX3K vx3K;
|
private static VX3K vx3K;
|
||||||
|
private static SMTPSender mailsender;
|
||||||
|
private static ModbusTCPServer modbusServer;
|
||||||
// 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");
|
||||||
@@ -28,6 +32,12 @@ public class Main {
|
|||||||
// initialize VX3K
|
// initialize VX3K
|
||||||
vx3K = new VX3K(config.getVX3KTargetIP(), config.getVX3KTargetPort());
|
vx3K = new VX3K(config.getVX3KTargetIP(), config.getVX3KTargetPort());
|
||||||
|
|
||||||
|
// initialize Email Sender
|
||||||
|
mailsender = new SMTPSender(config.getEmail_SMTPServer(), config.getEmail_SMTPPort(), true, config.getEmail_SMTPUsername(), config.getEmail_SMTPPassword());
|
||||||
|
|
||||||
|
modbusServer = new ModbusTCPServer(config.getModbus_MasterIP(), config.getModbus_Port(), 1000);
|
||||||
|
modbusServer.Start();
|
||||||
|
|
||||||
// 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
|
||||||
@@ -38,7 +48,6 @@ public class Main {
|
|||||||
Logger.error("GPIO pins closed or failed to open.");
|
Logger.error("GPIO pins closed or failed to open.");
|
||||||
}
|
}
|
||||||
}, pinStatus -> {
|
}, pinStatus -> {
|
||||||
// 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());
|
ContactInputData cib = db.GetContactInputData(pinStatus.getDescription());
|
||||||
@@ -57,6 +66,15 @@ public class Main {
|
|||||||
}
|
}
|
||||||
if (cib.isEnableEmail()){
|
if (cib.isEnableEmail()){
|
||||||
// Email notification can be added here
|
// Email notification can be added here
|
||||||
|
String subject = String.format("Fire Alarm Gateway - Pin %d Status Update", pinStatus.getGpioNumber());
|
||||||
|
String body = String.format("Pin %d with description '%s' has changed status to %d.", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus());
|
||||||
|
mailsender.SendEmail(config.getEmail_SMTPFrom(), cib.getEmailRecipient(), subject, body, sent -> {
|
||||||
|
if (sent) {
|
||||||
|
Logger.info("Email notification sent successfully.");
|
||||||
|
} else {
|
||||||
|
Logger.error("Failed to send email notification.");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (cib.isEnableVX3K()){
|
if (cib.isEnableVX3K()){
|
||||||
// VX3K Broadcast here
|
// VX3K Broadcast here
|
||||||
@@ -70,7 +88,9 @@ public class Main {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (cib.isEnableModbus()){
|
if (cib.isEnableModbus()){
|
||||||
// update Modbus Register here
|
if (modbusServer!=null){
|
||||||
|
modbusServer.SetRegister(cib.getContactID(), pinStatus.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +128,7 @@ public class Main {
|
|||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
if (gpio!=null && gpio.IsOpened()) gpio.Close();
|
if (gpio!=null && gpio.IsOpened()) gpio.Close();
|
||||||
if (mqttClient!=null && mqttClient.isConnected()) mqttClient.Disconnect();
|
if (mqttClient!=null && mqttClient.isConnected()) mqttClient.Disconnect();
|
||||||
|
if (modbusServer!=null && modbusServer.isRunning()) modbusServer.Stop();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
63
src/mail/SMTPSender.java
Normal file
63
src/mail/SMTPSender.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package mail;
|
||||||
|
|
||||||
|
import jakarta.mail.*;
|
||||||
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
import jakarta.mail.internet.MimeMessage;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class SMTPSender {
|
||||||
|
final Properties props;
|
||||||
|
final String username;
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for SMTPSender
|
||||||
|
* @param smtpHost the SMTP server host
|
||||||
|
* @param port the SMTP server port
|
||||||
|
* @param useSSL true to use SSL, false to use STARTTLS
|
||||||
|
* @param username the username for SMTP authentication
|
||||||
|
* @param password the password for SMTP authentication
|
||||||
|
*/
|
||||||
|
public SMTPSender(String smtpHost, int port, boolean useSSL, String username, String password){
|
||||||
|
props = new Properties();
|
||||||
|
props.put("mail.smtp.auth", "true");
|
||||||
|
props.put("mail.smtp.starttls.enable", String.valueOf(useSSL)); // Enable STARTTLS
|
||||||
|
props.put("mail.smtp.host", smtpHost);
|
||||||
|
props.put("mail.smtp.port", String.valueOf(port));
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an email using the configured SMTP settings.
|
||||||
|
*
|
||||||
|
* @param fromEmail the sender's email address
|
||||||
|
* @param toEmail the recipient's email address
|
||||||
|
* @param Subject the subject of the email
|
||||||
|
* @param body the body of the email
|
||||||
|
* @param success a callback that receives true if the email was sent successfully, false otherwise
|
||||||
|
*/
|
||||||
|
public void SendEmail(String fromEmail, String toEmail, String Subject, String body, @NonNull Consumer<@NonNull Boolean> success){
|
||||||
|
try{
|
||||||
|
Session session = Session.getInstance(props, new Authenticator() {
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
return new PasswordAuthentication(username, password);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Message message = new MimeMessage(session);
|
||||||
|
message.setFrom(new InternetAddress(fromEmail));
|
||||||
|
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
|
||||||
|
message.setSubject(Subject);
|
||||||
|
message.setText(body);
|
||||||
|
|
||||||
|
Transport.send(message);
|
||||||
|
success.accept(true);
|
||||||
|
} catch (Exception e){
|
||||||
|
success.accept(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
107
src/modbus/ModbusTCPServer.java
Normal file
107
src/modbus/ModbusTCPServer.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package modbus;
|
||||||
|
|
||||||
|
import com.digitalpetri.modbus.exceptions.ModbusResponseException;
|
||||||
|
import com.digitalpetri.modbus.exceptions.UnknownUnitIdException;
|
||||||
|
import com.digitalpetri.modbus.pdu.ReadHoldingRegistersRequest;
|
||||||
|
import com.digitalpetri.modbus.pdu.ReadHoldingRegistersResponse;
|
||||||
|
import com.digitalpetri.modbus.server.ModbusRequestContext;
|
||||||
|
import com.digitalpetri.modbus.server.ModbusServices;
|
||||||
|
import com.digitalpetri.modbus.server.ModbusTcpServer;
|
||||||
|
import com.digitalpetri.modbus.tcp.server.NettyTcpServerTransport;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.tinylog.Logger;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||||
|
|
||||||
|
|
||||||
|
public class ModbusTCPServer {
|
||||||
|
private @Getter boolean isRunning = false;
|
||||||
|
private ModbusTcpServer server;
|
||||||
|
|
||||||
|
private final NettyTcpServerTransport transport;
|
||||||
|
private final ModbusServices services;
|
||||||
|
private final AtomicIntegerArray holdingregister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Modbus TCP server that listens on the specified bind address and port.
|
||||||
|
*
|
||||||
|
* @param bindAddress the IP address to bind the server to
|
||||||
|
* @param port the port number to listen on
|
||||||
|
* @param holdingRegisterSize size of the holding register array
|
||||||
|
*/
|
||||||
|
public ModbusTCPServer(String bindAddress, int port, int holdingRegisterSize) {
|
||||||
|
this.holdingregister = new AtomicIntegerArray(holdingRegisterSize);
|
||||||
|
transport = NettyTcpServerTransport.create(cfg ->{
|
||||||
|
cfg.bindAddress = bindAddress;
|
||||||
|
cfg.port = port;
|
||||||
|
});
|
||||||
|
services = new ModbusServices() {
|
||||||
|
@SuppressWarnings("RedundantThrows")
|
||||||
|
@Override
|
||||||
|
public ReadHoldingRegistersResponse readHoldingRegisters(ModbusRequestContext context, int unitId, ReadHoldingRegistersRequest request) throws ModbusResponseException, UnknownUnitIdException {
|
||||||
|
ByteBuffer result = ByteBuffer.allocate(request.quantity()*2);
|
||||||
|
ShortBuffer xx = result.asShortBuffer();
|
||||||
|
for (int i = 0; i < request.quantity(); i++) {
|
||||||
|
int value = holdingregister.get(request.address() + i);
|
||||||
|
xx.put((short) value);
|
||||||
|
}
|
||||||
|
return new ReadHoldingRegistersResponse(result.array());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of a holding register at the specified address.
|
||||||
|
* @param address the address of the holding register (0-based index)
|
||||||
|
* @param value the value to set (should be in the range of a 16-bit integer)
|
||||||
|
*/
|
||||||
|
public void SetRegister(int address, int value) {
|
||||||
|
if (address < 0 || address >= holdingregister.length()) {
|
||||||
|
throw new IndexOutOfBoundsException("Address out of bounds: " + address);
|
||||||
|
}
|
||||||
|
holdingregister.set(address, (short) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the Modbus TCP server.
|
||||||
|
* @return true if the server started successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean Start(){
|
||||||
|
isRunning = false;
|
||||||
|
try{
|
||||||
|
var newserver = ModbusTcpServer.create(transport, services);
|
||||||
|
newserver.start();
|
||||||
|
server = newserver;
|
||||||
|
isRunning = true;
|
||||||
|
Logger.info("Modbus TCP server started");
|
||||||
|
} catch (Exception e){
|
||||||
|
Logger.error("Failed to start Modbus TCP server: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the Modbus TCP server.
|
||||||
|
*/
|
||||||
|
public void Stop(){
|
||||||
|
if (isRunning){
|
||||||
|
if (server!=null){
|
||||||
|
try {
|
||||||
|
server.stop();
|
||||||
|
Logger.info("Modbus TCP server stopped successfully.");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error("Failed to stop Modbus TCP server: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
server = null;
|
||||||
|
} else {
|
||||||
|
Logger.warn("Modbus TCP server instance is null, cannot stop.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Logger.warn("Modbus TCP server is not running.");
|
||||||
|
}
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user