diff --git a/.idea/artifacts/SIPIntercom_jar.xml b/.idea/artifacts/SIPIntercom_jar.xml new file mode 100644 index 0000000..15d61e4 --- /dev/null +++ b/.idea/artifacts/SIPIntercom_jar.xml @@ -0,0 +1,52 @@ + + + $PROJECT_DIR$/out/artifacts/SIPIntercom_jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..d516610 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/corundumstudio_socketio_netty.xml b/.idea/libraries/corundumstudio_socketio_netty.xml new file mode 100644 index 0000000..08cf220 --- /dev/null +++ b/.idea/libraries/corundumstudio_socketio_netty.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 0000000..e98c3ed --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/Properties/config.properties b/Properties/config.properties index e581083..f008b5a 100644 --- a/Properties/config.properties +++ b/Properties/config.properties @@ -1,6 +1,7 @@ WebUsername=admin WebPassword=admin WebListenPort = 8080 -SipServer=100.64.0.3 -SipUsername=100 -SipPassword=12345678 \ No newline at end of file +SipServer=rdkartono.ddns.me +SipPort=5060 +SipUsername=101 +SipPassword=password101 \ No newline at end of file diff --git a/SIPIntercom.iml b/SIPIntercom.iml index 7208ba6..44e6f58 100644 --- a/SIPIntercom.iml +++ b/SIPIntercom.iml @@ -15,5 +15,6 @@ + \ No newline at end of file diff --git a/libs/META-INF/MANIFEST.MF b/libs/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5ee19cb --- /dev/null +++ b/libs/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: Main + diff --git a/src/Main.java b/src/Main.java index af140a8..afaf54c 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,25 +1,23 @@ -import SBC.GpioInput; -import SBC.GpioOutput; -import SBC.NanopiDuo2; +import SBC.*; import SIP.SIP_Request; import SIP.SIP_Response; import SIP.jSIPClient; import SIP.javaSipEvents; -import Webpage.WebServer; +import Webpage.*; import code.common; +import com.google.gson.JsonSyntaxException; import org.pmw.tinylog.Logger; import java.io.File; import java.text.MessageFormat; -import java.util.Properties; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; -import static code.common.currentDir; +import static code.common.*; public class Main { private static jSIPClient client; private static WebServer webserver; + private static SocketioServer socketioserver; private static GpioInput callButton; private static GpioInput hangupButton; private static GpioOutput pilotLight; @@ -27,12 +25,21 @@ public class Main { private static GpioOutput callLight; private static GpioOutput Buzzer; private static Timer timer; + private static Timer system_monitoring_timer; private static TimerTask callLightTask; private static TimerTask BuzzerTask; private static SIP_Request incomingRequest; private static SIP_Request oncallRequest; private static SIP_Response incomingResponse; private static SIP_Response oncallResponse; + private static String SipStatus = "Idle"; + private static int cpuTemperature; + private static RamInformation ramInformation; + private static ProcessorStatus[] previousCpuInfo; + private static final Map cpuUsage = new HashMap<>(); + private static NetworkTransmitReceiveInfo[] previousNetworkInfo; + private static final Map networkTX = new HashMap<>(); + private static final Map networkRX = new HashMap<>(); public static void main(String[] args) { common.ExtractProperties(currentDir,"config.properties", false); @@ -40,18 +47,6 @@ public class Main { // Timer Section timer = new Timer(); - callLightTask = new TimerTask() { - @Override - public void run() { - if (callLight!=null && callLight.isInitialized()) callLight.BlinkON(100); - } - }; - BuzzerTask = new TimerTask() { - @Override - public void run() { - if (Buzzer!=null && Buzzer.isInitialized()) Buzzer.BlinkON(500); - } - }; // SIP Section client = new jSIPClient(config); @@ -61,6 +56,7 @@ public class Main { Logger.info("Registering to SIP Server, Request: {}",req); Buzzer_Off(); callLight_Registering(); + SipStatus = "Registering"; } @Override @@ -68,12 +64,16 @@ public class Main { Logger.info("Registered to SIP Server, Response: {}",resp); Buzzer_Off(); callLight_Idle(); + Logger.info("Calling callLight idle from RegisterSuccesful"); + SipStatus = "Idle"; + CallTest("100"); } @Override public void RegisterFailed(SIP_Response resp) { Logger.info("Failed to register to SIP Server, Response: {}",resp); Buzzer_Off(); + SipStatus = "Register Failed"; } @Override @@ -85,6 +85,7 @@ public class Main { incomingResponse = resp; oncallRequest = null; oncallResponse = null; + SipStatus = "Incoming Call from "+req.CallID; //client.AcceptIncomingCall(req); } @@ -92,9 +93,11 @@ public class Main { public void RemoteHangUp(SIP_Request req) { Logger.info("Remote Hangup, Request: {}",req); callLight_Idle(); + Logger.info("Calling callLight idle from RemoteHangUp"); Buzzer_Off(); client.HangUp(); + SipStatus = "Remote Hangup from "+req.CallID; incomingRequest = null; incomingResponse = null; oncallRequest = null; @@ -105,79 +108,144 @@ public class Main { @Override public void Ringing(SIP_Response resp) { Logger.info("Ringing, Response: {}",resp); + SipStatus = "Incoming Call from "+resp.CallID; } @Override public void CalleePickup(SIP_Response resp) { Logger.info("Callee Pickup, Response: {}",resp); + SipStatus = "Communication with "+resp.CallID; } }); - ReconnectSIP(); + client.Connect(); // Web Server Section webserver = new WebServer(config); webserver.Start(); + socketioserver = new SocketioServer("0.0.0.0", 9092); + socketioserver.Start(); + socketioserver.setOnRequest(req ->{ + // Ada request dari web + SocketioResponse resp; + if (networkLight!=null && networkLight.isInitialized()) networkLight.BlinkON(100); + + switch(req.getRequest()){ + case "setLogin": + try{ + LoginSetting login = gson.fromJson(req.getData(), LoginSetting.class); + if (ValidString(login.Username) && ValidString(login.Password)){ + config.setProperty("WebUsername", login.Username); + config.setProperty("WebPassword", login.Password); + if (SaveProperties(currentDir,"config.properties",config)){ + resp = new SocketioResponse("success", "Login Setting"); + } else throw new Exception("Failed to save properties"); + } else throw new Exception("Invalid Username or Password"); + } catch (JsonSyntaxException e){ + resp = new SocketioResponse("error", "Invalid JSON"); + } catch (Exception e){ + resp = new SocketioResponse("error", e.getMessage()); + } + break; + case "getLogin": + resp = SocketioResponse.fromLoginSetting("success", new LoginSetting(config.getProperty("WebUsername"), config.getProperty("WebPassword"))); + break; + case "setSipSetting": + try{ + SipSetting sip = gson.fromJson(req.getData(), SipSetting.class); + if (ValidString(sip.Server) && ValidString(sip.Username) && ValidString(sip.Password)){ + config.setProperty("SipServer", sip.Server); + config.setProperty("SipPort", String.valueOf(sip.Port)); + config.setProperty("SipUsername", sip.Username); + config.setProperty("SipPassword", sip.Password); + if (SaveProperties(currentDir,"config.properties",config)){ + resp = new SocketioResponse("success", "SIP Setting"); + } else throw new Exception("Failed to save properties"); + } else throw new Exception("Invalid SIP Setting"); + } catch (JsonSyntaxException e){ + resp = new SocketioResponse("error", "Invalid JSON"); + } catch (Exception e){ + resp = new SocketioResponse("error", e.getMessage()); + } + break; + case "getSipSetting": + resp = SocketioResponse.fromSipSetting("success", new SipSetting(config.getProperty("SipServer"), Integer.parseInt(config.getProperty("SipPort")), config.getProperty("SipUsername"), config.getProperty("SipPassword"))); + break; + case "getSipStatus": + resp = new SocketioResponse("success", SipStatus); + break; + case "hangup": + if (incomingRequest!=null){ + resp = new SocketioResponse("success", "Reject Incoming Call from "+incomingRequest.CallID); + hangupCall(); + } else if (oncallRequest!=null){ + resp = new SocketioResponse("success", "Hangup Call to "+oncallRequest.CallID); + hangupCall(); + } else { + resp = new SocketioResponse("error", "No Call to Hangup"); + } + break; + case "getRamInfo": + if (ramInformation!=null){ + resp = SocketioResponse.fromRamInformation("success", ramInformation); + } else { + resp = new SocketioResponse("error", "Failed to get RAM Information"); + } + break; + case "getCpuInfo": + if (cpuTemperature>0 && !cpuUsage.isEmpty()){ + resp = SocketioResponse.fromCpuStatus("success", cpuTemperature, cpuUsage); + } else { + resp = new SocketioResponse("error", "Failed to get CPU Information"); + } + break; + case "getNetworkInfo": + if (!networkTX.isEmpty() && !networkRX.isEmpty()){ + resp = SocketioResponse.fromTxRxMap("success", networkTX, networkRX); + } else { + resp = new SocketioResponse("error", "Failed to get Network Information"); + } + break; + case "call": + case "getDiskInfo": + resp = new SocketioResponse("error", "Not Implemented"); + break; + default: + resp = new SocketioResponse("error", "Invalid Request"); + break; + } + return resp; + }); // GPIO Section + // talk button = pin12 + // hangup button = pin14 + // Call light = pin 22 + // Network light = pin 20 callButton = new GpioInput(NanopiDuo2.Pin12.gpionumber, true); if (callButton.isInitialized()){ callButton.setOnLongPress(vv->{ Logger.info("Call Button Long Pressed"); - if (incomingRequest!=null && incomingResponse!=null){ - client.AcceptIncomingCall(incomingRequest); - callLight_OnCall(); - Buzzer_OnCall(); - oncallRequest = incomingRequest; - oncallResponse = incomingResponse; - incomingRequest = null; - incomingResponse = null; - } + pickupCall(); }); callButton.setOnShortPress(vv->{ Logger.info("Call Button Short Pressed"); - if (incomingRequest!=null && incomingResponse!=null){ - client.AcceptIncomingCall(incomingRequest); - callLight_OnCall(); - Buzzer_OnCall(); - oncallRequest = incomingRequest; - oncallResponse = incomingResponse; - incomingRequest = null; - incomingResponse = null; - } + pickupCall(); }); } hangupButton = new GpioInput(NanopiDuo2.Pin14.gpionumber, true); if (hangupButton.isInitialized()){ hangupButton.setOnShortPress(vv->{ Logger.info("Hangup Button Short Pressed"); - if (oncallRequest!=null || oncallResponse!=null){ - client.HangUp(); - oncallResponse = null; - oncallRequest = null; - } else if (incomingRequest!=null || incomingResponse!=null){ - client.RejectIncomingCall(incomingRequest); - incomingRequest = null; - incomingResponse = null; - } - callLight_Idle(); - Buzzer_Off(); + hangupCall(); }); hangupButton.setOnLongPress(vv->{ Logger.info("Hangup Button Long Pressed"); - if (oncallRequest!=null || oncallResponse!=null){ - client.HangUp(); - oncallResponse = null; - oncallRequest = null; - } else if (incomingRequest!=null || incomingResponse!=null){ - client.RejectIncomingCall(incomingRequest); - incomingRequest = null; - incomingResponse = null; - } - callLight_Idle(); - Buzzer_Off(); + hangupCall(); }); } + + // belum ada pinout nya di PCB demo (04/12/2024) pilotLight = new GpioOutput(NanopiDuo2.Pin16.gpionumber, true); if (pilotLight.isInitialized()){ timer.scheduleAtFixedRate(new TimerTask() { @@ -187,27 +255,72 @@ public class Main { } }, 0, 1000); } - networkLight = new GpioOutput(NanopiDuo2.Pin18.gpionumber, true); - callLight = new GpioOutput(NanopiDuo2.Pin20.gpionumber, true); - Buzzer = new GpioOutput(NanopiDuo2.Pin22.gpionumber, true); + + networkLight = new GpioOutput(NanopiDuo2.Pin20.gpionumber, true); + callLight = new GpioOutput(NanopiDuo2.Pin22.gpionumber, true); + + // belum ada pinout nya di PCB demo (04/12/2024) + Buzzer = new GpioOutput(NanopiDuo2.Pin18.gpionumber, true); + + // Start System monitoring + init_system_monitoring(); // Shutdown Hook Runtime.getRuntime().addShutdownHook(new Thread(() -> { Logger.info("Shutting down SIPIntercom"); if (client!=null) client.Disconnect(); if (webserver!=null) webserver.Stop(); + if (socketioserver!=null) socketioserver.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(); + if (system_monitoring_timer!=null) system_monitoring_timer.cancel(); })); } + /** + * Hangup call + */ + private static void hangupCall() { + if (oncallRequest!=null || oncallResponse!=null){ + client.HangUp(); + oncallResponse = null; + oncallRequest = null; + } else if (incomingRequest!=null || incomingResponse!=null){ + client.RejectIncomingCall(incomingRequest); + incomingRequest = null; + incomingResponse = null; + } + callLight_Idle(); + Buzzer_Off(); + SipStatus = "Idle"; + } + + /** + * Pickup incoming call + */ + private static void pickupCall() { + if (incomingRequest!=null && incomingResponse!=null){ + client.AcceptIncomingCall(incomingRequest); + callLight_OnCall(); + Buzzer_OnCall(); + oncallRequest = incomingRequest; + oncallResponse = incomingResponse; + incomingRequest = null; + incomingResponse = null; + SipStatus = "Communication with "+oncallRequest.CallID; + } + } + private static String CreateSipCallNumber(String extension){ + return MessageFormat.format("sip:{0}@{1}", extension, client.getServerAddress()); + } + @SuppressWarnings("unused") private static void CallTest(String extension){ - String callnumber = MessageFormat.format("sip:{0}@{1}", extension, client.getServerAddress()); + String callnumber = CreateSipCallNumber(extension); if (client.Call(callnumber)){ Logger.info("Call to {} is successful",callnumber); try{ @@ -240,27 +353,17 @@ public class Main { } else Logger.error("File not found: {}",ff.getAbsolutePath()); } - private static void ReconnectSIP(){ - if (client.Connect()){ - Logger.info("Connected to SIP Server"); - } - else{ - Logger.error("Failed to connect to SIP Server"); - try { - Thread.sleep(20*1000); - } catch (InterruptedException ignored) { - } - ReconnectSIP(); - } - } - /** * Registering state, call light is blinking with 500ms interval */ private static void callLight_Registering(){ - if (callLightTask!=null) callLightTask.cancel(); + if (callLightTask!=null) { + callLightTask.cancel(); + callLightTask = null; + } if (timer!=null){ timer.purge(); + callLightTask = CreateCallLightTask(); timer.scheduleAtFixedRate(callLightTask, 0, 500); } } @@ -269,9 +372,13 @@ public class Main { * Idle state, call light is blinking with interval 3000ms */ private static void callLight_Idle(){ - if (callLightTask!=null) callLightTask.cancel(); + if (callLightTask!=null) { + callLightTask.cancel(); + callLightTask = null; + } if (timer!=null){ timer.purge(); + callLightTask = CreateCallLightTask(); timer.scheduleAtFixedRate(callLightTask, 0, 3000); } } @@ -280,9 +387,13 @@ public class Main { * Incoming call, call light is blinking with 1000ms interval */ private static void callLight_IncomingCall(){ - if (callLightTask!=null) callLightTask.cancel(); + if (callLightTask!=null) { + callLightTask.cancel(); + callLightTask = null; + } if (timer!=null){ timer.purge(); + callLightTask = CreateCallLightTask(); timer.scheduleAtFixedRate(callLightTask, 0, 1000); } } @@ -291,7 +402,10 @@ public class Main { * On call, call light is on */ private static void callLight_OnCall(){ - if (callLightTask!=null) callLightTask.cancel(); + if (callLightTask!=null) { + callLightTask.cancel(); + callLightTask = null; + } if (timer!=null) timer.purge(); callLight.SetValue(true); } @@ -300,9 +414,13 @@ public class Main { * Incoming call, buzzer is beeping with 1000ms interval */ private static void Buzzer_IncomingCall(){ - if (BuzzerTask!=null) BuzzerTask.cancel(); + if (BuzzerTask!=null) { + BuzzerTask.cancel(); + BuzzerTask = null; + } if (timer!=null){ timer.purge(); + BuzzerTask = CreateBuzzerTask(); timer.scheduleAtFixedRate(BuzzerTask, 0, 1000); } } @@ -311,14 +429,97 @@ public class Main { * On-call, buzzer is off */ private static void Buzzer_OnCall(){ - if (BuzzerTask!=null) BuzzerTask.cancel(); + if (BuzzerTask!=null) { + BuzzerTask.cancel(); + BuzzerTask = null; + } if (timer!=null) timer.purge(); - Buzzer.SetValue(false); + if (Buzzer!=null) Buzzer.SetValue(false); } private static void Buzzer_Off(){ - if (BuzzerTask!=null) BuzzerTask.cancel(); + if (BuzzerTask!=null) { + BuzzerTask.cancel(); + BuzzerTask = null; + } if (timer!=null) timer.purge(); - Buzzer.SetValue(false); + if (Buzzer!=null) Buzzer.SetValue(false); } + + private static TimerTask CreateBuzzerTask(){ + return new TimerTask() { + @Override + public void run() { + if (Buzzer!=null && Buzzer.isInitialized()) Buzzer.BlinkON(500); + } + }; + } + + private static TimerTask CreateCallLightTask(){ + return new TimerTask() { + @Override + public void run() { + if (callLight!=null && callLight.isInitialized()) callLight.BlinkON(100); + } + }; + } + + private static void init_system_monitoring(){ + TimerTask tt = new TimerTask() { + @Override + public void run() { + cpuTemperature = SystemInformation.getCPUTemperature(); + ramInformation = SystemInformation.getRAMInformation(); + ProcessorStatus[] cpuinfo = SystemInformation.getProcStat(); + if (cpuinfo.length>0){ + if (previousCpuInfo==null || !Objects.equals(previousCpuInfo.length, cpuinfo.length)){ + previousCpuInfo = cpuinfo; + } else { + for(int ii=0;ii0){ + if (previousNetworkInfo==null || !Objects.equals(previousNetworkInfo.length, ntri.length)){ + previousNetworkInfo = ntri; + } else { + for(int ii=0;ii0){ + long bytesDiff = bytesReceived - prev.bytesReceived; + if (ValidString(unit)) unit = unit.toUpperCase(); + Double speed = ConvertToUnit(unit, timeDiff, bytesDiff); + if (speed != null) return speed; + } + } + } + return 0; + } + + @Nullable + private Double ConvertToUnit(String unit, long timeDiff, long bytesDiff) { + if (bytesDiff>0){ + double speed = ((double) bytesDiff / timeDiff) * 1000; + switch (unit) { + case "KB" : + return (speed / 1024); + case "MB" : + return (speed / 1024 / 1024); + case "GB" : + return (speed / 1024 / 1024 / 1024); + default : + return speed; + } + } + return null; + } + + /** + * Calculate the upload speed + * @param prev Previous NetworkTransmitReceiveInfo + * @param unit Speed unit (KB, MB, GB) + * @return Upload speed in {unit}/second + */ + public double TxSpeed(NetworkTransmitReceiveInfo prev, String unit){ + if (prev!=null){ + if (Objects.equals(prev.name, name)){ + long timeDiff = timetick - prev.timetick; + if (timeDiff>0){ + long bytesDiff = bytesTransmitted - prev.bytesTransmitted; + if (ValidString(unit)) unit = unit.toUpperCase(); + Double speed = ConvertToUnit(unit, timeDiff, bytesDiff); + if (speed != null) return speed; + } + } + } + return 0; + } +} diff --git a/src/SBC/ProcessorStatus.java b/src/SBC/ProcessorStatus.java new file mode 100644 index 0000000..355c041 --- /dev/null +++ b/src/SBC/ProcessorStatus.java @@ -0,0 +1,45 @@ +package SBC; + +public class ProcessorStatus { + public String name; + public int user; + public int nice; + public int system; + public int idle; + public int iowait; + public int irq; + public int softirq; + public int steal; + public int guest; + public int guest_nice; + + /** + * Calculate total CPU time + * @return Total CPU time + */ + public int total_time(){ + return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice; + } + + /** + * Calculate idle CPU time + * @return Idle CPU time + */ + public int idle_time(){ + return idle + iowait; + } + + /** + * Calculate CPU usage percentage + * @param prev Previous CPU information + * @return CPU usage percentage 0 - 100 + */ + public int cpu_usage(ProcessorStatus prev){ + if (prev!=null){ + int total_diff = total_time() - prev.total_time(); + int idle_diff = idle_time() - prev.idle_time(); + return (int)(100.0 * (total_diff - idle_diff) / total_diff); + } + return 0; + } +} diff --git a/src/SBC/RamInformation.java b/src/SBC/RamInformation.java new file mode 100644 index 0000000..d9fc08c --- /dev/null +++ b/src/SBC/RamInformation.java @@ -0,0 +1,12 @@ +package SBC; + +public class RamInformation { + public int totalKB; + public int usedKB; + public int availableKB; + public int swapTotalKB; + public int swapFreeKB; + public double RamUsagePercentage(){ + return (double) usedKB / totalKB * 100; + } +} diff --git a/src/SBC/SystemInformation.java b/src/SBC/SystemInformation.java new file mode 100644 index 0000000..8d6541e --- /dev/null +++ b/src/SBC/SystemInformation.java @@ -0,0 +1,179 @@ +package SBC; + +import com.sun.jna.Platform; + +import java.io.File; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SystemInformation { + + + + public static int getCPUTemperature() { + if (Platform.isLinux()){ + File ff = new File("/sys/class/thermal/thermal_zone0/temp"); + if (ff.isFile() && ff.canRead()){ + try{ + String value = new String(Files.readAllBytes(ff.toPath())).trim(); + return Integer.parseInt(value) / 1000; + } catch (Exception ignored) { + } + } + } + return 0; + } + + public static NetworkTransmitReceiveInfo[] getNetworkTransmitReceiveInfo(){ + if (Platform.isLinux()){ + File ff = new File("/proc/net/dev"); + if (ff.isFile() && ff.canRead()){ + List result = new ArrayList<>(); + final Pattern pattern = Pattern.compile("\\s+(.*):\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"); + try{ + String[] lines = Files.readAllLines(ff.toPath()).toArray(new String[0]); + for (String line : lines){ + Matcher m = pattern.matcher(line); + if (m.find()){ + NetworkTransmitReceiveInfo info = new NetworkTransmitReceiveInfo(); + info.name = m.group(1).trim(); + info.bytesReceived = Long.parseLong(m.group(2)); + info.packetsReceived = Long.parseLong(m.group(3)); + info.errorsReceived = Long.parseLong(m.group(4)); + info.droppedReceived = Long.parseLong(m.group(5)); + info.fifoReceived = Long.parseLong(m.group(6)); + info.frameReceived = Long.parseLong(m.group(7)); + info.compressedReceived = Long.parseLong(m.group(8)); + info.multicastReceived = Long.parseLong(m.group(9)); + info.bytesTransmitted = Long.parseLong(m.group(10)); + info.packetsTransmitted = Long.parseLong(m.group(11)); + info.errorsTransmitted = Long.parseLong(m.group(12)); + info.droppedTransmitted = Long.parseLong(m.group(13)); + info.fifoTransmitted = Long.parseLong(m.group(14)); + info.collsTransmitted = Long.parseLong(m.group(15)); + info.carrierTransmitted = Long.parseLong(m.group(16)); + info.compressedTransmitted = Long.parseLong(m.group(17)); + info.timetick = System.currentTimeMillis(); + result.add(info); + } + } + } catch (Exception ignored) { + + } + return result.toArray(new NetworkTransmitReceiveInfo[0]); + } + } + return new NetworkTransmitReceiveInfo[0]; + } + + public static CpuInfo getCPUInfo(){ + CpuInfo result = new CpuInfo(); + if (Platform.isLinux()){ + File ff = new File("/proc/cpuinfo"); + if (ff.isFile() && ff.canRead()){ + final Pattern pattern = Pattern.compile( "\\s*(.*):\\s*(.*)"); + try{ + String[] lines = Files.readAllLines(ff.toPath()).toArray(new String[0]); + for (String line : lines){ + Matcher m = pattern.matcher(line); + if (m.find()){ + String key = m.group(1).trim(); + String value = m.group(2).trim(); + switch (key){ + case "processor": + result.processorCount++; + break; + case "Revision": + result.revision = value; + break; + case "Serial": + result.serial = value; + break; + case "Model": + result.model = value; + break; + } + } + } + } catch (Exception ignored) { + } + } + } + return result; + } + + public static ProcessorStatus[] getProcStat(){ + if (Platform.isLinux()){ + File ff = new File("/proc/stat"); + if (ff.isFile() && ff.canRead()){ + final Pattern pattern = Pattern.compile( "(cpu\\d?)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"); + List result = new ArrayList<>(); + try{ + String[] lines = Files.readAllLines(ff.toPath()).toArray(new String[0]); + for (String line : lines){ + Matcher m = pattern.matcher(line); + if (m.find()){ + ProcessorStatus info = new ProcessorStatus(); + info.name = m.group(1).trim(); + info.user = Integer.parseInt(m.group(2)); + info.nice = Integer.parseInt(m.group(3)); + info.system = Integer.parseInt(m.group(4)); + info.idle = Integer.parseInt(m.group(5)); + info.iowait = Integer.parseInt(m.group(6)); + info.irq = Integer.parseInt(m.group(7)); + info.softirq = Integer.parseInt(m.group(8)); + info.steal = Integer.parseInt(m.group(9)); + info.guest = Integer.parseInt(m.group(10)); + info.guest_nice = Integer.parseInt(m.group(11)); + result.add(info); + } + } + return result.toArray(new ProcessorStatus[0]); + } catch (Exception ignored) { + } + } + } + return new ProcessorStatus[0]; + } + + public static RamInformation getRAMInformation(){ + + RamInformation result = new RamInformation(); + if (Platform.isLinux()){ + File ff = new File("/proc/meminfo"); + if (ff.isFile() && ff.canRead()){ + final Pattern pattern = Pattern.compile("(.*):\\s+(\\d+).kB"); + try{ + String[] lines = Files.readAllLines(ff.toPath()).toArray(new String[0]); + for (String line : lines) { + Matcher m = pattern.matcher(line); + if (m.find()){ + String key = m.group(1); + int value = Integer.parseInt(m.group(2)); + switch (key){ + case "MemTotal": + result.totalKB = value; + break; + case "MemAvailable": + result.availableKB = value; + break; + case "SwapTotal": + result.swapTotalKB = value; + break; + case "SwapFree": + result.swapFreeKB = value; + break; + } + } + } + } catch (Exception ignored) { + } + result.usedKB = result.totalKB - result.availableKB; + } + } + return result; + } +} diff --git a/src/SIP/jSIPClient.java b/src/SIP/jSIPClient.java index b8fe6a1..3090b11 100644 --- a/src/SIP/jSIPClient.java +++ b/src/SIP/jSIPClient.java @@ -67,6 +67,7 @@ public class jSIPClient { cc.setDomain(serverAddress); cc.setUserPart(Username); cc.setPassword(Password); + cc.SetLocalInetAddress("0.0.0.0"); em = new EventManager(cc); return false; @@ -616,9 +617,9 @@ public class jSIPClient { private void load_config(Properties prop) { - serverAddress = GetProperties_StringValue(prop,"SipServer","100.64.0.3"); - Username = GetProperties_StringValue(prop,"SipUsername","user1"); - Password = GetProperties_StringValue(prop,"SipPassword","12345678"); + serverAddress = GetProperties_StringValue(prop,"SipServer","rdkartono.ddns.me"); + Username = GetProperties_StringValue(prop,"SipUsername","101"); + Password = GetProperties_StringValue(prop,"SipPassword","password101"); Logger.info("SipServer: "+serverAddress); Logger.info("SipUsername: "+Username); Logger.info("SipPassword: "+Password); diff --git a/src/Webpage/LoginSetting.java b/src/Webpage/LoginSetting.java new file mode 100644 index 0000000..606f1a0 --- /dev/null +++ b/src/Webpage/LoginSetting.java @@ -0,0 +1,10 @@ +package Webpage; + +public class LoginSetting { + public String Username; + public String Password; + public LoginSetting(String username, String password){ + Username = username; + Password = password; + } +} diff --git a/src/Webpage/SipSetting.java b/src/Webpage/SipSetting.java new file mode 100644 index 0000000..cd07e8a --- /dev/null +++ b/src/Webpage/SipSetting.java @@ -0,0 +1,15 @@ +package Webpage; + +public class SipSetting { + public String Server; + public int Port; + public String Username; + public String Password; + + public SipSetting(String server, int port, String username, String password){ + this.Server = server; + this.Port = port; + this.Username = username; + this.Password = password; + } +} diff --git a/src/Webpage/SocketioRequest.java b/src/Webpage/SocketioRequest.java new file mode 100644 index 0000000..c434b4d --- /dev/null +++ b/src/Webpage/SocketioRequest.java @@ -0,0 +1,26 @@ +package Webpage; + +import lombok.Getter; + +import static code.common.gson; + +@Getter +public class SocketioRequest { + private final String request; + private final String data; + + public SocketioRequest(){ + request = ""; + data = ""; + } + + public SocketioRequest(String request, String data){ + this.request = request; + this.data = data; + } + + @Override + public String toString(){ + return gson.toJson(this); + } +} diff --git a/src/Webpage/SocketioResponse.java b/src/Webpage/SocketioResponse.java new file mode 100644 index 0000000..f43e39e --- /dev/null +++ b/src/Webpage/SocketioResponse.java @@ -0,0 +1,75 @@ +package Webpage; + +import SBC.RamInformation; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +import static code.common.gson; + +@Getter +@Setter +public class SocketioResponse { + private String response; + private String data; + + public SocketioResponse(){ + response = ""; + data = ""; + } + + public SocketioResponse(String response, String data){ + this.response = response; + this.data = data; + } + + @Override + public String toString(){ + return gson.toJson(this); + } + + public static SocketioResponse fromLoginSetting(String response, LoginSetting loginSetting){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + socketioResponse.setData(gson.toJson(loginSetting)); + return socketioResponse; + } + + public static SocketioResponse fromSipSetting(String response, SipSetting sipSetting){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + socketioResponse.setData(gson.toJson(sipSetting)); + return socketioResponse; + } + + public static SocketioResponse fromRamInformation(String response, RamInformation ramInformation){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + socketioResponse.setData(gson.toJson(ramInformation)); + return socketioResponse; + } + + public static SocketioResponse fromCpuStatus(String response, int cpuTemperature, Map cpuUsage){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + JsonObject jo = new JsonObject(); + jo.addProperty("cpuTemperature", cpuTemperature); + jo.addProperty("cpuUsage", gson.toJson(cpuUsage)); + socketioResponse.setData(jo.toString()); + return socketioResponse; + } + + public static SocketioResponse fromTxRxMap(String response, Map txmap, Map rxmap){ + SocketioResponse socketioResponse = new SocketioResponse(); + socketioResponse.setResponse(response); + JsonObject jo = new JsonObject(); + jo.addProperty("txmap", gson.toJson(txmap)); + jo.addProperty("rxmap", gson.toJson(rxmap)); + socketioResponse.setData(jo.toString()); + return socketioResponse; + } + + +} diff --git a/src/Webpage/SocketioServer.java b/src/Webpage/SocketioServer.java new file mode 100644 index 0000000..3fadece --- /dev/null +++ b/src/Webpage/SocketioServer.java @@ -0,0 +1,56 @@ +package Webpage; + +import com.corundumstudio.socketio.Configuration; +import com.corundumstudio.socketio.SocketIONamespace; +import com.corundumstudio.socketio.SocketIOServer; +import lombok.NonNull; +import lombok.Setter; +import org.pmw.tinylog.Logger; + +import java.util.function.Function; + +public class SocketioServer { + private final SocketIOServer server; + private @Setter Function<@NonNull SocketioRequest, @NonNull SocketioResponse> onRequest; + + /** + * Create Socket.io Server + * @param localip Local Ip address to bind.
if null or empty will default to 0.0.0.0 + * @param listenport Local Port to bind.
if invalid, will default to 9092 + */ + public SocketioServer(String localip,int listenport){ + if (localip==null || localip.isEmpty()) localip="0.0.0.0"; + if (listenport<=0 || listenport>65535) listenport=9092; + Configuration config = new Configuration(); + config.setHostname(localip); + config.setPort(listenport); + + server = new SocketIOServer(config); + SocketIONamespace socketio = server.addNamespace("/socketio"); + socketio.addConnectListener(client -> Logger.info("Client id={} remoteaddress={} Connected to /socketio: " , client.getSessionId(), client.getRemoteAddress())); + socketio.addDisconnectListener(client -> Logger.info("Client id={} remoteaddress={} Disconnected from /socketio: ", client.getSessionId(), client.getRemoteAddress())); + socketio.addEventListener("command", SocketioRequest.class, (client, data, ackRequest) -> { + Logger.info("Client id={} remoteaddress={} request: {}", client.getSessionId(), client.getRemoteAddress(), data); + if (onRequest!=null){ + SocketioResponse response = onRequest.apply(data); + Logger.info("Client id={} remoteaddress={} response: {}", client.getSessionId(), client.getRemoteAddress(), response); + ackRequest.sendAckData(response); + } + }); + + } + + /** + * Start the server + */ + public void Start(){ + if (server!=null) server.start(); + } + + /** + * Stop the server + */ + public void Stop(){ + if (server!=null) server.stop(); + } +} diff --git a/src/code/common.java b/src/code/common.java index 31b7d63..6885c6f 100644 --- a/src/code/common.java +++ b/src/code/common.java @@ -23,6 +23,9 @@ public class common { 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 final double KB_threshold = 1024.0; + public static final double MB_threshold = 1024.0 * 1024.0; + public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0; public static String GetProperties_StringValue(Properties prop, String key, String defaultavalue){ if (prop!=null){ @@ -108,6 +111,19 @@ public class common { return prop; } + public static boolean SaveProperties(String directory, String filename, Properties prop){ + try { + File file = new File(directory,filename); + file.createNewFile(); + prop.store(Files.newOutputStream(file.toPath()),""); + Logger.info("Saved properties file: {}",filename); + return true; + } catch (Exception e) { + Logger.error("Failed to save properties file: {}",filename); + } + return false; + } + /** * Check if String is not null and have value * @param value string to check diff --git a/src/peers/sip/core/useragent/UserAgent.java b/src/peers/sip/core/useragent/UserAgent.java index 8e178d6..46125ce 100644 --- a/src/peers/sip/core/useragent/UserAgent.java +++ b/src/peers/sip/core/useragent/UserAgent.java @@ -26,7 +26,6 @@ import java.util.List; import lombok.Getter; import lombok.Setter; -import org.pmw.tinylog.Logger; import peers.Config; import peers.XmlConfig; @@ -125,16 +124,7 @@ public class UserAgent { cseqCounter = 1; - String buf = "starting user agent [" + - "myAddress: " + - config.getLocalInetAddress().getHostAddress() + ", " + - "sipPort: " + - config.getSipPort() + ", " + - "userpart: " + - config.getUserPart() + ", " + - "domain: " + - config.getDomain() + "]"; - Logger.info(buf); + //transaction user diff --git a/src/peers/sip/transport/MessageReceiver.java b/src/peers/sip/transport/MessageReceiver.java index 0c1dbcf..b7365b0 100644 --- a/src/peers/sip/transport/MessageReceiver.java +++ b/src/peers/sip/transport/MessageReceiver.java @@ -26,6 +26,7 @@ import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.InetAddress; +import lombok.Setter; import org.pmw.tinylog.Logger; import peers.Config; @@ -47,10 +48,11 @@ public abstract class MessageReceiver implements Runnable { private boolean isListening; //private UAS uas; + @Setter private SipServerTransportUser sipServerTransportUser; - private TransactionManager transactionManager; - private TransportManager transportManager; - private Config config; + private final TransactionManager transactionManager; + private final TransportManager transportManager; + private final Config config; public MessageReceiver(int port, TransactionManager transactionManager, @@ -83,10 +85,7 @@ public abstract class MessageReceiver implements Runnable { } catch (UnsupportedEncodingException e) { Logger.error("unsupported encoding", e); } - if (RFC3261.DEFAULT_SIP_VERSION.equals(beginning)) { - return false; - } - return true; + return !RFC3261.DEFAULT_SIP_VERSION.equals(beginning); } protected void processMessage(byte[] message, InetAddress sourceIp, @@ -115,10 +114,7 @@ public abstract class MessageReceiver implements Runnable { } return; } - StringBuffer direction = new StringBuffer(); - direction.append("RECEIVED from ").append(sourceIp.getHostAddress()); - direction.append("/").append(sourcePort); - Logger.info(new String(message),direction.toString()); + SipMessage sipMessage = null; try { sipMessage = transportManager.sipParser.parse( @@ -158,7 +154,7 @@ public abstract class MessageReceiver implements Runnable { SipHeaderParamName rportName = new SipHeaderParamName( RFC3261.PARAM_RPORT); String rport = topVia.getParam(rportName); - if (rport != null && "".equals(rport)) { + if (rport != null && rport.isEmpty()) { topVia.removeParam(rportName); topVia.addParam(rportName, String.valueOf(sourcePort)); } @@ -193,13 +189,4 @@ public abstract class MessageReceiver implements Runnable { return isListening; } - public void setSipServerTransportUser( - SipServerTransportUser sipServerTransportUser) { - this.sipServerTransportUser = sipServerTransportUser; - } - -// public void setUas(UAS uas) { -// this.uas = uas; -// } - } diff --git a/src/peers/sip/transport/TransportManager.java b/src/peers/sip/transport/TransportManager.java index 7d302d1..811d839 100644 --- a/src/peers/sip/transport/TransportManager.java +++ b/src/peers/sip/transport/TransportManager.java @@ -329,7 +329,6 @@ public class TransportManager { } datagramSocket.setSoTimeout(SOCKET_TIMEOUT); datagramSockets.put(conn, datagramSocket); - Logger.info("added datagram socket " + conn); } socket = datagramSocket; messageSender = new UdpMessageSender(conn.getRemoteInetAddress(), @@ -409,7 +408,6 @@ public class TransportManager { } sipPort = datagramSocket.getLocalPort(); datagramSockets.put(sipTransportConnection, datagramSocket); - Logger.info("added datagram socket " + sipTransportConnection); } messageReceiver = new UdpMessageReceiver(datagramSocket, transactionManager, this, config); @@ -420,8 +418,7 @@ public class TransportManager { //messageReceiver = new TcpMessageReceiver(port); } messageReceivers.put(sipTransportConnection, messageReceiver); - Logger.info("added " + sipTransportConnection + ": " + messageReceiver - + " to message receivers"); + return messageReceiver; } diff --git a/src/peers/sip/transport/UdpMessageSender.java b/src/peers/sip/transport/UdpMessageSender.java index 4e65fcb..e65e137 100644 --- a/src/peers/sip/transport/UdpMessageSender.java +++ b/src/peers/sip/transport/UdpMessageSender.java @@ -44,15 +44,11 @@ public class UdpMessageSender extends MessageSender { @Override public synchronized void sendMessage(SipMessage sipMessage) { - Logger.debug("UdpMessageSender.sendMessage"); - if (sipMessage == null) { + if (sipMessage == null) { return; } byte[] buf = sipMessage.toString().getBytes(); sendBytes(buf); - String direction = "SENT to " + inetAddress.getHostAddress() + - "/" + port; - Logger.info(new String(buf), direction); } @Override