patches 20/11/2024

This commit is contained in:
2024-11-20 14:37:45 +07:00
parent 142c400273
commit 0c1679f899
14 changed files with 843 additions and 429 deletions

View File

@@ -1,54 +1,93 @@
import SBC.GpioInput;
import SBC.GpioOutput;
import SBC.NanopiDuo2;
import SIP.SIP_Request;
import SIP.SIP_Response;
import SIP.jSIPClient;
import SIP.javaSipEvents;
import Webpage.WebServer; import Webpage.WebServer;
import code.common; import code.common;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.io.File; import java.io.File;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import static code.common.currentDir; import static code.common.currentDir;
public class Main { public class Main {
private static jSIPClient client; private static jSIPClient client;
private static WebServer webserver; private static WebServer webserver;
private static GpioInput callButton;
private static GpioInput hangupButton;
private static GpioOutput pilotLight;
private static GpioOutput networkLight;
private static GpioOutput callLight;
private static Timer timer;
private static TimerTask callLightTask;
public static void main(String[] args) { public static void main(String[] args) {
common.ExtractProperties(currentDir,"config.properties", false); common.ExtractProperties(currentDir,"config.properties", false);
Properties config = common.LoadProperties(currentDir,"config.properties");
// Timer Section
timer = new Timer();
callLightTask = new TimerTask() {
@Override
public void run() {
if (callLight!=null && callLight.isInitialized()) callLight.BlinkON(100);
}
};
// SIP Section // SIP Section
client = new jSIPClient(); client = new jSIPClient(config);
client.SetJavaSipEvent(new javaSipEvents() { client.SetJavaSipEvent(new javaSipEvents() {
@Override @Override
public void Registering(jSIPClient.SIP_Request req) { public void Registering(SIP_Request req) {
Logger.info("Registering to SIP Server, Request: {}",req); Logger.info("Registering to SIP Server, Request: {}",req);
// selama registering, blink dengan interval 500ms
callLightTask.cancel();
timer.purge();
timer.scheduleAtFixedRate(callLightTask, 0, 500);
} }
@Override @Override
public void RegisterSuccesful(jSIPClient.SIP_Response resp) { public void RegisterSuccesful(SIP_Response resp) {
Logger.info("Registered to SIP Server, Response: {}",resp); Logger.info("Registered to SIP Server, Response: {}",resp);
// setelah register berhasil, blink dengan interval 3000ms
callLightTask.cancel();
timer.purge();
timer.scheduleAtFixedRate(callLightTask, 0, 3000);
} }
@Override @Override
public void RegisterFailed(jSIPClient.SIP_Response resp) { public void RegisterFailed(SIP_Response resp) {
Logger.info("Failed to register to SIP Server, Response: {}",resp); Logger.info("Failed to register to SIP Server, Response: {}",resp);
} }
@Override @Override
public void IncomingCall(jSIPClient.SIP_Request req, jSIPClient.SIP_Response resp) { public void IncomingCall(SIP_Request req, SIP_Response resp) {
Logger.info("Incoming Call, Request: {}, Response: {}",req,resp); Logger.info("Incoming Call, Request: {}, Response: {}",req,resp);
client.AcceptIncomingCall(req); client.AcceptIncomingCall(req);
} }
@Override @Override
public void RemoteHangUp(jSIPClient.SIP_Request req) { public void RemoteHangUp(SIP_Request req) {
Logger.info("Remote Hangup, Request: {}",req); Logger.info("Remote Hangup, Request: {}",req);
client.HangUp(); client.HangUp();
} }
@Override @Override
public void Ringing(jSIPClient.SIP_Response resp) { public void Ringing(SIP_Response resp) {
Logger.info("Ringing, Response: {}",resp); Logger.info("Ringing, Response: {}",resp);
} }
@Override @Override
public void CalleePickup(jSIPClient.SIP_Response resp) { public void CalleePickup(SIP_Response resp) {
Logger.info("Callee Pickup, Response: {}",resp); Logger.info("Callee Pickup, Response: {}",resp);
} }
}); });
@@ -56,13 +95,35 @@ public class Main {
// Web Server Section // Web Server Section
webserver = new WebServer(); webserver = new WebServer(config);
webserver.Start(); webserver.Start();
// GPIO Section
callButton = new GpioInput(NanopiDuo2.Pin12.gpionumber);
hangupButton = new GpioInput(NanopiDuo2.Pin14.gpionumber);
pilotLight = new GpioOutput(NanopiDuo2.Pin16.gpionumber, true);
if (pilotLight.isInitialized()){
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (pilotLight!=null && pilotLight.isInitialized()) pilotLight.BlinkON(100);
}
}, 0, 1000);
}
networkLight = new GpioOutput(NanopiDuo2.Pin18.gpionumber, true);
callLight = new GpioOutput(NanopiDuo2.Pin20.gpionumber, true);
// Shutdown Hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
Logger.info("Shutting down SIPIntercom"); Logger.info("Shutting down SIPIntercom");
if (client!=null) client.Disconnect(); if (client!=null) client.Disconnect();
if (webserver!=null) webserver.Stop(); if (webserver!=null) webserver.Stop();
if (callButton!=null && callButton.isInitialized()) callButton.Close();
if (hangupButton!=null && hangupButton.isInitialized()) hangupButton.Close();
if (pilotLight!=null && pilotLight.isInitialized()) pilotLight.Close();
if (networkLight!=null && networkLight.isInitialized()) networkLight.Close();
if (callLight!=null && callLight.isInitialized()) callLight.Close();
if (timer!=null) timer.cancel();
})); }));
} }

74
src/SBC/GpioInput.java Normal file
View File

@@ -0,0 +1,74 @@
package SBC;
import lombok.Getter;
import lombok.Setter;
import org.pmw.tinylog.Logger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
import static code.common.*;
@SuppressWarnings("unused")
@Getter
public class GpioInput {
private boolean initialized = false;
private int gpionumber = 0;
private String lastvalue = "";
private Path valuePath;
private Path directionPath;
@Setter private Consumer<String> onChange;
private void updateValue(String value){
if (onChange!=null){
if (ValidString(value)){
onChange.accept(value);
}
}
}
/**
* Create GpioInput object
* @param gpionumber GPIO number
*/
public GpioInput(int gpionumber){
if (gpionumber>0){
if (HaveGPIO()){
if (WriteFile(gpioExportPath,gpionumber)){
valuePath = gpioPath.resolve("gpio"+gpionumber).resolve("value");
directionPath = gpioPath.resolve("gpio"+gpionumber).resolve("direction");
if (Files.exists(valuePath) && Files.exists(directionPath)){
if (WriteFile(directionPath,"in")){
this.gpionumber = gpionumber;
initialized = true;
new Thread(()->{
while(initialized){
try{
Thread.sleep(10);
} catch (Exception ignored) {}
String value = ReadFile(valuePath);
if (Objects.equals(lastvalue, value)) continue;
lastvalue = value;
updateValue(value);
}
}).start();
Logger.info("GPIO Input created: {}",gpionumber);
} else Logger.info("Failed to set direction to in: {}",gpionumber);
} else Logger.info("Failed to export GPIO: {}",gpionumber);
} else Logger.info("Failed to write export GPIO: {}",gpionumber);
} else Logger.info("Dont have GPIO path");
} else Logger.info("Platform is not Linux");
}
/**
* Close Gpio Input
*/
public void Close(){
if (initialized){
initialized = false;
WriteFile(gpioUnexportPath,gpionumber);
}
}
}

97
src/SBC/GpioOutput.java Normal file
View File

@@ -0,0 +1,97 @@
package SBC;
import lombok.Getter;
import org.pmw.tinylog.Logger;
import java.nio.file.Files;
import java.nio.file.Path;
import static code.common.*;
@SuppressWarnings({"unused", "UnusedReturnValue"})
@Getter
public class GpioOutput {
private boolean initialized = false;
private int gpionumber = 0;
private Path valuePath;
private Path directionPath;
private boolean activeHigh = true;
/**
* Create GpioInput object
* Active High : ON = 1, OFF = 0
* Active Low : ON = 0, OFF = 1
* @param gpionumber GPIO number
* @param activeHigh true if active high, false if active low
*/
public GpioOutput(int gpionumber,boolean activeHigh){
if (gpionumber>0){
if (HaveGPIO()){
if (WriteFile(gpioExportPath,gpionumber)){
valuePath = gpioPath.resolve("gpio"+gpionumber).resolve("value");
directionPath = gpioPath.resolve("gpio"+gpionumber).resolve("direction");
if (Files.exists(valuePath) && Files.exists(directionPath)){
if (WriteFile(directionPath,"out")){
this.activeHigh = activeHigh;
this.gpionumber = gpionumber;
initialized = true;
Logger.info("GPIO Output created: {}",gpionumber);
} else Logger.info("Failed to set direction to in: {}",gpionumber);
} else Logger.info("Failed to export GPIO: {}",gpionumber);
} else Logger.info("Failed to write export GPIO: {}",gpionumber);
} else Logger.info("Dont have GPIO path");
} else Logger.info("Platform is not Linux");
}
/**
* Set GPIO Value
* @param isON true to set GPIO ON, false to set GPIO OFF
* @return true if success
*/
public boolean SetValue(boolean isON){
if (initialized){
return WriteFile(valuePath,activeHigh?isON?"1":"0":isON?"0":"1");
}
return false;
}
/**
* Set Blink ON for specific delay
* Blink ON = OFF -> ON -> OFF
* @param delay delay in milliseconds
*/
public void BlinkON(int delay){
SetValue(false);
SetValue(true);
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
}
SetValue(false);
}
/**
* Set Blink OFF for specific delay
* Blink OFF = ON -> OFF -> ON
* @param delay delay in milliseconds
*/
public void BlinkOFF(int delay) {
SetValue(true);
SetValue(false);
try {
Thread.sleep(delay);
} catch (InterruptedException ignored) {
}
SetValue(true);
}
/**
* Close Gpio Input
*/
public void Close(){
if (initialized){
SetValue(false);
initialized = false;
WriteFile(gpioUnexportPath,gpionumber);
}
}
}

24
src/SBC/NanopiDuo2.java Normal file
View File

@@ -0,0 +1,24 @@
package SBC;
public enum NanopiDuo2 {
Pin09(9,"IRRX",363),
Pin11(11,"PG11",203),
Pin02(2,"RX0",5),
Pin04(4,"TX0",4),
Pin08(8,"SCL",11),
Pin10(10,"SDA",12),
Pin12(12,"SPI_CS",13),
Pin14(14,"SPI_CLK",14),
Pin16(16,"SPI_MISO",16),
Pin18(18,"SPI_MOSI",15),
Pin20(20,"RX1",199),
Pin22(22,"TX1",198);
public final int pin;
public final String name;
public final int gpionumber;
NanopiDuo2(int pin, String name, int gpio) {
this.pin = pin;
this.name = name;
this.gpionumber = gpio;
}
}

View File

@@ -0,0 +1,42 @@
package SBC;
public enum RaspberryPi3B {
Pin03(3,"GPIO2/SDA", 2),
Pin05(5,"GPIO3/SCL", 3),
Pin07(7,"GPIO4/GPCLK0", 4),
Pin08(8,"GPIO14/TXD", 14),
Pin10(10,"GPIO15/RXD", 15),
Pin11(11,"GPIO17", 17),
Pin12(12,"GPIO18/PCMCLK", 18),
Pin13(13,"GPIO27", 27),
Pin15(15,"GPIO22", 22),
Pin16(16,"GPIO23", 23),
Pin18(18,"GPIO24", 24),
Pin19(19,"GPIO10/MOSI", 10),
Pin21(21,"GPIO9/MISO", 9),
Pin22(22,"GPIO25", 25),
Pin23(23,"GPIO11/SCLK", 11),
Pin24(24,"GPIO8/CE0", 8),
Pin26(26,"GPIO7/CE1", 7),
Pin27(27,"GPIO0/IDSD", 0),
Pin28(28,"GPIO1/IDSC", 1),
Pin29(29,"GPIO5", 5),
Pin31(31,"GPIO6", 6),
Pin32(32,"GPIO12/PWM0", 12),
Pin33(33,"GPIO13/PWM1", 13),
Pin35(35,"GPIO19/PCMFS", 19),
Pin36(36,"GPIO16", 16),
Pin37(37,"GPIO26", 26),
Pin38(38,"GPIO20/PCMDIN", 20),
Pin40(40,"GPIO21/PCMDOUT", 21);
public final int pin;
public final String name;
public final int gpionumber;
RaspberryPi3B(int pin, String name, int gpionumber){
this.pin = pin;
this.name = name;
this.gpionumber = gpionumber;
}
}

View File

@@ -0,0 +1,42 @@
package SBC;
public enum RaspberryPi5B {
Pin03(3,"GPIO2/SDA", 573),
Pin05(5,"GPIO3/SCL", 574),
Pin07(7,"GPIO4/GPCLK0", 575),
Pin08(8,"GPIO14/TXD", 585),
Pin10(10,"GPIO15/RXD", 586),
Pin11(11,"GPIO17", 588),
Pin12(12,"GPIO18/PCMCLK", 589),
Pin13(13,"GPIO27", 598),
Pin15(15,"GPIO22", 593),
Pin16(16,"GPIO23", 594),
Pin18(18,"GPIO24", 595),
Pin19(19,"GPIO10/MOSI", 581),
Pin21(21,"GPIO9/MISO", 580),
Pin22(22,"GPIO25", 596),
Pin23(23,"GPIO11/SCLK", 582),
Pin24(24,"GPIO8/CE0", 579),
Pin26(26,"GPIO7/CE1", 578),
Pin27(27,"GPIO0/IDSD", 587),
Pin28(28,"GPIO1/IDSC", 587),
Pin29(29,"GPIO5", 576),
Pin31(31,"GPIO6", 577),
Pin32(32,"GPIO12/PWM0", 583),
Pin33(33,"GPIO13/PWM1", 584),
Pin35(35,"GPIO19/PCMFS", 590),
Pin36(36,"GPIO16", 587),
Pin37(37,"GPIO26", 597),
Pin38(38,"GPIO20/PCMDIN", 591),
Pin40(40,"GPIO21/PCMDOUT", 592);
public final int pin;
public final String name;
public final int gpionumber;
RaspberryPi5B(int pin, String name, int gpionumber){
this.pin = pin;
this.name = name;
this.gpionumber = gpionumber;
}
}

291
src/SIP/CustomConfig.java Normal file
View File

@@ -0,0 +1,291 @@
package SIP;
import code.common;
import org.pmw.tinylog.Logger;
import peers.Config;
import peers.media.MediaMode;
import peers.sip.syntaxencoding.SipURI;
import java.net.InetAddress;
import java.net.UnknownHostException;
@SuppressWarnings("unused")
public class CustomConfig implements Config {
private InetAddress localIpAddress;
private InetAddress publicIpAddress;
private String registrar;
private String username;
private String password;
private int sip_port;
private int rtp_port;
private transient MediaMode mm; // tidak disave dan load
private SipURI outbondproxy;
private transient boolean mediadebug; // tidak disave dan load
private transient String mediafile; // tidak disave dan load
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
*/
public CustomConfig(String registrar, String username, String password) {
this.registrar = registrar;
this.password = password;
this.username = username;
setLocalInetAddress(null);
}
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
* @param localip local ethernet to use to register. if not valid, will use default LocalHost
*/
public CustomConfig(String registrar, String username, String password, String localip) {
this.registrar = registrar;
this.password = password;
this.username = username;
SetLocalInetAddress(localip);
}
public CustomConfig() {
this.registrar = "192.168.5.1";
this.username = "1002";
this.password = "1234";
setLocalInetAddress(null);
}
/**
* Get Local IP Address
*/
@Override
public InetAddress getLocalInetAddress() {
return localIpAddress;
}
/**
* Get public IP Address used
*/
@Override
public InetAddress getPublicInetAddress() {
return publicIpAddress;
}
/**
* Get Username to use for registering with SIP Server
*/
@Override
public String getUserPart() {
return username;
}
/**
* Get SIP Server (registrar)
*/
@Override
public String getDomain() {
return registrar;
}
/**
* Get Password
*/
@Override
public String getPassword() {
return password;
}
/**
* Get Outbond Proxy used
*/
@Override
public SipURI getOutboundProxy() {
return outbondproxy;
}
/**
* Get SIP Port . default is 5060
*/
@Override
public int getSipPort() {
return sip_port;
}
/**
* Get Current MediaMode
*/
@Override
public MediaMode getMediaMode() {
return mm;
}
/**
* Not used
*/
@Override
public boolean isMediaDebug() {
return mediadebug;
}
/**
* Get MediaFile used
*/
@Override
public String getMediaFile() {
return mediafile;
}
/**
* Get RTP Port used
*/
@Override
public int getRtpPort() {
return rtp_port;
}
/**
* Set Local Network Interface to use with SIP.jSIPClient
* useful when having multiple network interfaces in the machine
*/
@Override
public void setLocalInetAddress(InetAddress inetAddress) {
try {
this.localIpAddress = inetAddress == null ? InetAddress.getLocalHost() : inetAddress;
} catch (UnknownHostException e) {
Logger.error("setLocalInetAddress exception = " + e.getMessage());
}
}
/**
* Set Local Network Interface to use with SIP.jSIPClient
* useful when having multiple network interfaces in the machine
* @param ipaddress IP Address of the network interface to use in the machine
*/
public void SetLocalInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setLocalInetAddress(xx);
} catch (UnknownHostException e) {
Logger.error("SetLocalInetAddress exception = "+e.getMessage());
}
}
/**
* Set Public InetAddress to use with JSIPClient
* personal note : dont know if really necessary
*/
@Override
public void setPublicInetAddress(InetAddress inetAddress) {
publicIpAddress = inetAddress;
}
/**
* Set Public IP Address to use with SIP.jSIPClient
* Personal Note : dont know if really necessary
* @param ipaddress IP Address in string
*/
public void SetPublicInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setPublicInetAddress(xx);
} catch (UnknownHostException e) {
Logger.error("SetPublicInetAddress exception = "+e.getMessage());
}
}
/**
* Set Username to use for registering to SIP Server
*/
@Override
public void setUserPart(String username) {
this.username = username;
}
/**
* Set SIP Server (registrar) IP Address / Domain
*/
@Override
public void setDomain(String domain) {
registrar = domain;
}
/**
* Set Password to use for registering to SIP Server
*/
@Override
public void setPassword(String password) {
this.password = password;
}
/**
* Not used
*/
@Override
public void setOutboundProxy(SipURI outboundProxy) {
outbondproxy = outboundProxy;
}
/**
* Not used
*/
@Override
public void setSipPort(int sipPort) {
this.sip_port = common.ValidPortNumber(sipPort) ? sipPort : 5060;
}
/**
* Not used
*/
@Override
public void setMediaMode(MediaMode mediaMode) {
mm = mediaMode;
}
/**
* Not used
*/
@Override
public void setMediaDebug(boolean mediaDebug) {
mediadebug = mediaDebug;
}
/**
* Not used
*/
@Override
public void setMediaFile(String mediaFile) {
mediafile = mediaFile;
}
/**
* Not used
*/
@Override
public void setRtpPort(int rtpPort) {
rtp_port = common.ValidPortNumber(rtpPort) ? rtpPort : 49152 ;
}
/**
* Not used
*/
@Override
public void save() {}
}

37
src/SIP/SIP_Request.java Normal file
View File

@@ -0,0 +1,37 @@
package SIP;
import code.common;
import lombok.Getter;
import peers.sip.syntaxencoding.SipHeaders;
import peers.sip.transport.SipRequest;
import java.text.MessageFormat;
public class SIP_Request{
private @Getter
final SipRequest req;
public String To;
public String From;
public String CallID;
public String Contact;
public SIP_Request(SipRequest source) {
req = source;
if (req!=null) {
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head,"To", null);
this.From = common.GetSIPHeaderValue(head, "From", null);
this.CallID = common.GetSIPHeaderValue(head, "Call-ID", null);
this.Contact = common.GetSIPHeaderValue(head, "Contact", null);
}
}
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}", To, From, CallID, Contact);
}
}

48
src/SIP/SIP_Response.java Normal file
View File

@@ -0,0 +1,48 @@
package SIP;
import code.common;
import lombok.Getter;
import peers.sip.syntaxencoding.SipHeaders;
import peers.sip.transport.SipResponse;
import java.text.MessageFormat;
public class SIP_Response{
public SIP_Response(SipResponse source) {
resp = source;
if (resp!=null) {
this.statusCode = source.getStatusCode();
this.reasonPhrase = source.getReasonPhrase();
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head, "To", null);
this.From = common.GetSIPHeaderValue(head, "From", null);
this.CallID = common.GetSIPHeaderValue(head, "Call-ID", null);
this.Contact = common.GetSIPHeaderValue(head, "Contact", null);
this.Server = common.GetSIPHeaderValue(head, "Server", null);
this.Date = common.GetSIPHeaderValue(head, "Date", null);
}
}
private @Getter
final SipResponse resp;
public int statusCode;
public String reasonPhrase;
public String From;
public String To;
public String CallID;
public String Server;
public String Contact;
public String Date;
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}\n"
+ "Server:{4}\n"
+ "Date:{5}\n"
+ "StatusCode:{6}\n"
+ "ReasonPhrase:{7}", To, From, CallID, Contact, Server, Date, statusCode, reasonPhrase);
}
}

View File

@@ -1,10 +1,6 @@
import java.io.File; package SIP;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.MessageFormat;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -14,18 +10,14 @@ import Audio.BassFileReaderListener;
import Audio.BassSoundManager; import Audio.BassSoundManager;
import Audio.BassSoundManagerListener; import Audio.BassSoundManagerListener;
import code.common; import code.common;
import com.google.gson.JsonIOException;
import lombok.Getter; import lombok.Getter;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import peers.Config;
import peers.media.MediaManager; import peers.media.MediaManager;
import peers.media.MediaMode; import peers.media.MediaMode;
import peers.sip.Utils; import peers.sip.Utils;
import peers.sip.core.useragent.SipListener; import peers.sip.core.useragent.SipListener;
import peers.sip.core.useragent.UserAgent; import peers.sip.core.useragent.UserAgent;
import peers.sip.syntaxencoding.SipHeaders;
import peers.sip.syntaxencoding.SipURI;
import peers.sip.syntaxencoding.SipUriSyntaxException; import peers.sip.syntaxencoding.SipUriSyntaxException;
import peers.sip.transactionuser.Dialog; import peers.sip.transactionuser.Dialog;
import peers.sip.transactionuser.DialogManager; import peers.sip.transactionuser.DialogManager;
@@ -37,12 +29,10 @@ import static code.common.*;
@SuppressWarnings({"unused", "UnusedReturnValue"}) @SuppressWarnings({"unused", "UnusedReturnValue"})
public class jSIPClient { public class jSIPClient {
public jSIPClient() { public jSIPClient(Properties config) {
runningfolder = new File("").getAbsolutePath(); load_config(config);
load_config();
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
raise_log_event("jSIPClient ShutdownHook called"); raise_log_event("SIP.jSIPClient ShutdownHook called");
save_config();
HangUp(); HangUp();
Disconnect(); Disconnect();
})); }));
@@ -55,8 +45,7 @@ public class jSIPClient {
public CustomConfig cc = new CustomConfig(); public CustomConfig cc = new CustomConfig();
private EventManager em; private EventManager em;
private final String runningfolder;
private javaSipEvents jse; private javaSipEvents jse;
@@ -253,7 +242,7 @@ public class jSIPClient {
private boolean all_success; private boolean all_success;
//JavaxSoundManager jsm; //JavaxSoundManager jsm;
BassSoundManager jsm; BassSoundManager jsm;
public EventManager(final CustomConfig xx) { public EventManager(final CustomConfig xx) {
all_success = false; all_success = false;
//Logger lg = new FileLogger(null); //Logger lg = new FileLogger(null);
@@ -281,7 +270,7 @@ public class jSIPClient {
@Override @Override
public void log_error(String msg) { public void log_error(String msg) {
raise_log_event("BassSoundManager error : "+msg); raise_log_event("BassSoundManager error : "+msg);
} }
@Override @Override
@@ -318,15 +307,15 @@ public class jSIPClient {
@Override @Override
public void ChannelLevel(boolean is_input, int value) { public void ChannelLevel(boolean is_input, int value) {
if (is_input) if (is_input)
raise_inputchannellevel_event(value); raise_inputchannellevel_event(value);
else else
raise_outputchannellevel_event(value); raise_outputchannellevel_event(value);
} }
}); });
try { try {
user_agent = new UserAgent(this, xx, jsm); user_agent = new UserAgent(this, xx, jsm);
exec.submit(() -> { exec.submit(() -> {
@@ -337,33 +326,33 @@ public class jSIPClient {
raise_log_event("EventManager register exception = "+e.getMessage()); raise_log_event("EventManager register exception = "+e.getMessage());
} }
}); });
} catch (SocketException e) { } catch (SocketException e) {
raise_log_event("EventManager create exception = "+e.getMessage()); raise_log_event("EventManager create exception = "+e.getMessage());
} }
} }
public void setInputVolume(int value) { public void setInputVolume(int value) {
if (jsm!=null) jsm.setInputChannelVolume(value); if (jsm!=null) jsm.setInputChannelVolume(value);
} }
public int getInputVolume() { public int getInputVolume() {
if (jsm!=null) { if (jsm!=null) {
return jsm.getInputChannelVolume(); return jsm.getInputChannelVolume();
} else return 0; } else return 0;
} }
public void setOutputVolume(int value) { public void setOutputVolume(int value) {
if (jsm!=null) jsm.setOutputChannelVolume(value); if (jsm!=null) jsm.setOutputChannelVolume(value);
} }
public int getOutputVolume() { public int getOutputVolume() {
if (jsm!=null) { if (jsm!=null) {
return jsm.getOutputChannelVolume(); return jsm.getOutputChannelVolume();
} else return 0; } else return 0;
} }
/** /**
* Check if EventManager succesfully created * Check if EventManager succesfully created
* @return true if success * @return true if success
@@ -371,9 +360,9 @@ public class jSIPClient {
public boolean IsCreated() { public boolean IsCreated() {
return all_success; return all_success;
} }
/** /**
* Call * Call
* @param targetsip Target SIP * @param targetsip Target SIP
*/ */
public void Call(final String targetsip) { public void Call(final String targetsip) {
@@ -386,10 +375,10 @@ public class jSIPClient {
raise_log_event("Call exception = "+e.getMessage()); raise_log_event("Call exception = "+e.getMessage());
} }
}); });
} }
} }
/** /**
* Accept Incoming Call * Accept Incoming Call
* @param req SipRequest to accept * @param req SipRequest to accept
@@ -404,11 +393,11 @@ public class jSIPClient {
Dialog dialog = dialogManager.getDialog(callId); Dialog dialog = dialogManager.getDialog(callId);
user_agent.acceptCall(req, dialog); user_agent.acceptCall(req, dialog);
}); });
} }
} }
} }
/** /**
* Add Listener for File Streaming * Add Listener for File Streaming
* @param event BassFileReaderListener * @param event BassFileReaderListener
@@ -427,20 +416,20 @@ public class jSIPClient {
} }
return false; return false;
} }
public void DTMF(final char code) { public void DTMF(final char code) {
if (user_agent!=null) { if (user_agent!=null) {
exec.submit(() -> { exec.submit(() -> {
MediaManager mm = user_agent.getMediaManager(); MediaManager mm = user_agent.getMediaManager();
mm.sendDtmf(code); mm.sendDtmf(code);
}); });
} }
} }
/** /**
* Reject Incoming Call * Reject Incoming Call
* @param req SipRequest to reject * @param req SipRequest to reject
@@ -449,11 +438,11 @@ public class jSIPClient {
if (user_agent!=null) { if (user_agent!=null) {
if (req!=null) { if (req!=null) {
exec.submit(() -> user_agent.rejectCall(req)); exec.submit(() -> user_agent.rejectCall(req));
} }
} }
} }
/** /**
* Check if Calling in Progress * Check if Calling in Progress
* @return true if in progress * @return true if in progress
@@ -461,7 +450,7 @@ public class jSIPClient {
public boolean CallingInProgress() { public boolean CallingInProgress() {
return sip_request!=null; return sip_request!=null;
} }
/** /**
* Hang-Up current call * Hang-Up current call
*/ */
@@ -472,11 +461,11 @@ public class jSIPClient {
user_agent.terminate(sip_request); user_agent.terminate(sip_request);
sip_request = null; sip_request = null;
}); });
} else raise_log_event("HangUp failed, user_agent not available"); } else raise_log_event("HangUp failed, user_agent not available");
} else raise_log_event("HangUp failed, sip_request not available"); } else raise_log_event("HangUp failed, sip_request not available");
} }
/** /**
* Close Connection to SIP Server * Close Connection to SIP Server
*/ */
@@ -485,7 +474,7 @@ public class jSIPClient {
user_agent.close(); user_agent.close();
} }
} }
@Override @Override
public void registering(SipRequest sipRequest) { public void registering(SipRequest sipRequest) {
SIP_Request req = new SIP_Request(sipRequest); SIP_Request req = new SIP_Request(sipRequest);
@@ -532,357 +521,16 @@ public class jSIPClient {
@Override @Override
public void error(SipResponse sipResponse) { public void error(SipResponse sipResponse) {
raise_log_event("sip error, response="+common.gson.toJson(sipResponse)); raise_log_event("sip error, response="+common.gson.toJson(sipResponse));
} }
} }
public static class SIP_Request{
private @Getter final SipRequest req;
public String To;
public String From;
public String CallID;
public String Contact;
public SIP_Request(SipRequest source) {
req = source;
if (req!=null) {
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head,"To", null);
this.From = common.GetSIPHeaderValue(head, "From", null);
this.CallID = common.GetSIPHeaderValue(head, "Call-ID", null);
this.Contact = common.GetSIPHeaderValue(head, "Contact", null);
}
}
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}", To, From, CallID, Contact);
}
}
public static class SIP_Response{
public SIP_Response(SipResponse source) {
resp = source;
if (resp!=null) {
this.statusCode = source.getStatusCode();
this.reasonPhrase = source.getReasonPhrase();
SipHeaders head = source.getSipHeaders();
this.To = common.GetSIPHeaderValue(head, "To", null);
this.From = common.GetSIPHeaderValue(head, "From", null);
this.CallID = common.GetSIPHeaderValue(head, "Call-ID", null);
this.Contact = common.GetSIPHeaderValue(head, "Contact", null);
this.Server = common.GetSIPHeaderValue(head, "Server", null);
this.Date = common.GetSIPHeaderValue(head, "Date", null);
}
}
private @Getter final SipResponse resp;
public int statusCode;
public String reasonPhrase;
public String From;
public String To;
public String CallID;
public String Server;
public String Contact;
public String Date;
@Override
public String toString() {
return MessageFormat.format("To:{0}\n"
+ "From:{1}\n"
+ "Call-ID:{2}\n"
+ "Contact:{3}\n"
+ "Server:{4}\n"
+ "Date:{5}\n"
+ "StatusCode:{6}\n"
+ "ReasonPhrase:{7}", To, From, CallID, Contact, Server, Date, statusCode, reasonPhrase);
}
}
public class CustomConfig implements Config{
private InetAddress localIpAddress;
private InetAddress publicIpAddress;
private String registrar;
private String username;
private String password;
private int sip_port;
private int rtp_port;
private transient MediaMode mm; // tidak disave dan load
private SipURI outbondproxy;
private transient boolean mediadebug; // tidak disave dan load
private transient String mediafile; // tidak disave dan load
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
*/
public CustomConfig(String registrar, String username, String password) {
this.registrar = registrar;
this.password = password;
this.username = username;
setLocalInetAddress(null);
}
/**
* Create CustomConfig
* @param registrar Server IP
* @param username username
* @param password password
* @param localip local ethernet to use to register. if not valid, will use default LocalHost
*/
public CustomConfig(String registrar, String username, String password, String localip) {
this.registrar = registrar;
this.password = password;
this.username = username;
SetLocalInetAddress(localip);
}
public CustomConfig() {
this.registrar = "192.168.5.1";
this.username = "1002";
this.password = "1234";
setLocalInetAddress(null);
}
/**
* Get Local IP Address
*/
@Override
public InetAddress getLocalInetAddress() {
return localIpAddress;
}
/**
* Get public IP Address used
*/
@Override
public InetAddress getPublicInetAddress() {
return publicIpAddress;
}
/**
* Get Username to use for registering with SIP Server
*/
@Override
public String getUserPart() {
return username;
}
/**
* Get SIP Server (registrar)
*/
@Override
public String getDomain() {
return registrar;
}
/**
* Get Password
*/
@Override
public String getPassword() {
return password;
}
/**
* Get Outbond Proxy used
*/
@Override
public SipURI getOutboundProxy() {
return outbondproxy;
}
/**
* Get SIP Port . default is 5060
*/
@Override
public int getSipPort() {
return sip_port;
}
/**
* Get Current MediaMode
*/
@Override
public MediaMode getMediaMode() {
return mm;
}
/**
* Not used
*/
@Override
public boolean isMediaDebug() {
return mediadebug;
}
/**
* Get MediaFile used
*/
@Override
public String getMediaFile() {
return mediafile;
}
/**
* Get RTP Port used
*/
@Override
public int getRtpPort() {
return rtp_port;
}
/**
* Set Local Network Interface to use with jSIPClient
* useful when having multiple network interfaces in the machine
*/
@Override
public void setLocalInetAddress(InetAddress inetAddress) {
try {
this.localIpAddress = inetAddress == null ? InetAddress.getLocalHost() : inetAddress;
} catch (UnknownHostException e) {
raise_log_event("setLocalInetAddress exception = "+e.getMessage());
}
}
/**
* Set Local Network Interface to use with jSIPClient
* useful when having multiple network interfaces in the machine
* @param ipaddress IP Address of the network interface to use in the machine
*/
public void SetLocalInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setLocalInetAddress(xx);
} catch (UnknownHostException e) {
raise_log_event("SetLocalInetAddress exception = "+e.getMessage());
}
}
/**
* Set Public InetAddress to use with JSIPClient
* personal note : dont know if really necessary
*/
@Override
public void setPublicInetAddress(InetAddress inetAddress) {
publicIpAddress = inetAddress;
}
/**
* Set Public IP Address to use with jSIPClient
* Personal Note : dont know if really necessary
* @param ipaddress IP Address in string
*/
public void SetPublicInetAddress(String ipaddress) {
try {
InetAddress xx = InetAddress.getByName(ipaddress);
setPublicInetAddress(xx);
} catch (UnknownHostException e) {
raise_log_event("SetPublicInetAddress exception = "+e.getMessage());
}
}
/**
* Set Username to use for registering to SIP Server
*/
@Override
public void setUserPart(String username) {
this.username = username;
}
/**
* Set SIP Server (registrar) IP Address / Domain
*/
@Override
public void setDomain(String domain) {
registrar = domain;
}
/**
* Set Password to use for registering to SIP Server
*/
@Override
public void setPassword(String password) {
this.password = password;
}
/**
* Not used
*/
@Override
public void setOutboundProxy(SipURI outboundProxy) {
outbondproxy = outboundProxy;
}
/**
* Not used
*/
@Override
public void setSipPort(int sipPort) {
this.sip_port = common.ValidPortNumber(sipPort) ? sipPort : 5060;
}
/**
* Not used
*/
@Override
public void setMediaMode(MediaMode mediaMode) {
mm = mediaMode;
}
/**
* Not used
*/
@Override
public void setMediaDebug(boolean mediaDebug) {
mediadebug = mediaDebug;
}
/**
* Not used
*/
@Override
public void setMediaFile(String mediaFile) {
mediafile = mediaFile;
}
/**
* Not used
*/
@Override
public void setRtpPort(int rtpPort) {
rtp_port = common.ValidPortNumber(rtpPort) ? rtpPort : 49152 ;
}
/**
* Not used
*/
@Override
public void save() {}
}
//////////// private functions /////////////// //////////// private functions ///////////////
@@ -962,22 +610,9 @@ public class jSIPClient {
//if (need_outputchannellevel_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_outputchannellevel", false, new Object[] {value}); //if (need_outputchannellevel_event) ba.raiseEventFromDifferentThread(Me, null, 0, event+"_outputchannellevel", false, new Object[] {value});
} }
/**
* Dipanggil saat ShutdownHook
*/
private void save_config() {
if (cc!=null) {
try {
common.gson.toJson(cc, new FileWriter(new File(runningfolder,"Config.json")));
raise_log_event("Config.json saved");
} catch (JsonIOException | IOException e) {
raise_log_event("save_config failed, exception = "+e.getMessage());
}
}
}
private void load_config(){
Properties prop = LoadProperties(currentDir,"config.properties"); private void load_config(Properties prop) {
serverAddress = GetProperties_StringValue(prop,"SipServer","100.64.0.3"); serverAddress = GetProperties_StringValue(prop,"SipServer","100.64.0.3");
Username = GetProperties_StringValue(prop,"SipUsername","user1"); Username = GetProperties_StringValue(prop,"SipUsername","user1");
Password = GetProperties_StringValue(prop,"SipPassword","12345678"); Password = GetProperties_StringValue(prop,"SipPassword","12345678");

View File

@@ -0,0 +1,11 @@
package SIP;
public interface javaSipEvents {
void Registering(SIP_Request req);
void RegisterSuccesful(SIP_Response resp);
void RegisterFailed(SIP_Response resp);
void IncomingCall(SIP_Request req, SIP_Response resp);
void RemoteHangUp(SIP_Request req);
void Ringing(SIP_Response resp);
void CalleePickup(SIP_Response resp);
}

View File

@@ -1,6 +1,5 @@
package Webpage; package Webpage;
import code.common;
import io.javalin.Javalin; import io.javalin.Javalin;
import io.javalin.http.staticfiles.Location; import io.javalin.http.staticfiles.Location;
@@ -14,8 +13,7 @@ public class WebServer {
private final int listenport; private final int listenport;
private final String webusername; private final String webusername;
private final String webpassword; private final String webpassword;
public WebServer() { public WebServer(Properties prop) {
Properties prop = common.LoadProperties(currentDir,"config.properties");
listenport = GetProperties_IntValue(prop,"WebListenPort", 8080); listenport = GetProperties_IntValue(prop,"WebListenPort", 8080);
webusername = GetProperties_StringValue(prop,"WebUsername", "admin"); webusername = GetProperties_StringValue(prop,"WebUsername", "admin");
webpassword = GetProperties_StringValue(prop,"WebPassword", "admin"); webpassword = GetProperties_StringValue(prop,"WebPassword", "admin");

View File

@@ -2,6 +2,8 @@ package code;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.Platform;
import org.jetbrains.annotations.NotNull;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import peers.sip.syntaxencoding.SipHeaderFieldName; import peers.sip.syntaxencoding.SipHeaderFieldName;
import peers.sip.syntaxencoding.SipHeaderFieldValue; import peers.sip.syntaxencoding.SipHeaderFieldValue;
@@ -10,11 +12,17 @@ import peers.sip.syntaxencoding.SipHeaders;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties; import java.util.Properties;
public class common { public class common {
public static String currentDir = System.getProperty("user.dir"); public static String currentDir = System.getProperty("user.dir");
public static Gson gson = new Gson(); public static Gson gson = new Gson();
public static final Path gpioPath = Paths.get("/sys/class/gpio") ;
public static final Path gpioExportPath = Paths.get("/sys/class/gpio/export");
public static final Path gpioUnexportPath = Paths.get("/sys/class/gpio/unexport");
public static String GetProperties_StringValue(Properties prop, String key, String defaultavalue){ public static String GetProperties_StringValue(Properties prop, String key, String defaultavalue){
if (prop!=null){ if (prop!=null){
@@ -140,4 +148,60 @@ public class common {
} }
return defaultvalue; return defaultvalue;
} }
/**
* Check if GPIO is available
* @return true if GPIO is available
*/
public static boolean HaveGPIO(){
if (Platform.isLinux()){
if (Files.exists(gpioPath)){
if (Files.exists(gpioExportPath)) {
return Files.exists(gpioUnexportPath);
}
}
}
return false;
}
/**
* Write value to file
* @param path file path
* @param value value to write
* @return true if write success
*/
public static boolean WriteFile(Path path, String value){
try {
Files.write(path, value.getBytes());
return true;
} catch (Exception e) {
Logger.error("Failed to write file: {}",path);
return false;
}
}
/**
* Write integer value to file
* @param path file path
* @param value integer value to write
* @return true if write success
*/
public static boolean WriteFile(Path path, int value){
return WriteFile(path, String.valueOf(value));
}
/**
* Read file content
* @param path file path
* @return file content, or empty string if failed to read
*/
public static @NotNull String ReadFile(Path path){
try {
byte[] data = Files.readAllBytes(path);
return new String(data);
} catch (Exception e) {
Logger.error("Failed to read file: {}",path);
}
return "";
}
} }

View File

@@ -1,10 +0,0 @@
public interface javaSipEvents {
void Registering(jSIPClient.SIP_Request req);
void RegisterSuccesful(jSIPClient.SIP_Response resp);
void RegisterFailed(jSIPClient.SIP_Response resp);
void IncomingCall(jSIPClient.SIP_Request req, jSIPClient.SIP_Response resp);
void RemoteHangUp(jSIPClient.SIP_Request req);
void Ringing(jSIPClient.SIP_Response resp);
void CalleePickup(jSIPClient.SIP_Response resp);
}