commit 30/06/2025

This commit is contained in:
2025-06-30 09:03:08 +07:00
parent 0d572514db
commit b8d185f46a
7 changed files with 258 additions and 117 deletions

View File

@@ -1,8 +1,10 @@
package additional;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.tinylog.Logger;
import web.webSettingArgs;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -43,33 +45,28 @@ public class config {
Logger.info("additional.config content: {}", configContent);
config loadedConfig = Somecodes.gson.fromJson(configContent, config.class);
Logger.info("Loaded additional.config from {}", loadedConfig.toString());
if (loadedConfig != null) {
// Copy values from loadedConfig to this instance
this.Modbus_MasterIP = loadedConfig.Modbus_MasterIP;
this.Modbus_Port = loadedConfig.Modbus_Port;
this.Modbus_SlaveID = loadedConfig.Modbus_SlaveID;
this.VX3KTargetIP = loadedConfig.VX3KTargetIP;
this.VX3KTargetPort = loadedConfig.VX3KTargetPort;
this.Email_SMTPServer = loadedConfig.Email_SMTPServer;
this.Email_SMTPPort = loadedConfig.Email_SMTPPort;
this.Email_SMTPSSL = loadedConfig.Email_SMTPSSL;
this.Email_SMTPUsername = loadedConfig.Email_SMTPUsername;
this.Email_SMTPPassword = loadedConfig.Email_SMTPPassword;
this.Email_SMTPFrom = loadedConfig.Email_SMTPFrom;
this.Email_SenderName = loadedConfig.Email_SenderName;
this.Email_Subject = loadedConfig.Email_Subject;
this.MQTT_Broker = loadedConfig.MQTT_Broker;
this.MQTT_Port = loadedConfig.MQTT_Port;
this.MQTT_Topic = loadedConfig.MQTT_Topic;
this.MQTT_ClientID = loadedConfig.MQTT_ClientID;
this.MQTT_Username = loadedConfig.MQTT_Username;
this.MQTT_Password = loadedConfig.MQTT_Password;
this.WebListenPort = loadedConfig.WebListenPort;
// Copy values from loadedConfig to this instance
this.Modbus_MasterIP = loadedConfig.Modbus_MasterIP;
this.Modbus_Port = loadedConfig.Modbus_Port;
this.Modbus_SlaveID = loadedConfig.Modbus_SlaveID;
this.VX3KTargetIP = loadedConfig.VX3KTargetIP;
this.VX3KTargetPort = loadedConfig.VX3KTargetPort;
this.Email_SMTPServer = loadedConfig.Email_SMTPServer;
this.Email_SMTPPort = loadedConfig.Email_SMTPPort;
this.Email_SMTPSSL = loadedConfig.Email_SMTPSSL;
this.Email_SMTPUsername = loadedConfig.Email_SMTPUsername;
this.Email_SMTPPassword = loadedConfig.Email_SMTPPassword;
this.Email_SMTPFrom = loadedConfig.Email_SMTPFrom;
this.Email_SenderName = loadedConfig.Email_SenderName;
this.Email_Subject = loadedConfig.Email_Subject;
this.MQTT_Broker = loadedConfig.MQTT_Broker;
this.MQTT_Port = loadedConfig.MQTT_Port;
this.MQTT_Topic = loadedConfig.MQTT_Topic;
this.MQTT_ClientID = loadedConfig.MQTT_ClientID;
this.MQTT_Username = loadedConfig.MQTT_Username;
this.MQTT_Password = loadedConfig.MQTT_Password;
this.WebListenPort = loadedConfig.WebListenPort;
} else {
Logger.error("Loaded additional.config is null, creating Default Config");
MakeDefaults();
}
} catch (Exception e){
Logger.error("Failed to read additional.config file: {}, creating Default Config", e.getMessage());
MakeDefaults();
@@ -84,9 +81,9 @@ public class config {
* Create default configuration values.
* This method sets default values for all configuration fields.
*/
private void MakeDefaults() {
public void MakeDefaults() {
// Set default values if needed
Modbus_MasterIP = "192.168.10.1";
Modbus_MasterIP = "0.0.0.0";
Modbus_Port = 502;
Modbus_SlaveID = "1";
VX3KTargetIP = "192.168.14.1";
@@ -115,6 +112,7 @@ public class config {
* This method serializes the configuration object to JSON and writes it to a file.
* @return true if the save operation was successful, false otherwise.
*/
@SuppressWarnings("UnusedReturnValue")
public boolean Save(){
Path configPath = Path.of(Somecodes.currentdirectory, "additional.config.json");
String gs = Somecodes.gson.toJson(this);
@@ -127,4 +125,100 @@ public class config {
}
return false;
}
/**
* Check if the current configuration is equal to another configuration.
* @param other the other configuration to compare with
* @return true if the configurations are equal, false otherwise.
*/
@SuppressWarnings({"RedundantIfStatement", "unused"})
public boolean IsEqual(@NonNull config other){
if (!other.getMQTT_ClientID().equals(MQTT_ClientID)) return false;
if (!other.getMQTT_Broker().equals(MQTT_Broker)) return false;
if (other.getMQTT_Port() != MQTT_Port) return false;
if (!other.getMQTT_Topic().equals(MQTT_Topic)) return false;
if (!other.getMQTT_Username().equals(MQTT_Username)) return false;
if (!other.getMQTT_Password().equals(MQTT_Password)) return false;
if (!other.getVX3KTargetIP().equals(VX3KTargetIP)) return false;
if (other.getVX3KTargetPort() != VX3KTargetPort) return false;
if (!other.getEmail_SMTPServer().equals(Email_SMTPServer)) return false;
if (other.getEmail_SMTPPort() != Email_SMTPPort) return false;
if (other.isEmail_SMTPSSL() != Email_SMTPSSL) return false;
if (!other.getEmail_SMTPUsername().equals(Email_SMTPUsername)) return false;
if (!other.getEmail_SMTPPassword().equals(Email_SMTPPassword)) return false;
if (!other.getEmail_SMTPFrom().equals(Email_SMTPFrom)) return false;
if (!other.getEmail_SenderName().equals(Email_SenderName)) return false;
if (!other.getEmail_Subject().equals(Email_Subject)) return false;
if (!other.getModbus_MasterIP().equals(Modbus_MasterIP)) return false;
if (other.getModbus_Port() != Modbus_Port) return false;
if (!other.getModbus_SlaveID().equals(Modbus_SlaveID)) return false;
if (!other.getWebListenPort().equals(WebListenPort)) return false;
return true;
}
/**
* Convert webSettingArgs to config.
* This method creates a config object from the provided webSettingArgs.
* @param args the webSettingArgs to convert
* @return a config object with values from the webSettingArgs
*/
@SuppressWarnings("unused")
public static @NonNull config From_webSettingArgs(@NonNull webSettingArgs args) {
config cfg = new config();
// MQTT
cfg.setMQTT_Broker(args.mqttBrokerIP);
cfg.setMQTT_ClientID(args.mqttClientID);
cfg.setMQTT_Port(args.mqttPort);
cfg.setMQTT_Topic(args.mqttTopic);
cfg.setMQTT_Username(args.mqttUsername);
cfg.setMQTT_Password(args.mqttPassword);
// VX3K
cfg.setVX3KTargetIP(args.vx3kIP);
cfg.setVX3KTargetPort(args.vx3kPort);
// Email
cfg.setEmail_SenderName(args.smtpSenderName);
cfg.setEmail_SMTPServer(args.smtpServer);
cfg.setEmail_SMTPPort(args.smtpPort);
cfg.setEmail_SMTPSSL(args.smtpSSL);
cfg.setEmail_SMTPUsername(args.smtpUsername);
cfg.setEmail_SMTPPassword(args.smtpPassword);
cfg.setEmail_SMTPFrom(args.smtpSenderAddress);
cfg.setEmail_Subject(args.smtpSubject);
// Modbus
cfg.setModbus_MasterIP("0.0.0.0");
cfg.setModbus_Port(502);
cfg.setModbus_SlaveID("1");
return cfg;
}
/**
* Convert config to webSettingArgs.
* This method creates a webSettingArgs object from the provided config.
* @param cfg the config to convert
* @return a webSettingArgs object with values from the config
*/
public static @NonNull webSettingArgs To_webSettingArgs(@NonNull config cfg) {
webSettingArgs args = new webSettingArgs();
args.mqttBrokerIP = cfg.getMQTT_Broker();
args.mqttPassword=cfg.getMQTT_Password();
args.mqttPort=cfg.getMQTT_Port();
args.mqttTopic=cfg.getMQTT_Topic();
args.mqttUsername=cfg.getMQTT_Username();
args.mqttClientID=cfg.getMQTT_ClientID();
args.vx3kIP=cfg.getVX3KTargetIP();
args.vx3kPort=cfg.getVX3KTargetPort();
args.smtpSenderName=cfg.getEmail_SenderName();
args.smtpServer=cfg.getEmail_SMTPServer();
args.smtpPort=cfg.getEmail_SMTPPort();
args.smtpSSL=cfg.isEmail_SMTPSSL();
args.smtpUsername=cfg.getEmail_SMTPUsername();
args.smtpPassword=cfg.getEmail_SMTPPassword();
args.smtpSenderAddress=cfg.getEmail_SMTPFrom();
args.smtpSubject=cfg.getEmail_Subject();
return args;
}
}

View File

@@ -1,19 +1,18 @@
package database;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
@ToString
public class ContactInputData {
private int ContactID;
private String Description;
private boolean EnableEmail;
private String EmailRecipient;
private boolean EnableMQTT;
private boolean EnableModbus;
private int ModbusRegister;
private boolean EnableVX3K;
private int VX3KFrameID;
private int VX3KContactID;
public int ContactID;
public String Description;
public boolean EnableEmail;
public String EmailRecipient;
public boolean EnableMQTT;
public boolean EnableModbus;
public int ModbusRegister;
public boolean EnableVX3K;
public int VX3KFrameID;
public int VX3KContactID;
}

View File

@@ -62,16 +62,16 @@ public class Database {
while (resultSet.next()) {
ContactInputData contactInputData = new ContactInputData();
contactInputData.setContactID(resultSet.getInt("ContactID"));
contactInputData.setDescription(resultSet.getString("Description"));
contactInputData.setEnableEmail(resultSet.getBoolean("EnableEmail"));
contactInputData.setEmailRecipient(resultSet.getString("EmailRecipient"));
contactInputData.setEnableMQTT(resultSet.getBoolean("EnableMQTT"));
contactInputData.setEnableModbus(resultSet.getBoolean("EnableModbus"));
contactInputData.setModbusRegister(resultSet.getInt("ModbusRegister"));
contactInputData.setEnableVX3K(resultSet.getBoolean("EnableVX3K"));
contactInputData.setVX3KFrameID(resultSet.getInt("VX3KFrameID"));
contactInputData.setVX3KContactID(resultSet.getInt("VX3KContactID"));
contactInputData.ContactID=resultSet.getInt("ContactID");
contactInputData.Description=resultSet.getString("Description");
contactInputData.EnableEmail=resultSet.getBoolean("EnableEmail");
contactInputData.EmailRecipient=resultSet.getString("EmailRecipient");
contactInputData.EnableMQTT=resultSet.getBoolean("EnableMQTT");
contactInputData.EnableModbus=resultSet.getBoolean("EnableModbus");
contactInputData.ModbusRegister=resultSet.getInt("ModbusRegister");
contactInputData.EnableVX3K=resultSet.getBoolean("EnableVX3K");
contactInputData.VX3KFrameID=resultSet.getInt("VX3KFrameID");
contactInputData.VX3KContactID=resultSet.getInt("VX3KContactID");
loadedData.add(contactInputData);
}
@@ -89,7 +89,6 @@ public class Database {
* Load ContactInputData into the contactInputDataList.
* @param loadedData List of ContactInputData objects loaded from the database.
*/
@SuppressWarnings("ExtractMethodRecommender")
private void LoadContactInputDataList(List<ContactInputData> loadedData){
contactInputDataList.clear();
// Maximum number of contact input data
@@ -97,7 +96,7 @@ public class Database {
for (int i = 1; i <= maxContactInputData; i++){
final int contactID = i;
ContactInputData cid = loadedData.stream()
.filter(x -> x.getContactID() == contactID)
.filter(x -> x.ContactID == contactID)
.findFirst()
.orElse(null);
if (cid != null){
@@ -105,16 +104,16 @@ public class Database {
} else {
// Create default ContactInputData if not exists
ContactInputData newContactInputData = new ContactInputData();
newContactInputData.setContactID(contactID);
newContactInputData.setDescription("Contact " + contactID);
newContactInputData.setEnableEmail(false);
newContactInputData.setEmailRecipient("");
newContactInputData.setEnableMQTT(false);
newContactInputData.setEnableModbus(false);
newContactInputData.setModbusRegister(0);
newContactInputData.setEnableVX3K(false);
newContactInputData.setVX3KFrameID(0);
newContactInputData.setVX3KContactID(0);
newContactInputData.ContactID=contactID;
newContactInputData.Description="Contact " + contactID;
newContactInputData.EnableEmail=false;
newContactInputData.EmailRecipient="";
newContactInputData.EnableMQTT=false;
newContactInputData.EnableModbus=false;
newContactInputData.ModbusRegister=0;
newContactInputData.EnableVX3K=false;
newContactInputData.VX3KFrameID=0;
newContactInputData.VX3KContactID=0;
contactInputDataList.add(newContactInputData);
Create_ContactInputData(newContactInputData);
@@ -133,15 +132,15 @@ public class Database {
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (Connection conn = DriverManager.getConnection(DB_NAME)) {
var pstmt = conn.prepareStatement(sql);
pstmt.setString(1, contactInputData.getDescription());
pstmt.setBoolean(2, contactInputData.isEnableEmail());
pstmt.setString(3, contactInputData.getEmailRecipient());
pstmt.setBoolean(4, contactInputData.isEnableMQTT());
pstmt.setBoolean(5, contactInputData.isEnableModbus());
pstmt.setInt(6, contactInputData.getModbusRegister());
pstmt.setBoolean(7, contactInputData.isEnableVX3K());
pstmt.setInt(8, contactInputData.getVX3KFrameID());
pstmt.setInt(9, contactInputData.getVX3KContactID());
pstmt.setString(1, contactInputData.Description);
pstmt.setBoolean(2, contactInputData.EnableEmail);
pstmt.setString(3, contactInputData.EmailRecipient);
pstmt.setBoolean(4, contactInputData.EnableMQTT);
pstmt.setBoolean(5, contactInputData.EnableModbus);
pstmt.setInt(6, contactInputData.ModbusRegister);
pstmt.setBoolean(7, contactInputData.EnableVX3K);
pstmt.setInt(8, contactInputData.VX3KFrameID);
pstmt.setInt(9, contactInputData.VX3KContactID);
int rowsAffected = pstmt.executeUpdate();
if (rowsAffected>0){
@@ -161,7 +160,7 @@ public class Database {
* @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);
return contactInputDataList.stream().filter(x -> x.ContactID == contactID).findFirst().orElse(null);
}
/**
@@ -173,7 +172,7 @@ public class Database {
public String GetContactInputDataDescription(int contactID, @NonNull String defaultname){
ContactInputData contactInputData = GetContactInputData(contactID);
if (contactInputData != null) {
return contactInputData.getDescription();
return contactInputData.Description;
}
return defaultname;
}
@@ -184,7 +183,7 @@ public class Database {
* @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);
return contactInputDataList.stream().filter(x -> x.Description.equals(description)).findFirst().orElse(null);
}
/**
@@ -239,16 +238,16 @@ public class Database {
+ "WHERE ContactID = ?";
try (Connection conn = DriverManager.getConnection(DB_NAME)) {
var pstmt = conn.prepareStatement(sql);
pstmt.setString(1, contactInputData.getDescription());
pstmt.setBoolean(2, contactInputData.isEnableEmail());
pstmt.setString(3, contactInputData.getEmailRecipient());
pstmt.setBoolean(4, contactInputData.isEnableMQTT());
pstmt.setBoolean(5, contactInputData.isEnableModbus());
pstmt.setInt(6, contactInputData.getModbusRegister());
pstmt.setBoolean(7, contactInputData.isEnableVX3K());
pstmt.setInt(8, contactInputData.getVX3KFrameID());
pstmt.setInt(9, contactInputData.getVX3KContactID());
pstmt.setInt(10, contactInputData.getContactID());
pstmt.setString(1, contactInputData.Description);
pstmt.setBoolean(2, contactInputData.EnableEmail);
pstmt.setString(3, contactInputData.EmailRecipient);
pstmt.setBoolean(4, contactInputData.EnableMQTT);
pstmt.setBoolean(5, contactInputData.EnableModbus);
pstmt.setInt(6, contactInputData.ModbusRegister);
pstmt.setBoolean(7, contactInputData.EnableVX3K);
pstmt.setInt(8, contactInputData.VX3KFrameID);
pstmt.setInt(9, contactInputData.VX3KContactID);
pstmt.setInt(10, contactInputData.ContactID);
int rowsAffected = pstmt.executeUpdate();
if (rowsAffected>0){
@@ -257,7 +256,7 @@ public class Database {
LoadContactInputDataList(GetContactInputData());
return true;
} else {
Logger.error("No Contact Input Data found with ID {}", contactInputData.getContactID());
Logger.error("No Contact Input Data found with ID {}", contactInputData.ContactID);
}
} catch (Exception e) {
Logger.error("Error updating Contact Input Data: {}", e.getMessage());

View File

@@ -4,6 +4,7 @@ import additional.config;
import database.ContactInputData;
import database.Database;
import gpio.NanopiGpio;
import gpio.PinStatus;
import mail.SMTPSender;
import modbus.ModbusTCPServer;
import mqtt.MqttClient;
@@ -12,13 +13,17 @@ import pa.VX3K;
import pa.VX3KPseudoContactInput;
import web.WebServer;
import java.util.HashMap;
import java.util.Map;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static config config;
public static Map<Integer,PinStatus> pinStatusMap = new HashMap<>();
private static MqttClient mqttClient;
private static NanopiGpio gpio;
private static Database db;
public static Database db;
private static VX3K vx3K;
private static SMTPSender mailsender;
private static ModbusTCPServer modbusServer;
@@ -76,10 +81,12 @@ public class Main {
}
}, pinStatus -> {
Logger.info("Gpio {}, Description {}, status updated to {}", pinStatus.getGpioNumber(), pinStatus.getDescription(), pinStatus.getStatus());
// tampung di Map, nanti untuk kirim status pin di websocket
pinStatusMap.put(pinStatus.getGpioNumber(), pinStatus);
ContactInputData cib = db.GetContactInputData(pinStatus.getDescription());
if (cib!=null){
if (cib.isEnableMQTT()){
if (cib.EnableMQTT){
// 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()),
@@ -91,11 +98,11 @@ public class Main {
}
});
}
if (cib.isEnableEmail()){
if (cib.EnableEmail){
// 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 -> {
mailsender.SendEmail(config.getEmail_SMTPFrom(), cib.EmailRecipient, subject, body, sent -> {
if (sent) {
Logger.info("Email notification sent successfully.");
} else {
@@ -103,9 +110,9 @@ public class Main {
}
});
}
if (cib.isEnableVX3K()){
if (cib.EnableVX3K){
// VX3K Broadcast here
VX3KPseudoContactInput cmd = new VX3KPseudoContactInput(cib.getVX3KFrameID(), cib.getVX3KContactID(), pinStatus.getStatus()==1);
VX3KPseudoContactInput cmd = new VX3KPseudoContactInput(cib.VX3KFrameID, cib.VX3KContactID, pinStatus.getStatus()==1);
vx3K.PseudoContactInput(cmd, result -> {
if (result.success()){
Logger.info("VX3K PseudoContactInput successfully executed.");
@@ -114,9 +121,9 @@ public class Main {
}
});
}
if (cib.isEnableModbus()){
if (cib.EnableModbus){
if (modbusServer!=null){
modbusServer.SetRegister(cib.getContactID(), pinStatus.getStatus());
modbusServer.SetRegister(cib.ContactID, pinStatus.getStatus());
}
}
}

View File

@@ -1,6 +1,7 @@
package web;
import additional.config;
import database.ContactInputData;
import io.javalin.Javalin;
import lombok.Getter;
import main.Main;
@@ -55,17 +56,41 @@ public class WebServer {
String cmd = req.request().trim().toUpperCase();
switch(cmd){
case "GET_SETTING" :
webSettingArgs args1 = new webSettingArgs();
args1.mqttBrokerIP = Main.config.getMQTT_Broker();
webSettingArgs args1 = additional.config.To_webSettingArgs(Main.config);
webResponse response = new webResponse("GET_SETTING", gson.toJson(args1));
ctx.send(response);
break;
case "RESET_DEFAULT":
Main.config.MakeDefaults();
webResponse resetResponse = new webResponse("RESET_DEFAULT", "Default settings restored.");
ctx.send(resetResponse);
// Send updated settings after reset
webSettingArgs args2 = additional.config.To_webSettingArgs(Main.config);
webResponse response2 = new webResponse("GET_SETTING", gson.toJson(args2));
ctx.send(response2);
break;
case "SET_SETTING":
webSettingArgs args2 = gson.fromJson(req.args(), webSettingArgs.class);
webSettingArgs args3 = gson.fromJson(req.args(), webSettingArgs.class);
config newConfig = additional.config.From_webSettingArgs(args3);
if (Main.config.IsEqual(newConfig)) {
Logger.info("No changes detected in settings, not updating.");
ctx.send(new webResponse("SET_SETTING", "No changes made."));
} else {
Main.config = newConfig;
Main.config.Save();
Logger.info("Settings updated successfully.");
ctx.send(new webResponse("SET_SETTING", "Settings updated successfully."));
}
break;
case "GET_CONTACT_SETUP":
// ambil dari database ContactInputData, kirim balik
ContactInputData[] contactInputs = Main.db.contactInputDataList.toArray(new ContactInputData[0]);
break;
case "GET_CONTACT_STATUS":
// ambil dari Nanopi Gpio, kirim balik
break;
}
}
@@ -83,7 +108,9 @@ public class WebServer {
});
ws.onError(ctx -> {
Logger.error("WebSocket error: {}", ctx.error().getMessage());
if (ctx.error()!=null && ValidString(ctx.error().getMessage())){
Logger.error("WebSocket error: {}", ctx.error().getMessage());
}
});
});
}

View File

@@ -0,0 +1,16 @@
package web;
import database.ContactInputData;
@SuppressWarnings("unused")
public class webContactSetupArgs {
public ContactInputData c1;
public ContactInputData c2;
public ContactInputData c3;
public ContactInputData c4;
public ContactInputData c5;
public ContactInputData c6;
public ContactInputData c7;
public ContactInputData c8;
}

View File

@@ -1,23 +1,22 @@
package web;
import lombok.Data;
@Data
@SuppressWarnings("unused")
public class webSettingArgs {
String smtpServer;
int smtpPort;
String smtpUsername;
String smtpPassword;
boolean smtpSSL;
String smtpSenderAddress;
String smtpSenderName;
String smtpSubject;
String vx3kIP;
int vx3kPort;
String mqttBrokerIP;
int mqttPort;
String mqttUsername;
String mqttPassword;
String mqttClientID;
String mqttTopic;
public String smtpServer;
public int smtpPort;
public String smtpUsername;
public String smtpPassword;
public boolean smtpSSL;
public String smtpSenderAddress;
public String smtpSenderName;
public String smtpSubject;
public String vx3kIP;
public int vx3kPort;
public String mqttBrokerIP;
public int mqttPort;
public String mqttUsername;
public String mqttPassword;
public String mqttClientID;
public String mqttTopic;
}