Allow pulling part of the log file from a hub via bluetooth.

This commit is contained in:
MarkBryanMilligan 2021-02-28 23:36:58 -06:00
parent 11097049e2
commit 16c853bf86
8 changed files with 115 additions and 27 deletions

View File

@ -3,7 +3,7 @@
<groupId>com.lanternsoftware.currentmonitor</groupId> <groupId>com.lanternsoftware.currentmonitor</groupId>
<artifactId>lantern-currentmonitor</artifactId> <artifactId>lantern-currentmonitor</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>0.9.6</version> <version>1.0.1</version>
<name>lantern-currentmonitor</name> <name>lantern-currentmonitor</name>
<properties> <properties>

View File

@ -101,7 +101,7 @@ public class CurrentMonitor {
listener = _listener; listener = _listener;
List<Breaker> validBreakers = CollectionUtils.filter(_breakers, _b->_b.getPort() > 0 && _b.getPort() < 16); List<Breaker> validBreakers = CollectionUtils.filter(_breakers, _b->_b.getPort() > 0 && _b.getPort() < 16);
sampler = new Sampler(_hub, validBreakers, _intervalMs, 2); sampler = new Sampler(_hub, validBreakers, _intervalMs, 2);
LOG.info("Starting to monitor ports {}", CollectionUtils.transformToCommaSeparated(_breakers, _b->String.valueOf(_b.getPort()))); LOG.info("Starting to monitor ports {}", CollectionUtils.transformToCommaSeparated(validBreakers, _b->String.valueOf(_b.getPort())));
executor.submit(sampler); executor.submit(sampler);
} }

View File

@ -13,10 +13,12 @@ import com.lanternsoftware.datamodel.currentmonitor.BreakerPowerMinute;
import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic; import com.lanternsoftware.datamodel.currentmonitor.HubConfigCharacteristic;
import com.lanternsoftware.datamodel.currentmonitor.HubConfigService; import com.lanternsoftware.datamodel.currentmonitor.HubConfigService;
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute; import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
import com.lanternsoftware.datamodel.currentmonitor.NetworkStatus;
import com.lanternsoftware.util.CollectionUtils; import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.DateUtils; import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.NullUtils; import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.ResourceLoader; import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.ZipUtils;
import com.lanternsoftware.util.concurrency.ConcurrencyUtils; import com.lanternsoftware.util.concurrency.ConcurrencyUtils;
import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.DaoSerializer;
@ -39,6 +41,7 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -165,20 +168,32 @@ public class MonitorApp {
return ByteBuffer.allocate(4).putInt(breakerConfig == null?0:breakerConfig.getAccountId()).array(); return ByteBuffer.allocate(4).putInt(breakerConfig == null?0:breakerConfig.getAccountId()).array();
if (HubConfigCharacteristic.NetworkState == ch) if (HubConfigCharacteristic.NetworkState == ch)
return new byte[]{NetworkMonitor.getNetworkStatus().toMask()}; return new byte[]{NetworkMonitor.getNetworkStatus().toMask()};
if (HubConfigCharacteristic.NetworkDetails == ch) {
NetworkStatus status = NetworkMonitor.getNetworkStatus();
DaoEntity meta = DaoSerializer.fromZipBson(pool.executeToByteArray(new HttpGet(host + "update/version")));
status.setPingSuccessful(CollectionUtils.isNotEmpty(meta));
return DaoSerializer.toZipBson(status);
}
if (HubConfigCharacteristic.Log == ch) {
String[] log = NullUtils.cleanSplit(ResourceLoader.loadFileAsString(WORKING_DIR + "log/log.txt"), "\n");
if (log.length > 10)
log = Arrays.copyOfRange(log, log.length-10, log.length);
return ZipUtils.zip(NullUtils.toByteArray(CollectionUtils.delimit(Arrays.asList(log), "\n")));
}
return null; return null;
} }
}); });
bluetoothConfig.start(); bluetoothConfig.start();
if (NullUtils.isNotEmpty(config.getAuthCode())) if (NullUtils.isNotEmpty(config.getAuthCode()))
authCode = config.getAuthCode(); authCode = config.getAuthCode();
else if (NullUtils.isNotEmpty(host)) { else if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(config.getUsername()) && NullUtils.isNotEmpty(config.getPassword())) {
HttpGet auth = new HttpGet(host + "auth"); HttpGet auth = new HttpGet(host + "auth");
HttpPool.addBasicAuthHeader(auth, config.getUsername(), config.getPassword()); HttpPool.addBasicAuthHeader(auth, config.getUsername(), config.getPassword());
authCode = DaoSerializer.getString(DaoSerializer.parse(pool.executeToString(auth)), "auth_code"); authCode = DaoSerializer.getString(DaoSerializer.parse(pool.executeToString(auth)), "auth_code");
} }
if (NullUtils.isNotEmpty(config.getMqttBrokerUrl())) if (NullUtils.isNotEmpty(config.getMqttBrokerUrl()))
mqttPoster = new MqttPoster(config); mqttPoster = new MqttPoster(config);
if (NullUtils.isNotEmpty(host)) { if (NullUtils.isNotEmpty(host) && NullUtils.isNotEmpty(authCode)) {
while (true) { while (true) {
HttpGet get = new HttpGet(host + "config"); HttpGet get = new HttpGet(host + "config");
get.addHeader("auth_code", authCode); get.addHeader("auth_code", authCode);
@ -209,6 +224,7 @@ public class MonitorApp {
breakerConfig.getBreakerGroups().add(g); breakerConfig.getBreakerGroups().add(g);
} }
} }
if (breakerConfig != null) {
LOG.info("Breaker Config loaded"); LOG.info("Breaker Config loaded");
BreakerHub hub = breakerConfig.getHub(config.getHub()); BreakerHub hub = breakerConfig.getHub(config.getHub());
if (hub != null) { if (hub != null) {
@ -227,6 +243,7 @@ public class MonitorApp {
monitor.monitorPower(hub, breakers, 1000, logger); monitor.monitorPower(hub, breakers, 1000, logger);
} }
monitor.submit(new PowerPoster()); monitor.submit(new PowerPoster());
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
synchronized (running) { synchronized (running) {
running.set(false); running.set(false);

View File

@ -18,33 +18,46 @@ public abstract class NetworkMonitor {
private static final Pattern wifiPattern = Pattern.compile(".*(wlan[0-9]):(.*)"); private static final Pattern wifiPattern = Pattern.compile(".*(wlan[0-9]):(.*)");
public static NetworkStatus getNetworkStatus() { public static NetworkStatus getNetworkStatus() {
NetworkStatus status = new NetworkStatus();
String[] commands = {"ifconfig", "-a"}; String[] commands = {"ifconfig", "-a"};
InputStream is = null; InputStream is = null;
try { try {
is = Runtime.getRuntime().exec(commands).getInputStream(); is = Runtime.getRuntime().exec(commands).getInputStream();
String ifconfig = IOUtils.toString(is); return getNetworkStatus(IOUtils.toString(is));
status.setEthernetIPs(getIPs(ifconfig, ethernetPattern));
status.setWifiIPs(getIPs(ifconfig, wifiPattern));
} }
catch (Exception _e) { catch (Exception _e) {
LOG.error("Failed to check network state", _e); LOG.error("Failed to check network state", _e);
return new NetworkStatus();
} }
finally { finally {
IOUtils.closeQuietly(is); IOUtils.closeQuietly(is);
} }
}
public static NetworkStatus getNetworkStatus(String _ifconfig) {
NetworkStatus status = new NetworkStatus();
status.setEthernetIPs(parseEthernetIp(_ifconfig));
status.setWifiIPs(parseWifiIp(_ifconfig));
return status; return status;
} }
public static List<String> parseWifiIp(String _ifconfig) {
return getIPs(_ifconfig, wifiPattern);
}
public static List<String> parseEthernetIp(String _ifconfig) {
return getIPs(_ifconfig, ethernetPattern);
}
private static List<String> getIPs(String _ifConfig, Pattern _pattern) { private static List<String> getIPs(String _ifConfig, Pattern _pattern) {
List<String> ips = new ArrayList<>(); List<String> ips = new ArrayList<>();
Matcher m = _pattern.matcher(_ifConfig); Matcher m = _pattern.matcher(_ifConfig);
while (m.find()) { while (m.find()) {
int start = m.start(0); int start = m.start(0);
int ipStart = _ifConfig.indexOf("inet ", start) + 5; int ipStart = _ifConfig.indexOf("inet ", start) + 5;
int deviceEnd = _ifConfig.indexOf("\n\n", start);
if (ipStart > 4) { if (ipStart > 4) {
int ipEnd = _ifConfig.indexOf(" ", ipStart); int ipEnd = _ifConfig.indexOf(" ", ipStart);
if (ipEnd > -1) if ((ipEnd > -1) && ((deviceEnd < 0) || (ipEnd <= deviceEnd)))
ips.add(_ifConfig.substring(ipStart, ipEnd)); ips.add(_ifConfig.substring(ipStart, ipEnd));
} }
} }

View File

@ -15,7 +15,9 @@ public enum HubConfigCharacteristic {
AccountId(7, CharacteristicFlag.READ), AccountId(7, CharacteristicFlag.READ),
NetworkState(8, CharacteristicFlag.READ), NetworkState(8, CharacteristicFlag.READ),
Flash(9, CharacteristicFlag.WRITE), Flash(9, CharacteristicFlag.WRITE),
Host(10, CharacteristicFlag.WRITE); Host(10, CharacteristicFlag.WRITE),
Log(11, CharacteristicFlag.READ),
NetworkDetails(12, CharacteristicFlag.READ);
public final int idx; public final int idx;
public final UUID uuid; public final UUID uuid;

View File

@ -1,13 +1,16 @@
package com.lanternsoftware.datamodel.currentmonitor; package com.lanternsoftware.datamodel.currentmonitor;
import com.lanternsoftware.util.CollectionUtils; import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.dao.annotations.DBSerializable;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@DBSerializable
public class NetworkStatus { public class NetworkStatus {
private List<String> wifiIPs; private List<String> wifiIPs;
private List<String> ethernetIPs; private List<String> ethernetIPs;
private boolean pingSuccessful = true;
public List<String> getWifiIPs() { public List<String> getWifiIPs() {
return wifiIPs; return wifiIPs;
@ -25,6 +28,14 @@ public class NetworkStatus {
ethernetIPs = _ethernetIPs; ethernetIPs = _ethernetIPs;
} }
public boolean isPingSuccessful() {
return pingSuccessful;
}
public void setPingSuccessful(boolean _pingSuccessful) {
pingSuccessful = _pingSuccessful;
}
public boolean isWifiConnected() { public boolean isWifiConnected() {
return CollectionUtils.isNotEmpty(wifiIPs); return CollectionUtils.isNotEmpty(wifiIPs);
} }
@ -35,9 +46,9 @@ public class NetworkStatus {
public byte toMask() { public byte toMask() {
EnumSet<NetworkAdapter> adapters = EnumSet.noneOf(NetworkAdapter.class); EnumSet<NetworkAdapter> adapters = EnumSet.noneOf(NetworkAdapter.class);
if (isWifiConnected()) if (isWifiConnected() && isPingSuccessful())
adapters.add(NetworkAdapter.WIFI); adapters.add(NetworkAdapter.WIFI);
if (isEthernetConnected()) if (isEthernetConnected() && isPingSuccessful())
adapters.add(NetworkAdapter.ETHERNET); adapters.add(NetworkAdapter.ETHERNET);
return NetworkAdapter.toMask(adapters); return NetworkAdapter.toMask(adapters);
} }

View File

@ -0,0 +1,44 @@
package com.lanternsoftware.datamodel.currentmonitor.dao;
import com.lanternsoftware.datamodel.currentmonitor.NetworkStatus;
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoProxyType;
import com.lanternsoftware.util.dao.DaoSerializer;
import java.lang.String;
import java.util.Collections;
import java.util.List;
public class NetworkStatusSerializer extends AbstractDaoSerializer<NetworkStatus>
{
@Override
public Class<NetworkStatus> getSupportedClass()
{
return NetworkStatus.class;
}
@Override
public List<DaoProxyType> getSupportedProxies() {
return Collections.singletonList(DaoProxyType.MONGO);
}
@Override
public DaoEntity toDaoEntity(NetworkStatus _o)
{
DaoEntity d = new DaoEntity();
d.put("wifi_ips", _o.getWifiIPs());
d.put("ethernet_ips", _o.getEthernetIPs());
d.put("ping_successful", _o.isPingSuccessful());
return d;
}
@Override
public NetworkStatus fromDaoEntity(DaoEntity _d)
{
NetworkStatus o = new NetworkStatus();
o.setWifiIPs(DaoSerializer.getList(_d, "wifi_ips", String.class));
o.setEthernetIPs(DaoSerializer.getList(_d, "ethernet_ips", String.class));
o.setPingSuccessful(DaoSerializer.getBoolean(_d, "ping_successful"));
return o;
}
}

View File

@ -12,5 +12,6 @@ com.lanternsoftware.datamodel.currentmonitor.dao.BreakerSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer com.lanternsoftware.datamodel.currentmonitor.dao.EnergyBlockSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.HubPowerMinuteSerializer com.lanternsoftware.datamodel.currentmonitor.dao.HubPowerMinuteSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.MeterSerializer com.lanternsoftware.datamodel.currentmonitor.dao.MeterSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.NetworkStatusSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.SequenceSerializer com.lanternsoftware.datamodel.currentmonitor.dao.SequenceSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.SignupResponseSerializer com.lanternsoftware.datamodel.currentmonitor.dao.SignupResponseSerializer