Skip to content

Commit 8572d43

Browse files
authored
Merge pull request #100 from norkator/nut-fqdn-and-authentication
NUT "FQDN" connection and authentication
2 parents 96bfd97 + f201b31 commit 8572d43

File tree

7 files changed

+122
-16
lines changed

7 files changed

+122
-16
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dependencies {
4747
implementation 'com.google.android.material:material:1.5.0'
4848
implementation 'joda-time:joda-time:2.10.13'
4949
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
50+
implementation 'com.google.android.flexbox:flexbox:3.0.0'
5051
// For the notifications
5152
implementation 'com.google.firebase:firebase-messaging:23.0.0'
5253
// Tests

app/src/main/java/com/nitramite/apcupsdmonitor/ConnectionType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ public class ConnectionType {
77
public static final String UPS_CONNECTION_TYPE_SSH = "0"; // SSH (Secure Shell)
88
public static final String UPS_CONNECTION_TYPE_NIS = "1"; // APCUPSD (Network Information Server)
99
public static final String UPS_CONNECTION_TYPE_IPM = "2"; // Eaton IPM (Intelligent Power Manager)
10+
public static final String UPS_CONNECTION_TYPE_NUT = "3"; // NUT server (Network UPS Tools)
1011

1112
}

app/src/main/java/com/nitramite/apcupsdmonitor/ConnectorTask.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ ups.UPS_SERVER_ADDRESS, portStringToInteger(ups.UPS_SERVER_PORT),
187187
databaseHelper.insertEvents(writablePool, ups.UPS_ID, ipm.getEvents());
188188
}
189189
break;
190+
case ConnectionType.UPS_CONNECTION_TYPE_NUT:
191+
try {
192+
String[] nutFQDN = ups.UPS_SERVER_ADDRESS.split("@");
193+
Socket socket = connectSocketServer(nutFQDN[1], portStringToInteger(ups.UPS_SERVER_PORT));
194+
getUPSStatusNUT(writablePool, socket, ups, nutFQDN[0]);
195+
} catch (IOError e) {
196+
apcupsdInterface.onCommandError(e.toString());
197+
} catch (IOException e) {
198+
onConnectionError(writablePool, ups.UPS_ID);
199+
}
200+
break;
190201
default:
191202
Log.w(TAG, "Unsupported UPS connection type");
192203
break;
@@ -324,7 +335,7 @@ private void getUPSStatusNMC(
324335
}
325336
}
326337

327-
// Get ups status
338+
328339
private void getUPSStatusSSH(
329340
SQLiteDatabase writablePool, Session session, final UPS ups, final boolean loadEvents
330341
) {
@@ -404,6 +415,38 @@ private void getUPSStatusAPCUPSD(
404415
}
405416

406417

418+
private void getUPSStatusNUT(
419+
SQLiteDatabase writablePool, Socket socket, final UPS ups, final String nutUpsName
420+
) {
421+
try {
422+
StringBuilder stringBuilder = new StringBuilder();
423+
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
424+
425+
dOut.writeBytes("LIST VAR " + nutUpsName + "\n");
426+
427+
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
428+
429+
String line = null;
430+
while ((line = in.readLine()) != null) {
431+
String line_ = line.replace("VAR " + nutUpsName + " ", "");
432+
stringBuilder.append(line_);
433+
Log.i(TAG, line_);
434+
if (line.contains("END LIST VAR")) {
435+
break;
436+
}
437+
}
438+
439+
ContentValues contentValues = new ContentValues();
440+
contentValues.put(DatabaseHelper.UPS_REACHABLE, UPS.UPS_REACHABLE);
441+
contentValues.put(DatabaseHelper.UPS_STATUS_STR, stringBuilder.toString());
442+
databaseHelper.insertUpdateUps(writablePool, ups.UPS_ID, contentValues);
443+
} catch (IOException e) {
444+
e.printStackTrace();
445+
apcupsdInterface.onCommandError(e.toString());
446+
}
447+
}
448+
449+
407450
// ---------------------------------------------------------------------------------------------
408451

409452

app/src/main/java/com/nitramite/apcupsdmonitor/UpsEditor.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import android.widget.RadioButton;
2323
import android.widget.Spinner;
2424
import android.widget.Switch;
25+
import android.widget.TextView;
2526
import android.widget.Toast;
2627

2728
import androidx.appcompat.app.AppCompatActivity;
@@ -53,6 +54,7 @@ public class UpsEditor extends AppCompatActivity {
5354
private RadioButton sshRB;
5455
private RadioButton nisRB;
5556
private RadioButton ipmRB;
57+
private RadioButton nutRB;
5658

5759
// File paths
5860
public static final String PATH = "/keys/";
@@ -73,6 +75,7 @@ protected void onCreate(Bundle savedInstanceState) {
7375
sshRB = findViewById(R.id.sshRB);
7476
nisRB = findViewById(R.id.nisRB);
7577
ipmRB = findViewById(R.id.ipmRB);
78+
nutRB = findViewById(R.id.nutRB);
7679

7780
// Editable views
7881
final EditText serverAddressET = findViewById(R.id.serverAddressET);
@@ -90,6 +93,10 @@ protected void onCreate(Bundle savedInstanceState) {
9093
final Switch upsEnabledSwitch = findViewById(R.id.upsEnabledSwitch);
9194
final Switch httpsEnabledSwitch = findViewById(R.id.httpsEnabledSwitch);
9295

96+
// Other views
97+
final TextView serverAddressHintText = findViewById(R.id.serverAddressHintText);
98+
serverAddressHintText.setVisibility(View.GONE);
99+
93100

94101
final Spinner cmdPresetSelection = findViewById(R.id.cmdPresetSelection);
95102
List<String> cmdPresetOptions = new ArrayList<>();
@@ -146,13 +153,15 @@ public void onNothingSelected(AdapterView<?> parent) {
146153
ipmOptionsLayout = findViewById(R.id.ipmOptionsLayout);
147154
httpHttpsOptionsLayout = findViewById(R.id.httpHttpsOptionsLayout);
148155

156+
// Todo, please somebody find a better way for this setChecked, visibility mess
149157
sshRB.setOnClickListener(v -> {
150158
sshOptionsLayout.setVisibility(View.VISIBLE);
151159
credentialOptionsLayout.setVisibility(View.VISIBLE);
152160
ipmOptionsLayout.setVisibility(View.GONE);
153161
httpHttpsOptionsLayout.setVisibility(View.GONE);
154162
nisRB.setChecked(false);
155163
ipmRB.setChecked(false);
164+
nutRB.setChecked(false);
156165
});
157166
nisRB.setOnClickListener(v -> {
158167
sshOptionsLayout.setVisibility(View.GONE);
@@ -161,6 +170,7 @@ public void onNothingSelected(AdapterView<?> parent) {
161170
httpHttpsOptionsLayout.setVisibility(View.GONE);
162171
sshRB.setChecked(false);
163172
ipmRB.setChecked(false);
173+
nutRB.setChecked(false);
164174
});
165175
ipmRB.setOnClickListener(v -> {
166176
sshOptionsLayout.setVisibility(View.GONE);
@@ -169,6 +179,18 @@ public void onNothingSelected(AdapterView<?> parent) {
169179
httpHttpsOptionsLayout.setVisibility(View.VISIBLE);
170180
nisRB.setChecked(false);
171181
sshRB.setChecked(false);
182+
nutRB.setChecked(false);
183+
});
184+
nutRB.setOnClickListener(v -> {
185+
sshOptionsLayout.setVisibility(View.GONE);
186+
credentialOptionsLayout.setVisibility(View.VISIBLE);
187+
ipmOptionsLayout.setVisibility(View.VISIBLE);
188+
httpHttpsOptionsLayout.setVisibility(View.GONE);
189+
serverAddressHintText.setVisibility(View.VISIBLE);
190+
nodeIdET.setVisibility(View.GONE);
191+
nisRB.setChecked(false);
192+
sshRB.setChecked(false);
193+
ipmRB.setChecked(false);
172194
});
173195

174196

@@ -187,6 +209,7 @@ public void onNothingSelected(AdapterView<?> parent) {
187209
sshRB.setChecked(true);
188210
ipmRB.setChecked(false);
189211
nisRB.setChecked(false);
212+
nutRB.setChecked(false);
190213
sshOptionsLayout.setVisibility(View.VISIBLE);
191214
credentialOptionsLayout.setVisibility(View.VISIBLE);
192215
ipmOptionsLayout.setVisibility(View.GONE);
@@ -195,6 +218,7 @@ public void onNothingSelected(AdapterView<?> parent) {
195218
nisRB.setChecked(true);
196219
ipmRB.setChecked(false);
197220
sshRB.setChecked(false);
221+
nutRB.setChecked(false);
198222
sshOptionsLayout.setVisibility(View.GONE);
199223
credentialOptionsLayout.setVisibility(View.GONE);
200224
ipmOptionsLayout.setVisibility(View.GONE);
@@ -203,10 +227,22 @@ public void onNothingSelected(AdapterView<?> parent) {
203227
ipmRB.setChecked(true);
204228
nisRB.setChecked(false);
205229
sshRB.setChecked(false);
230+
nutRB.setChecked(false);
206231
sshOptionsLayout.setVisibility(View.GONE);
207232
credentialOptionsLayout.setVisibility(View.VISIBLE);
208233
ipmOptionsLayout.setVisibility(View.VISIBLE);
209234
break;
235+
case ConnectionType.UPS_CONNECTION_TYPE_NUT:
236+
nutRB.setChecked(true);
237+
ipmRB.setChecked(false);
238+
nisRB.setChecked(false);
239+
sshRB.setChecked(false);
240+
sshOptionsLayout.setVisibility(View.GONE);
241+
credentialOptionsLayout.setVisibility(View.VISIBLE);
242+
ipmOptionsLayout.setVisibility(View.GONE);
243+
httpsEnabledSwitch.setVisibility(View.GONE);
244+
serverAddressHintText.setVisibility(View.VISIBLE);
245+
break;
210246
}
211247

212248
serverAddressET.setText(ups.UPS_SERVER_ADDRESS);
@@ -329,6 +365,8 @@ private String getConnectionType() {
329365
return ConnectionType.UPS_CONNECTION_TYPE_NIS;
330366
} else if (ipmRB.isChecked()) {
331367
return ConnectionType.UPS_CONNECTION_TYPE_IPM;
368+
} else if (nutRB.isChecked()) {
369+
return ConnectionType.UPS_CONNECTION_TYPE_NUT;
332370
} else {
333371
return ConnectionType.UPS_CONNECTION_TYPE_NA;
334372
}

app/src/main/res/layout/activity_ups_editor.xml

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools"
4+
xmlns:app="http://schemas.android.com/apk/res-auto"
45
android:layout_width="match_parent"
56
android:layout_height="match_parent"
67
android:orientation="vertical"
@@ -47,11 +48,12 @@
4748
android:text="@string/off_ssh_on_apcupsd_tcp_port"
4849
android:textSize="12sp" />
4950

50-
<LinearLayout
51-
android:layout_width="fill_parent"
51+
<com.google.android.flexbox.FlexboxLayout
52+
android:layout_width="match_parent"
5253
android:layout_height="wrap_content"
53-
android:layout_gravity="center"
54-
android:orientation="horizontal">
54+
app:flexWrap="wrap"
55+
app:alignItems="stretch"
56+
app:alignContent="stretch">
5557

5658
<RadioButton
5759
android:id="@+id/sshRB"
@@ -81,8 +83,16 @@
8183
android:text="@string/eaton_ipm"
8284
tools:ignore="UnusedAttribute" />
8385

84-
</LinearLayout>
86+
<RadioButton
87+
android:id="@+id/nutRB"
88+
android:layout_width="wrap_content"
89+
android:layout_height="wrap_content"
90+
android:layout_weight="1"
91+
android:enabled="true"
92+
android:text="@string/nut"
93+
tools:ignore="UnusedAttribute" />
8594

95+
</com.google.android.flexbox.FlexboxLayout>
8696

8797

8898
<TextView
@@ -92,6 +102,14 @@
92102
android:text="@string/server_address"
93103
android:textSize="18sp" />
94104

105+
<TextView
106+
android:id="@+id/serverAddressHintText"
107+
android:layout_width="wrap_content"
108+
android:layout_height="wrap_content"
109+
android:layout_marginTop="5dp"
110+
android:text="@string/server_address_hint_text"
111+
android:textSize="12sp" />
112+
95113
<EditText
96114
android:id="@+id/serverAddressET"
97115
android:layout_width="match_parent"

app/src/main/res/values-ru/strings.xml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<string name="app_name">APCUPSD Monitor</string>
66

77
<!-- Generic -->
8+
89
<string name="stats">Статистика</string>
910
<string name="loading">ЗАГРУЗКА</string>
1011
<string name="error">ошибка</string>
@@ -46,7 +47,7 @@
4647
<string name="server_address">Адрес сервера</string>
4748
<string name="server_ip_or_domain_address">IP-адрес сервера или адрес домена</string>
4849
<string name="server_port">Порт сервера</string>
49-
<string name="ssh_default_port_is_22_apcupsd_default_tcp_port_is_3551">Порт SSH по умолчанию - 22. Порт TCP по умолчанию APCUPSD - 3551. Eaton IPM HTTPS 4680 а также HTTP 4679.</string>
50+
<string name="ssh_default_port_is_22_apcupsd_default_tcp_port_is_3551">Порт SSH по умолчанию - 22. Порт TCP по умолчанию APCUPSD - 3551. Eaton IPM HTTPS 4680 а также HTTP 4679. Порт сервера NUT по умолчанию — 3493.</string>
5051
<string name="port_to_use_for_connection">Порт для подключения</string>
5152
<string name="server_username_ssh">Имя пользователя сервера (SSH)</string>
5253
<string name="ssh_server_username">Имя пользователя</string>
@@ -78,6 +79,12 @@
7879
<string name="ups_enable_toggle_description">ИБП можно на мгновение отключить, если он не подключен. Затем процесс обновления пропустит этот ИБП.</string>
7980
<string name="use_https">Использовать HTTPS</string>
8081
<string name="http_https_connection_description">HTTPS использует безопасный зашифрованный канал связи, что рекомендуется. Для HTTPS вам понадобится действующий сертификат. Использовать открытый текст HTTP только как последний вариант.</string>
82+
<string name="apcupsd_nis">APCUPSD NIS</string>
83+
<string name="eaton_ipm">Eaton IPM</string>
84+
<string name="nut">NUT</string>
85+
<string name="node_id_ipm">Node ID (IPM)</string>
86+
<string name="node_id_eaton_ipm_hint">Идентификатор узла для Eaton IPM, например UW222A0123</string>
87+
<string name="server_address_hint_text">Адрес NUT определяется именем ИБП@адрес, например: dummy@192.168.1.100</string>
8188

8289
<!-- UpsViewer -->
8390
<string name="m">M</string>
@@ -189,10 +196,6 @@
189196
<string name="ssh">SSH</string>
190197

191198
<!-- Others -->
192-
<string name="apcupsd_nis">APCUPSD NIS</string>
193-
<string name="eaton_ipm">Eaton IPM</string>
194-
<string name="node_id_ipm">Node ID (IPM)</string>
195-
<string name="node_id_eaton_ipm_hint">Идентификатор узла для Eaton IPM, например UW222A0123</string>
196199
<string name="ups_undefined_cannot_load_web_page">ИБП не определен. Невозможно загрузить веб-страницу.</string>
197200
<string name="no_web_interface">У этого ИБП нет веб-интерфейса.</string>
198201
<string name="toggle_web_interface">Переключить веб-интерфейс</string>

app/src/main/res/values/strings.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<string name="server_address">Server address</string>
4747
<string name="server_ip_or_domain_address">Server ip or domain address</string>
4848
<string name="server_port">Server port</string>
49-
<string name="ssh_default_port_is_22_apcupsd_default_tcp_port_is_3551">SSH default port is 22. APCUPSD default tcp port is 3551. Eaton IPM HTTPS 4680 and HTTP 4679.</string>
49+
<string name="ssh_default_port_is_22_apcupsd_default_tcp_port_is_3551">SSH default port is 22. APCUPSD default tcp port is 3551. Eaton IPM HTTPS 4680 and HTTP 4679. NUT server default port is 3493.</string>
5050
<string name="port_to_use_for_connection">Port to use for connection</string>
5151
<string name="server_username_ssh">Server username</string>
5252
<string name="ssh_server_username">Server username (SSH, IPM etc)</string>
@@ -78,6 +78,12 @@
7878
<string name="ups_enable_toggle_description">UPS can be disabled momentarily if its not connected. Update process will then skip this UPS.</string>
7979
<string name="use_https">Use HTTPS</string>
8080
<string name="http_https_connection_description">HTTPS uses secure encrypted communication channel which is recommended way. With HTTPS you will need valid certificate. Use cleartext HTTP only as last option.</string>
81+
<string name="apcupsd_nis">APCUPSD NIS</string>
82+
<string name="eaton_ipm">Eaton IPM</string>
83+
<string name="nut">NUT</string>
84+
<string name="node_id_ipm">Node ID (IPM)</string>
85+
<string name="node_id_eaton_ipm_hint">Node id for Eaton IPM like UW222A0123</string>
86+
<string name="server_address_hint_text">NUT address is defined with UPS name@address like: dummy@192.168.1.100</string>
8187

8288
<!-- UpsViewer -->
8389
<string name="m">M</string>
@@ -189,10 +195,6 @@
189195
<string name="ssh">SSH</string>
190196

191197
<!-- Others -->
192-
<string name="apcupsd_nis">APCUPSD NIS</string>
193-
<string name="eaton_ipm">Eaton IPM</string>
194-
<string name="node_id_ipm">Node ID (IPM)</string>
195-
<string name="node_id_eaton_ipm_hint">Node id for Eaton IPM like UW222A0123</string>
196198
<string name="ups_undefined_cannot_load_web_page">UPS is undefined. Cannot load web page.</string>
197199
<string name="no_web_interface">This UPS does not have web interface</string>
198200
<string name="toggle_web_interface">Toggle web interface</string>

0 commit comments

Comments
 (0)