11package betaflight .configurator .plugin ;
22
3- import android .util .Log ;
4-
53import com .getcapacitor .JSObject ;
64import com .getcapacitor .Plugin ;
75import com .getcapacitor .PluginCall ;
108import java .io .*;
119import java .net .Socket ;
1210
11+ /**
12+ * Capacitor plugin that provides raw TCP socket functionality.
13+ * Implements methods to connect, send, receive, and disconnect.
14+ */
1315@ CapacitorPlugin (name = "SocketPlugin" )
1416public class SocketPlugin extends Plugin {
1517 private Socket socket ;
1618 private BufferedReader reader ;
1719 private BufferedWriter writer ;
20+ private boolean isConnected = false ;
1821
1922 @ PluginMethod
2023 public void connect (PluginCall call ) {
2124 String ip = call .getString ("ip" );
2225 int port = call .getInt ("port" );
26+
27+ // Validate inputs
28+ if (ip == null || ip .isEmpty ()) {
29+ call .reject ("IP address is required" );
30+ return ;
31+ }
32+
33+ if (port <= 0 || port > 65535 ) {
34+ call .reject ("Invalid port number" );
35+ return ;
36+ }
37+
38+ // Prevent duplicate connections
39+ if (socket != null && !socket .isClosed ()) {
40+ call .reject ("Already connected; please disconnect first" );
41+ return ;
42+ }
43+
2344 try {
2445 socket = new Socket (ip , port );
46+ socket .setSoTimeout (30_000 ); // 30s timeout
2547 reader = new BufferedReader (new InputStreamReader (socket .getInputStream ()));
2648 writer = new BufferedWriter (new OutputStreamWriter (socket .getOutputStream ()));
2749 JSObject ret = new JSObject ();
2850 ret .put ("success" , true );
2951 call .resolve (ret );
3052 } catch (Exception e ) {
53+ closeResources ();
3154 call .reject ("Connection failed: " + e .getMessage ());
3255 }
3356 }
3457
35- @ PluginMethod
58+ @ PluginMethod
3659 public void send (PluginCall call ) {
3760 String data = call .getString ("data" );
61+
62+ // Validate input
63+ if (data == null ) {
64+ call .reject ("Data is required" );
65+ return ;
66+ }
67+
68+ // Check connection state
69+ if (socket == null || socket .isClosed () || !isConnected ) {
70+ call .reject ("Not connected to any server" );
71+ return ;
72+ }
73+
3874 try {
3975 writer .write (data );
4076 writer .flush ();
4177 JSObject ret = new JSObject ();
4278 ret .put ("success" , true );
4379 call .resolve (ret );
4480 } catch (Exception e ) {
81+ closeResources ();
82+ isConnected = false ;
4583 call .reject ("Send failed: " + e .getMessage ());
4684 }
4785 }
@@ -61,12 +99,36 @@ public void receive(PluginCall call) {
6199 @ PluginMethod
62100 public void disconnect (PluginCall call ) {
63101 try {
64- if (socket != null ) socket .close ();
102+ closeResources ();
103+ isConnected = false ;
65104 JSObject ret = new JSObject ();
66105 ret .put ("success" , true );
67106 call .resolve (ret );
68107 } catch (Exception e ) {
69108 call .reject ("Disconnect failed: " + e .getMessage ());
70109 }
71110 }
111+
112+ /**
113+ * Helper method to close all resources and clean up state
114+ */
115+ private void closeResources () {
116+ try {
117+ if (reader != null ) {
118+ reader .close ();
119+ reader = null ;
120+ }
121+ if (writer != null ) {
122+ writer .close ();
123+ writer = null ;
124+ }
125+ if (socket != null ) {
126+ socket .close ();
127+ socket = null ;
128+ }
129+ } catch (IOException e ) {
130+ // Log but continue cleanup
131+ getContext ().getActivity ().runOnUiThread (() ->
132+ Log .e ("SocketPlugin" , "Error closing resources" , e ));
133+ }
72134}
0 commit comments