use of me.retrodaredevil.solarthing.packets.Packet in project solarthing by wildmountainfarms.
the class FXEventUpdaterListReceiver method receive.
@Override
public void receive(List<Packet> packets) {
for (Packet packet : packets) {
if (packet instanceof FXStatusPacket) {
FXStatusPacket fx = (FXStatusPacket) packet;
FXStatusPacket previous = previousPacketMap.get(fx.getIdentifier());
previousPacketMap.put(fx.getIdentifier(), fx);
Integer warningIgnoreValue = fxWarningIgnoreMap.get(fx.getAddress());
useData(fx, previous, warningIgnoreValue == null ? FXWarningModeChangePacket.DEFAULT_IGNORED_WARNING_MODE_VALUE_CONSTANT : warningIgnoreValue);
}
}
}
use of me.retrodaredevil.solarthing.packets.Packet in project solarthing by wildmountainfarms.
the class AlterManagerAction method isDocumentMadeByUs.
private boolean isDocumentMadeByUs(Instant now, ScheduledCommandData scheduledCommandData, StoredPacketGroup existingDocument) {
LargeIntegrityPacket largeIntegrityPacket = (LargeIntegrityPacket) existingDocument.getPackets().stream().filter(p -> p instanceof LargeIntegrityPacket).findAny().orElse(null);
if (largeIntegrityPacket == null) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "The stored document did not have a LargeIntegrity packet. Someone must be trying to stop a scheduled command!");
return false;
}
String sender = largeIntegrityPacket.getSender();
if (!commandManager.getSender().equals(sender)) {
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "The sender of the large integrity packet we are inspecting is not us (" + commandManager.getSender() + "). It is " + sender + ". Might be a malicious actor, might be a bad setup.");
return false;
}
String encryptedHash = largeIntegrityPacket.getEncryptedHash();
String data;
try {
synchronized (CIPHER) {
data = Decrypt.decrypt(CIPHER, commandManager.getKeyPair().getPublic(), encryptedHash);
}
} catch (InvalidKeyException e) {
throw new RuntimeException("Should be a valid key!", e);
} catch (DecryptException e) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "The document we are inspecting had a large integrity packet with the sender: " + sender + ", but that's us and we couldn't decrypt their payload. Likely a malicious actor", e);
return false;
}
final String[] split = data.split(",", 2);
LOGGER.debug("decrypted data: " + data);
if (split.length != 2) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "split.length: " + split.length + " split: " + Arrays.asList(split));
return false;
}
String hexMillis = split[0];
// String message = split[1]; We don't care what the message is. We don't even care enough to check if it matches the payload's hash
long dateMillis;
try {
dateMillis = Long.parseLong(hexMillis, 16);
} catch (NumberFormatException e) {
LOGGER.error(SolarThingConstants.SUMMARY_MARKER, "Error parsing hex date millis", e);
return false;
}
if (dateMillis < scheduledCommandData.getScheduledTimeMillis()) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "The dateMillis for this is less than the command's scheduled execution time! This must be a malicious actor!");
return false;
}
if (dateMillis > now.toEpochMilli()) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "The dateMillis for this is greater than now! This should never ever happen.");
return false;
}
return true;
}
use of me.retrodaredevil.solarthing.packets.Packet in project solarthing by wildmountainfarms.
the class AlterManagerAction method receivePacketWithIntegrity.
private void receivePacketWithIntegrity(String sender, TargetPacketGroup packetGroup) {
LOGGER.debug("Sender: " + sender + " is authorized and sent a packet targeting no fragments, so we will see if we want to handle anything from it.");
long now = System.currentTimeMillis();
List<StoredAlterPacket> storedAlterPacketsToUpload = new ArrayList<>();
List<DeleteAlterPacket> deleteAlterPackets = new ArrayList<>();
for (Packet packet : packetGroup.getPackets()) {
if (packet instanceof ScheduleCommandPacket) {
ScheduleCommandPacket scheduleCommandPacket = (ScheduleCommandPacket) packet;
ScheduledCommandData data = scheduleCommandPacket.getData();
ExecutionReason executionReason = new OpenSourceExecutionReason(new OpenSource(sender, packetGroup.getDateMillis(), scheduleCommandPacket, // this is legacy data and shouldn't be used anywhere, so it doesn't matter what we put here
scheduleCommandPacket.getUniqueString()));
ScheduledCommandPacket scheduledCommandPacket = new ScheduledCommandPacket(data, executionReason);
// This databaseId is basically an arbitrary way to generate a unique ID. It contains some stuff such as the command name to debug more easily
String databaseId = "alter-scheduled-command-" + data.getCommandName() + "-" + Long.toHexString(data.getScheduledTimeMillis()) + "-" + sender + "-" + Math.random();
StoredAlterPacket storedAlterPacket = new ImmutableStoredAlterPacket(databaseId, now, scheduledCommandPacket, this.sourceId);
storedAlterPacketsToUpload.add(storedAlterPacket);
} else if (packet instanceof DeleteAlterPacket) {
DeleteAlterPacket deleteAlterPacket = (DeleteAlterPacket) packet;
try {
database.validateUpdateToken(deleteAlterPacket.getUpdateToken());
deleteAlterPackets.add(deleteAlterPacket);
} catch (IncompatibleUpdateTokenException ex) {
LOGGER.error(SolarThingConstants.SUMMARY_MARKER, "For some reason we have an incompatible update token!", ex);
}
} else if (packet instanceof RequestFlagPacket) {
RequestFlagPacket requestFlagPacket = (RequestFlagPacket) packet;
// Originally I was going to not upload a FlagPacket if an existing FlagPacket's
// time range fully encapsulated the newly requested one, but that adds some complexity
// that is not needed at the moment
FlagData flagData = requestFlagPacket.getFlagData();
ExecutionReason executionReason = new OpenSourceExecutionReason(new OpenSource(sender, packetGroup.getDateMillis(), requestFlagPacket, // this is legacy data and shouldn't be used anywhere, so it doesn't matter what we put here
requestFlagPacket.getUniqueString()));
FlagPacket flagPacket = new FlagPacket(flagData, executionReason);
String databaseId = "alter-flag-" + flagData.getFlagName() + "-" + sender + "-" + Math.random();
StoredAlterPacket storedAlterPacket = new ImmutableStoredAlterPacket(databaseId, now, flagPacket, sourceId);
storedAlterPacketsToUpload.add(storedAlterPacket);
}
}
if (storedAlterPacketsToUpload.isEmpty() && deleteAlterPackets.isEmpty()) {
// Nothing for us to do, so no need to schedule a runnable
return;
}
executorService.execute(() -> {
int uploadCount = 0;
try {
for (StoredAlterPacket storedAlterPacket : storedAlterPacketsToUpload) {
this.database.getAlterDatabase().upload(storedAlterPacket);
uploadCount++;
}
} catch (SolarThingDatabaseException e) {
// TODO in future we should try multiple times to upload
LOGGER.error(SolarThingConstants.SUMMARY_MARKER, "Could not upload a stored alter packet! uploaded: " + uploadCount + " / " + storedAlterPacketsToUpload.size(), e);
}
int deleteCount = 0;
try {
for (DeleteAlterPacket deleteAlterPacket : deleteAlterPackets) {
this.database.getAlterDatabase().delete(deleteAlterPacket.getDocumentIdToDelete(), deleteAlterPacket.getUpdateToken());
deleteCount++;
}
} catch (SolarThingDatabaseException e) {
LOGGER.error(SolarThingConstants.SUMMARY_MARKER, "Could not delete alter packets! deleted: " + deleteCount + " / " + deleteAlterPackets.size(), e);
}
});
}
use of me.retrodaredevil.solarthing.packets.Packet in project solarthing by wildmountainfarms.
the class MXEventUpdaterListReceiver method useData.
private void useData(MXStatusPacket mx, MXStatusPacket last) {
final Integer previousChargerModeValue;
final Integer previousRawAuxModeValue;
final Integer previousErrorModeValue;
if (last == null) {
previousChargerModeValue = null;
previousRawAuxModeValue = null;
previousErrorModeValue = null;
} else {
previousChargerModeValue = last.getChargerModeValue();
previousRawAuxModeValue = last.getRawAuxModeValue();
previousErrorModeValue = last.getErrorModeValue();
}
int chargerModeValue = mx.getChargerModeValue();
int rawAuxModeValue = mx.getRawAuxModeValue();
int errorModeValue = mx.getErrorModeValue();
List<Packet> eventPackets = new ArrayList<>();
if (previousChargerModeValue == null || chargerModeValue != previousChargerModeValue) {
eventPackets.add(new ImmutableMXChargerModeChangePacket(mx.getIdentifier(), chargerModeValue, previousChargerModeValue));
}
if (previousRawAuxModeValue == null || rawAuxModeValue != previousRawAuxModeValue) {
eventPackets.add(new ImmutableMXAuxModeChangePacket(mx.getIdentifier(), rawAuxModeValue, previousRawAuxModeValue));
}
if (previousErrorModeValue == null || errorModeValue != previousErrorModeValue) {
eventPackets.add(new ImmutableMXErrorModeChangePacket(mx.getIdentifier(), errorModeValue, previousErrorModeValue));
}
if (last != null && mx.isNewDay(last)) {
eventPackets.add(new ImmutableMXRawDayEndPacket(mx.getAddress(), mx.getDailyKWH(), mx.getDailyAH(), mx.getDailyAHSupport()));
}
if (!eventPackets.isEmpty()) {
eventReceiver.receive(eventPackets);
}
}
use of me.retrodaredevil.solarthing.packets.Packet in project solarthing by wildmountainfarms.
the class MXEventUpdaterListReceiver method receive.
@Override
public void receive(List<Packet> packets) {
for (Packet packet : packets) {
if (packet instanceof MXStatusPacket) {
MXStatusPacket mx = (MXStatusPacket) packet;
MXStatusPacket previous = previousPacketMap.get(mx.getIdentifier());
previousPacketMap.put(mx.getIdentifier(), mx);
useData(mx, previous);
}
}
}
Aggregations