Search in sources :

Example 11 with FragmentedPacketGroup

use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.

the class DeserializeTest method testRunAlertGeneratorOffWhileAuxOn.

@Test
void testRunAlertGeneratorOffWhileAuxOn() throws IOException, ParsePacketAsciiDecimalDigitException, CheckSumException {
    File file = new File(ACTION_CONFIG_DIRECTORY, "alert_generator_off_while_aux_on.json");
    ActionNode actionNode = MAPPER.readValue(file, ActionNode.class);
    // We need to simulate an automation program environment to run this action
    Duration[] timeReference = new Duration[] { Duration.ZERO };
    FragmentedPacketGroup[] packetGroupReference = new FragmentedPacketGroup[] { null };
    FragmentedPacketGroupProvider fragmentedPacketGroupProvider = () -> requireNonNull(packetGroupReference[0]);
    InjectEnvironment injectEnvironment = new InjectEnvironment.Builder().add(new NanoTimeProviderEnvironment(() -> timeReference[0].toNanos())).add(new LatestPacketGroupEnvironment(fragmentedPacketGroupProvider)).add(new LatestFragmentedPacketGroupEnvironment(fragmentedPacketGroupProvider)).build();
    FXStatusPacket auxOnNoAC = FXStatusPackets.createFromChars("\n1,00,00,02,123,123,00,10,000,00,252,136,000,999\r".toCharArray(), IgnoreCheckSum.IGNORE);
    FXStatusPacket auxOffNoAC = FXStatusPackets.createFromChars("\n1,00,00,02,123,123,00,10,000,00,252,008,000,999\r".toCharArray(), IgnoreCheckSum.IGNORE);
    FXStatusPacket auxOnACUse = FXStatusPackets.createFromChars("\n1,00,00,02,123,123,00,10,000,02,252,136,000,999\r".toCharArray(), IgnoreCheckSum.IGNORE);
    FXStatusPacket auxOffACUse = FXStatusPackets.createFromChars("\n1,00,00,02,123,123,00,10,000,02,252,008,000,999\r".toCharArray(), IgnoreCheckSum.IGNORE);
    for (FXStatusPacket packet : new FXStatusPacket[] { auxOffNoAC, auxOnACUse, auxOffACUse }) {
        // for these three cases, the action should end immediately
        packetGroupReference[0] = PacketGroups.createInstancePacketGroup(Collections.singleton(packet), 0L, "my_source_id", 999);
        Action action = actionNode.createAction(new ActionEnvironment(new VariableEnvironment(), new VariableEnvironment(), injectEnvironment));
        action.update();
        assertTrue(action.isDone());
    }
    {
        // Test that no alert is sent unless the aux is on, and it's in No AC for 30 seconds
        packetGroupReference[0] = PacketGroups.createInstancePacketGroup(Collections.singleton(auxOnNoAC), 0L, "my_source_id", 999);
        Action action = actionNode.createAction(new ActionEnvironment(new VariableEnvironment(), new VariableEnvironment(), injectEnvironment));
        action.update();
        assertFalse(action.isDone());
        timeReference[0] = timeReference[0].plus(Duration.ofSeconds(29));
        action.update();
        assertFalse(action.isDone());
        packetGroupReference[0] = PacketGroups.createInstancePacketGroup(Collections.singleton(auxOnACUse), 0L, "my_source_id", 999);
        action.update();
        // No alert has been sent, since it started to AC Use before the 30 second period completed.
        assertTrue(action.isDone());
    }
    {
        // Test that the alert gets sent and the action doesn't end until the 300-second timeout completes
        packetGroupReference[0] = PacketGroups.createInstancePacketGroup(Collections.singleton(auxOnNoAC), 0L, "my_source_id", 999);
        Action action = actionNode.createAction(new ActionEnvironment(new VariableEnvironment(), new VariableEnvironment(), injectEnvironment));
        action.update();
        assertFalse(action.isDone());
        timeReference[0] = timeReference[0].plus(Duration.ofSeconds(30));
        action.update();
        assertFalse(action.isDone());
        packetGroupReference[0] = PacketGroups.createInstancePacketGroup(Collections.singleton(auxOnACUse), 0L, "my_source_id", 999);
        action.update();
        // Alert has been sent, so the action isn't going to end
        assertFalse(action.isDone());
        timeReference[0] = timeReference[0].plus(Duration.ofSeconds(299));
        action.update();
        assertFalse(action.isDone());
        timeReference[0] = timeReference[0].plus(Duration.ofSeconds(1));
        action.update();
        // the 300-second timeout has completed, so the action will end
        assertTrue(action.isDone());
    }
}
Also used : FragmentedPacketGroup(me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup) ActionEnvironment(me.retrodaredevil.action.node.environment.ActionEnvironment) Action(me.retrodaredevil.action.Action) NanoTimeProviderEnvironment(me.retrodaredevil.action.node.environment.NanoTimeProviderEnvironment) LatestPacketGroupEnvironment(me.retrodaredevil.solarthing.actions.environment.LatestPacketGroupEnvironment) SerialConfigBuilder(me.retrodaredevil.io.serial.SerialConfigBuilder) ActionNode(me.retrodaredevil.action.node.ActionNode) Duration(java.time.Duration) FragmentedPacketGroupProvider(me.retrodaredevil.solarthing.FragmentedPacketGroupProvider) InjectEnvironment(me.retrodaredevil.action.node.environment.InjectEnvironment) LatestFragmentedPacketGroupEnvironment(me.retrodaredevil.solarthing.actions.environment.LatestFragmentedPacketGroupEnvironment) FXStatusPacket(me.retrodaredevil.solarthing.solar.outback.fx.FXStatusPacket) VariableEnvironment(me.retrodaredevil.action.node.environment.VariableEnvironment) File(java.io.File) Test(org.junit.jupiter.api.Test)

Example 12 with FragmentedPacketGroup

use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.

the class PVOutputUploadMain method startRangeUpload.

private static int startRangeUpload(SimpleDate fromDate, SimpleDate toDate, PVOutputUploadProgramOptions options, SolarThingDatabase database, PVOutputHandler handler, PVOutputService service, ZoneId zoneId) {
    List<AddOutputParameters> addOutputParameters = new ArrayList<>();
    SimpleDate date = fromDate;
    while (date.compareTo(toDate) <= 0) {
        System.out.println("Doing " + date);
        SimpleDate tomorrow = date.tomorrow();
        long dayStart = date.getDayStartDateMillis(zoneId);
        long dayEnd = tomorrow.getDayStartDateMillis(zoneId);
        List<? extends PacketGroup> rawPacketGroups = null;
        try {
            rawPacketGroups = database.getStatusDatabase().query(new MillisQueryBuilder().startKey(dayStart).endKey(dayEnd).inclusiveEnd(false).build());
            System.out.println("Got " + rawPacketGroups.size() + " packets for date: " + date.toPVOutputString());
        } catch (SolarThingDatabaseException e) {
            e.printStackTrace();
            System.err.println("Couldn't query packets. Skipping " + date.toPVOutputString());
        }
        if (rawPacketGroups != null) {
            List<FragmentedPacketGroup> packetGroups = PacketUtil.getPacketGroups(options.getSourceId(), options.getDefaultInstanceOptions(), rawPacketGroups);
            if (packetGroups != null) {
                if (!handler.checkPackets(dayStart, packetGroups)) {
                    System.err.println("Unsuccessfully checked packets for " + date.toPVOutputString());
                    try {
                        System.out.println(MAPPER.writeValueAsString(packetGroups.get(packetGroups.size() - 1)));
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
                } else {
                    AddStatusParameters statusParameters = handler.getStatus(dayStart, packetGroups);
                    AddOutputParametersBuilder outputParametersBuilder = new AddOutputParametersBuilder(statusParameters.getDate()).setGenerated(statusParameters.getEnergyGeneration()).setConsumption(statusParameters.getEnergyConsumption());
                    PVOutputHandler.setImportedExported(outputParametersBuilder, packetGroups, AccumulationConfig.createDefault(dayStart), options.isIncludeImport(), options.isIncludeExport());
                    AddOutputParameters outputParameters = outputParametersBuilder.build();
                    addOutputParameters.add(outputParameters);
                    System.out.println("Added parameters for " + date.toPVOutputString() + " to queue.");
                    System.out.println("Generated: " + statusParameters.getEnergyGeneration());
                    System.out.println(Arrays.toString(outputParameters.toCsvArray()));
                    System.out.println(CsvUtil.toCsvString(outputParameters.toCsvArray()));
                }
            } else {
                System.err.println("Didn't find any packets with source: " + options.getSourceId() + " for date: " + date.toPVOutputString());
            }
        }
        date = tomorrow;
    }
    System.out.println("Going to upload in batches of 30...");
    for (int i = 0; i < addOutputParameters.size(); i += 30) {
        if (i != 0) {
            System.out.println("Sleeping...");
            try {
                // noinspection BusyWait
                Thread.sleep(7000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Interrupted");
                return SolarThingConstants.EXIT_CODE_INTERRUPTED;
            }
        }
        int endIndex = Math.min(i + 30, addOutputParameters.size());
        List<AddOutputParameters> parameters = addOutputParameters.subList(i, endIndex);
        System.out.println("Going to upload from " + parameters.get(0).getOutputDate().toPVOutputString() + " to " + parameters.get(parameters.size() - 1).getOutputDate().toPVOutputString());
        AddBatchOutputParameters batchOutputParameters = new ImmutableAddBatchOutputParameters(parameters);
        try {
            LOGGER.debug("Batch Output parameters as JSON: " + MAPPER.writeValueAsString(batchOutputParameters));
        } catch (JsonProcessingException e) {
            LOGGER.error("Got error serializing JSON. This should never happen.", e);
        }
        boolean successful = false;
        for (int j = 0; j < 5; j++) {
            if (j != 0) {
                System.out.println("Sleeping before trying again");
                try {
                    // noinspection BusyWait
                    Thread.sleep(j * 7000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    System.err.println("Interrupted");
                    return SolarThingConstants.EXIT_CODE_INTERRUPTED;
                }
            }
            Call<String> call = service.addBatchOutput(batchOutputParameters);
            final Response<String> response;
            try {
                response = call.execute();
            } catch (IOException e) {
                e.printStackTrace();
                System.err.println("Error while executing");
                continue;
            }
            if (response.isSuccessful()) {
                System.out.println("Executed successfully. Result: " + response.body());
                successful = true;
                break;
            } else {
                System.err.println("Unsuccessful. Message: " + response.message() + " code: " + response.code());
            }
        }
        if (!successful) {
            System.err.println("All tries were unsuccessful. Ending");
            return SolarThingConstants.EXIT_CODE_FAIL;
        }
    }
    System.out.println("Done!");
    return 0;
}
Also used : FragmentedPacketGroup(me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup) MillisQueryBuilder(me.retrodaredevil.solarthing.database.MillisQueryBuilder) IOException(java.io.IOException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) SimpleDate(me.retrodaredevil.solarthing.pvoutput.SimpleDate) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Example 13 with FragmentedPacketGroup

use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.

the class PVOutputUploadMain method startRealTimeProgram.

private static int startRealTimeProgram(PVOutputUploadProgramOptions options, SolarThingDatabase database, PVOutputHandler handler, PVOutputService service, ZoneId zoneId) {
    if (options.isJoinTeams()) {
        LOGGER.info("Going to join SolarThing team...");
        Call<String> call = service.joinTeam(PVOutputConstants.SOLARTHING_TEAM_ID);
        LOGGER.debug("Executing call");
        Response<String> response = null;
        try {
            response = call.execute();
        } catch (IOException e) {
            LOGGER.error("Exception while executing", e);
        }
        if (response != null) {
            int code = response.code();
            String errorBody;
            try {
                ResponseBody responseBody = response.errorBody();
                if (responseBody != null) {
                    errorBody = responseBody.string();
                } else {
                    errorBody = "null";
                }
            } catch (IOException e) {
                e.printStackTrace();
                errorBody = "exception occurred";
            }
            if (code == 200) {
                LOGGER.info("Joined the SolarThing team! Response: " + response.body());
            } else if (code == 400) {
                if (errorBody.contains("already")) {
                    LOGGER.info("Already joined SolarThing team. Response: " + errorBody);
                } else if (errorBody.contains("must have at least")) {
                    LOGGER.info("We will try joining SolarThing team later once we have more outputs. Response: " + errorBody);
                } else {
                    LOGGER.error("Error joining SolarThing team! Response: " + errorBody);
                }
            } else {
                LOGGER.error("Unknown error joining SolarThing team! Response: " + errorBody);
            }
        }
    }
    while (!Thread.currentThread().isInterrupted()) {
        LOGGER.debug("Going to do stuff now.");
        long now = System.currentTimeMillis();
        SimpleDate today = SimpleDate.fromDateMillis(now, zoneId);
        long dayStartTimeMillis = today.getDayStartDateMillis(zoneId);
        List<? extends PacketGroup> rawPacketGroups = null;
        try {
            rawPacketGroups = database.getStatusDatabase().query(new MillisQueryBuilder().startKey(dayStartTimeMillis).endKey(now).build());
            LOGGER.debug("Got packets");
        } catch (SolarThingDatabaseException e) {
            LOGGER.error("Couldn't get status packets", e);
        }
        if (rawPacketGroups != null) {
            List<FragmentedPacketGroup> packetGroups = PacketUtil.getPacketGroups(options.getSourceId(), options.getDefaultInstanceOptions(), rawPacketGroups);
            if (packetGroups != null) {
                FragmentedPacketGroup latestPacketGroup = packetGroups.get(packetGroups.size() - 1);
                if (latestPacketGroup.getDateMillis() < now - 5 * 60 * 1000) {
                    LOGGER.warn("The last packet is more than 5 minutes in the past! now=" + now + " packet date=" + latestPacketGroup.getDateMillis());
                    try {
                        LOGGER.debug("Packets: " + MAPPER.writeValueAsString(latestPacketGroup.getPackets()));
                    } catch (JsonProcessingException e) {
                        LOGGER.warn("Couldn't serialize for some reason", e);
                    }
                } else if (!handler.checkPackets(dayStartTimeMillis, packetGroups)) {
                    LOGGER.warn("Checking packets unsuccessful.");
                } else {
                    AddStatusParameters parameters = handler.getStatus(dayStartTimeMillis, packetGroups);
                    if (uploadStatus(service, parameters) && (options.isIncludeImport() || options.isIncludeExport())) {
                        // only upload output if status is successful
                        AddOutputParametersBuilder outputParametersBuilder = new AddOutputParametersBuilder(parameters.getDate());
                        PVOutputHandler.setImportedExported(outputParametersBuilder, packetGroups, AccumulationConfig.createDefault(dayStartTimeMillis), options.isIncludeImport(), options.isIncludeExport());
                        AddOutputParameters outputParameters = outputParametersBuilder.build();
                        uploadOutput(service, outputParameters);
                    }
                }
            } else {
                LOGGER.warn("Got " + rawPacketGroups.size() + " packets but, there must not have been any packets with the source: " + options.getSourceId());
            }
        }
        LOGGER.debug("Going to sleep now");
        try {
            // noinspection BusyWait
            Thread.sleep(5 * 60 * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    return SolarThingConstants.EXIT_CODE_INTERRUPTED;
}
Also used : FragmentedPacketGroup(me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup) MillisQueryBuilder(me.retrodaredevil.solarthing.database.MillisQueryBuilder) IOException(java.io.IOException) ResponseBody(okhttp3.ResponseBody) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) SimpleDate(me.retrodaredevil.solarthing.pvoutput.SimpleDate) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Example 14 with FragmentedPacketGroup

use of me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup in project solarthing by wildmountainfarms.

the class StatusChatBotHandler method handleMessage.

@Override
public boolean handleMessage(Message message, MessageSender messageSender) {
    if (ChatBotUtil.isSimilar("battery voltage", message.getText())) {
        FragmentedPacketGroup packetGroup = packetGroupProvider.getPacketGroup();
        Float batteryVoltageAverage = BatteryUtil.getBatteryVoltageAverage(packetGroup);
        if (batteryVoltageAverage == null) {
            messageSender.sendMessage("Battery voltage unavailable from latest data. Sorry!");
        } else {
            messageSender.sendMessage("Battery voltage: " + Formatting.HUNDREDTHS_FORMAT.format(batteryVoltageAverage));
        }
        return true;
    } else if (ChatBotUtil.isSimilar("battery temperature", message.getText()) || ChatBotUtil.isSimilar("battery temp", message.getText())) {
        FragmentedPacketGroup packetGroup = packetGroupProvider.getPacketGroup();
        List<String> lines = new ArrayList<>();
        for (Packet packet : packetGroup.getPackets()) {
            int fragmentId = packetGroup.getFragmentId(packet);
            if (packet instanceof BatteryTemperature && packet instanceof Identifiable) {
                float temperature = ((BatteryTemperature) packet).getBatteryTemperatureFahrenheit();
                IdentityInfo identityInfo = ((Identifiable) packet).getIdentityInfo();
                lines.add(identityInfo.getDisplayName() + " (" + fragmentId + "): " + temperature + "F");
            }
        }
        if (lines.isEmpty()) {
            messageSender.sendMessage("No devices to read temperature!");
        } else {
            messageSender.sendMessage(String.join("\n", lines));
        }
        return true;
    } else if (ChatBotUtil.isSimilar("alter", message.getText())) {
        List<VersionedPacket<StoredAlterPacket>> alterPackets = alterPacketsProvider.getPackets();
        if (alterPackets == null) {
            messageSender.sendMessage("Error - Must have failed to query alter database");
        } else {
            List<String> scheduledCommandLines = new ArrayList<>();
            for (VersionedPacket<StoredAlterPacket> versionedPacket : alterPackets) {
                StoredAlterPacket storedAlterPacket = versionedPacket.getPacket();
                AlterPacket alterPacket = storedAlterPacket.getPacket();
                if (alterPacket instanceof ScheduledCommandPacket) {
                    ScheduledCommandData data = ((ScheduledCommandPacket) alterPacket).getData();
                    // ExecutionReason executionReason = ((ScheduledCommandPacket) alterPacket).getExecutionReason();
                    String timeString = TimeUtil.instantToSlackDateSeconds(Instant.ofEpochMilli(data.getScheduledTimeMillis()));
                    scheduledCommandLines.add(data.getCommandName() + " - " + timeString);
                }
            }
            if (scheduledCommandLines.isEmpty()) {
                messageSender.sendMessage("No scheduled commands (from " + alterPackets.size() + " alter packets)");
            } else {
                messageSender.sendMessage("Scheduled commands:\n\t" + String.join("\n\t", scheduledCommandLines));
            }
        }
        return true;
    }
    return false;
}
Also used : FragmentedPacketGroup(me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup) Packet(me.retrodaredevil.solarthing.packets.Packet) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) StoredAlterPacket(me.retrodaredevil.solarthing.type.alter.StoredAlterPacket) AlterPacket(me.retrodaredevil.solarthing.type.alter.AlterPacket) ScheduledCommandPacket(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandPacket) BatteryTemperature(me.retrodaredevil.solarthing.solar.common.BatteryTemperature) StoredAlterPacket(me.retrodaredevil.solarthing.type.alter.StoredAlterPacket) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) ArrayList(java.util.ArrayList) StoredAlterPacket(me.retrodaredevil.solarthing.type.alter.StoredAlterPacket) AlterPacket(me.retrodaredevil.solarthing.type.alter.AlterPacket) Identifiable(me.retrodaredevil.solarthing.packets.identification.Identifiable) ScheduledCommandPacket(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandPacket) IdentityInfo(me.retrodaredevil.solarthing.packets.identification.IdentityInfo) ArrayList(java.util.ArrayList) List(java.util.List) ScheduledCommandData(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData)

Aggregations

FragmentedPacketGroup (me.retrodaredevil.solarthing.packets.collection.FragmentedPacketGroup)14 Packet (me.retrodaredevil.solarthing.packets.Packet)7 ArrayList (java.util.ArrayList)6 LatestFragmentedPacketGroupEnvironment (me.retrodaredevil.solarthing.actions.environment.LatestFragmentedPacketGroupEnvironment)5 IOException (java.io.IOException)4 List (java.util.List)4 SolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)3 IdentifierFragment (me.retrodaredevil.solarthing.packets.identification.IdentifierFragment)3 FXStatusPacket (me.retrodaredevil.solarthing.solar.outback.fx.FXStatusPacket)3 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)2 Duration (java.time.Duration)2 SimpleAction (me.retrodaredevil.action.SimpleAction)2 ActionNode (me.retrodaredevil.action.node.ActionNode)2 ActionEnvironment (me.retrodaredevil.action.node.environment.ActionEnvironment)2 InjectEnvironment (me.retrodaredevil.action.node.environment.InjectEnvironment)2 NanoTimeProviderEnvironment (me.retrodaredevil.action.node.environment.NanoTimeProviderEnvironment)2 VariableEnvironment (me.retrodaredevil.action.node.environment.VariableEnvironment)2 FragmentedPacketGroupProvider (me.retrodaredevil.solarthing.FragmentedPacketGroupProvider)2 MillisQueryBuilder (me.retrodaredevil.solarthing.database.MillisQueryBuilder)2 TimestampedPacket (me.retrodaredevil.solarthing.packets.TimestampedPacket)2