use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.
the class HomeAssistantActionNode method createAction.
@Override
public Action createAction(ActionEnvironment actionEnvironment) {
LatestFragmentedPacketGroupEnvironment latestFragmentedPacketGroupEnvironment = actionEnvironment.getInjectEnvironment().get(LatestFragmentedPacketGroupEnvironment.class);
return Actions.createRunOnce(() -> {
FragmentedPacketGroup packetGroup = latestFragmentedPacketGroupEnvironment.getFragmentedPacketGroupProvider().getPacketGroup();
if (packetGroup == null) {
LOGGER.warn("packetGroup is null!");
return;
}
List<Call<SensorInfo>> calls = new ArrayList<>();
for (Packet packet : packetGroup.getPackets()) {
int fragmentId = packetGroup.getFragmentId(packet);
String sourceId = packetGroup.getSourceId(packet);
String nameBase = "solarthing_" + sourceId + "_" + fragmentId + "_";
if (packet instanceof FXStatusPacket) {
FXStatusPacket fx = (FXStatusPacket) packet;
nameBase += "fx_" + fx.getAddress() + "_";
calls.add(service.updateSensor(nameBase + "acmode", new SensorState(fx.getACMode().getModeName(), new AttributeBuilder().friendlyName("AC Mode").build())));
calls.add(service.updateBinarySensor(nameBase + "acpresent", new BinarySensorState(fx.getACMode() != ACMode.NO_AC, new AttributeBuilder().friendlyName("AC Present").build())));
calls.add(service.updateSensor(nameBase + "batteryvoltage", new SensorState(FORMAT.format(fx.getBatteryVoltage()), new AttributeBuilder().friendlyName("Battery Voltage").build())));
}
}
for (Call<SensorInfo> call : calls) {
try {
// TODO move into a separate thread
Response<SensorInfo> response = call.execute();
if (!response.isSuccessful()) {
LOGGER.error("Unsuccessful response! " + requireNonNull(response.errorBody()).string());
}
} catch (IOException e) {
LOGGER.error("Home assistant error", e);
}
}
});
}
use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.
the class SolarThingGraphQLFXService method queryFXCharging.
@GraphQLQuery(description = "Gives the timer values for the master FX of a single fragment over a time range")
public List<DataNode<FXChargingPacket>> queryFXCharging(@GraphQLArgument(name = "from") long from, @GraphQLArgument(name = "to") long to, @GraphQLArgument(name = "fragmentId") int fragmentId) {
MetaDatabase metaDatabase = simpleQueryHandler.queryMeta();
FXChargingSettingsPacket fxChargingSettingsPacket = null;
FXChargingTemperatureAdjustPacket fxChargingTemperatureAdjustPacket = null;
for (TargetedMetaPacket targetedMetaPacket : metaDatabase.getMeta(to, fragmentId)) {
if (targetedMetaPacket.getPacketType() == TargetedMetaPacketType.FX_CHARGING_SETTINGS) {
fxChargingSettingsPacket = (FXChargingSettingsPacket) targetedMetaPacket;
} else if (targetedMetaPacket.getPacketType() == TargetedMetaPacketType.FX_CHARGING_TEMPERATURE_ADJUST) {
fxChargingTemperatureAdjustPacket = (FXChargingTemperatureAdjustPacket) targetedMetaPacket;
}
}
if (fxChargingSettingsPacket == null) {
throw new UnexpectedResponseException("Could not find FX Charging settings in meta!");
}
// 3 hours back
long startTime = from - 3 * 60 * 60 * 1000;
List<? extends InstancePacketGroup> packets = simpleQueryHandler.queryStatus(startTime, to, null);
// We make masterIdIgnoreDistance null because we will only be using fragmentId as the master fragment ID
Map<String, List<FragmentedPacketGroup>> map = // separate based on source ID
PacketGroups.sortPackets(packets, simpleQueryHandler.getDefaultInstanceOptions(), SolarThingConstants.STANDARD_MAX_TIME_DISTANCE.toMillis(), null, // make fragmentId be the master ID
FragmentUtil.createPriorityComparator(fragmentId));
List<FragmentedPacketGroup> sortedPackets = null;
for (List<FragmentedPacketGroup> fragmentedPacketGroups : map.values()) {
if (fragmentedPacketGroups.get(0).hasFragmentId(fragmentId)) {
sortedPackets = fragmentedPacketGroups;
break;
}
}
if (sortedPackets == null) {
throw new UnexpectedResponseException("Could not find fragment ID: " + fragmentId);
}
FXChargingSettings settings = fxChargingSettingsPacket.getFXChargingSettings();
FXChargingStateHandler stateHandler = new FXChargingStateHandler(settings);
Long lastUpdate = null;
List<DataNode<FXChargingPacket>> r = new ArrayList<>();
for (FragmentedPacketGroup packetGroup : sortedPackets) {
List<FXStatusPacket> fxPackets = new ArrayList<>();
Integer temperature = null;
for (Packet packet : packetGroup.getPackets()) {
if (packet instanceof FXStatusPacket && packetGroup.getFragmentId(packet) == fragmentId) {
fxPackets.add((FXStatusPacket) packet);
} else if (packet instanceof BatteryTemperature) {
temperature = Math.round(((BatteryTemperature) packet).getBatteryTemperatureCelsius().floatValue());
}
}
if (fxPackets.isEmpty()) {
continue;
}
if (temperature == null) {
// we need temperature data for accurate results // TODO add option for systems that don't use temperature compensation
continue;
}
temperature += fxChargingTemperatureAdjustPacket == null ? 0 : fxChargingTemperatureAdjustPacket.getTemperatureAdjustCelsius();
FXStatusPacket fx = OutbackUtil.getMasterFX(fxPackets);
if (fx == null) {
continue;
}
final long delta;
if (lastUpdate == null) {
delta = 1000;
} else {
delta = packetGroup.getDateMillis() - lastUpdate;
}
lastUpdate = packetGroup.getDateMillis();
stateHandler.update(delta, fx, temperature);
FXChargingPacket fxChargingPacket = new ImmutableFXChargingPacket(fx.getIdentifier(), stateHandler.getMode(), stateHandler.getRemainingAbsorbTimeMillis(), stateHandler.getRemainingFloatTimeMillis(), stateHandler.getRemainingEqualizeTimeMillis(), settings.getAbsorbTimeMillis(), settings.getFloatTimeMillis(), settings.getEqualizeTimeMillis());
r.add(new DataNode<>(fxChargingPacket, fx, packetGroup.getDateMillis(), packetGroup.getSourceId(fx), fragmentId));
}
if (r.isEmpty() && !sortedPackets.isEmpty()) {
throw new UnexpectedResponseException("There must have been no FX packets or no rover packets!");
}
return r;
}
use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.
the class DefaultIdentificationCacheCreator method convertPackets.
@SuppressWarnings("unchecked")
private static <T extends Identifiable> Map<String, Map<IdentifierFragment, List<TimestampedPacket<T>>>> convertPackets(List<? extends FragmentedPacketGroup> packetGroups, Class<T> acceptedType) {
Map<String, Map<IdentifierFragment, List<TimestampedPacket<T>>>> r = new HashMap<>();
for (FragmentedPacketGroup packetGroup : packetGroups) {
for (Packet packet : packetGroup.getPackets()) {
if (!acceptedType.isInstance(packet)) {
continue;
}
T identifiablePacket = (T) packet;
String sourceId = packetGroup.getSourceId(packet);
int fragmentId = packetGroup.getFragmentId(packet);
Identifier identifier = identifiablePacket.getIdentifier();
IdentifierFragment identifierFragment = IdentifierFragment.create(fragmentId, identifier);
List<TimestampedPacket<T>> list = r.computeIfAbsent(sourceId, k -> new HashMap<>()).computeIfAbsent(identifierFragment, k -> new ArrayList<>());
long dateMillis = packetGroup.getDateMillisOrKnown(packet);
list.add(new TimestampedPacket<>(identifiablePacket, dateMillis));
}
}
return r;
}
use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.
the class PacketUtil method convertPackets.
/**
* @return A mutable list of packets of a certain type
*/
@SuppressWarnings("unchecked")
public static <T> List<PacketNode<T>> convertPackets(List<? extends FragmentedPacketGroup> packetGroups, Class<T> acceptClass, PacketFilter filter) {
List<PacketNode<T>> r = new ArrayList<>();
for (FragmentedPacketGroup packetGroup : packetGroups) {
for (Packet packet : packetGroup.getPackets()) {
if (!acceptClass.isInstance(packet)) {
continue;
}
int fragmentId = packetGroup.getFragmentId(packet);
String sourceId = packetGroup.getSourceId(packet);
long dateMillis = packetGroup.getDateMillisOrKnown(packet);
PacketNode<T> packetNode = new PacketNode<>((T) packet, dateMillis, sourceId, fragmentId);
if (filter.keep(packetNode)) {
r.add(packetNode);
}
}
}
return r;
}
use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.
the class PVOutputHandler method getStatus.
public AddStatusParameters getStatus(long dayStartTimeMillis, List<FragmentedPacketGroup> packetGroupList) {
FragmentedPacketGroup latestPacketGroup = packetGroupList.get(packetGroupList.size() - 1);
LOGGER.debug("Continuing with the latest packet group. Day start: " + dayStartTimeMillis);
AddStatusParametersBuilder addStatusParametersBuilder = createStatusBuilder(zoneId, latestPacketGroup.getDateMillis());
setStatusPowerValues(addStatusParametersBuilder, latestPacketGroup);
setStatusEnergyValues(addStatusParametersBuilder, packetGroupList, AccumulationConfig.createDefault(dayStartTimeMillis));
for (Packet packet : latestPacketGroup.getPackets()) {
if (packet instanceof PVCurrentAndVoltage) {
int fragmentId = latestPacketGroup.getFragmentId(packet);
PVCurrentAndVoltage pvCurrentAndVoltage = (PVCurrentAndVoltage) packet;
IdentifierFragment identifierFragment = IdentifierFragment.create(fragmentId, pvCurrentAndVoltage.getIdentifier());
if (voltageIdentifierFragmentMatcher.matches(identifierFragment)) {
float voltage = pvCurrentAndVoltage.getPVVoltage().floatValue();
addStatusParametersBuilder.setVoltage(voltage);
}
} else if (packet instanceof TemperaturePacket) {
int fragmentId = latestPacketGroup.getFragmentId(packet);
TemperaturePacket temperaturePacket = (TemperaturePacket) packet;
IdentifierFragment identifierFragment = IdentifierFragment.create(fragmentId, temperaturePacket.getIdentifier());
if (temperatureIdentifierFragmentMatcher.matches(identifierFragment)) {
float temperatureCelsius = temperaturePacket.getTemperatureCelsius();
if (!TemperaturePacket.POSSIBLE_BAD_VALUES.contains(temperatureCelsius)) {
addStatusParametersBuilder.setTemperatureCelsius(temperatureCelsius);
} else {
LOGGER.info("Not setting temperature: " + temperatureCelsius + " because it could be a bad reading");
}
}
}
}
return addStatusParametersBuilder.build();
}
Aggregations