org.bensteele.jirrigate.Console.java Source code

Java tutorial

Introduction

Here is the source code for org.bensteele.jirrigate.Console.java

Source

package org.bensteele.jirrigate;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;
import java.util.TreeSet;

import jline.console.ConsoleReader;
import jline.console.completer.Completer;
import jline.console.completer.StringsCompleter;

import org.apache.commons.lang.ArrayUtils;
import org.bensteele.jirrigate.controller.Controller;
import org.bensteele.jirrigate.controller.IrrigationResult;
import org.bensteele.jirrigate.controller.zone.Zone;
import org.bensteele.jirrigate.weather.WeatherStation;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * A simple class to provide an interactive console/shell to jirrigate using jline2.
 * 
 * @author Ben Steele (ben@bensteele.org)
 */
public class Console {

    private final Irrigator irrigator;
    private final Set<String> commands = new TreeSet<String>();
    private final ConsoleReader reader;

    private Completer completer = new StringsCompleter();

    public Console(Irrigator irrigator) throws IOException {
        this.irrigator = irrigator;
        this.reader = new ConsoleReader();
    }

    private void activateController(String input) {
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                System.out.print("Activating " + c.getName() + ": ");
                c.setActive(true);
                System.out.println("OK");
            }
        }
    }

    private void activateWeatherStation(String input) {
        for (WeatherStation ws : irrigator.getWeatherStations()) {
            if (input.toLowerCase().contains(ws.getName().toLowerCase())) {
                System.out.print("Activating " + ws.getName() + ": ");
                ws.setActive(true);
                System.out.println("OK");
            }
        }
    }

    private void deactivateController(String input) {
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                System.out.print("Deactivating " + c.getName() + ": ");
                c.setActive(false);
                System.out.println("OK");
            }
        }
    }

    private void deactivateWeatherStation(String input) {
        for (WeatherStation ws : irrigator.getWeatherStations()) {
            if (input.toLowerCase().contains(ws.getName().toLowerCase())) {
                System.out.print("Deactivating " + ws.getName() + ": ");
                ws.setActive(false);
                System.out.println("OK");
            }
        }
    }

    private void printControllerInfo(String input) {
        System.out.format("%-25s%-20s%-20s%-10s%-15s%-15s%-10s\n", "Controller", "Type", "IP", "Port", "Username",
                "Password", "# Zones");
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                System.out.format("%-25s%-20s%-20s%-10s%-15s%-15s%-10s\n", c.getName(), c.getControllerType(),
                        c.getIpAddress().getHostAddress(), c.getPort(), c.getUsername(), c.getPassword(),
                        c.getZones().size());
            }
        }
    }

    private void printControllerInfoAll(String input) {
        System.out.format("%-25s%-20s%-20s%-10s%-15s%-15s%-10s\n", "Controller", "Type", "IP", "Port", "Username",
                "Password", "# Zones");
        for (Controller c : irrigator.getControllers()) {
            System.out.format("%-25s%-20s%-20s%-10s%-15s%-15s%-10s\n", c.getName(), c.getControllerType(),
                    c.getIpAddress().getHostAddress(), c.getPort(), c.getUsername(), c.getPassword(),
                    c.getZones().size());
        }
    }

    private void printControllerStatus(String input) {
        DateTimeFormatter statusFormatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm");
        System.out.format("%-25s%-20s%-25s%-10s%-15s%-28s\n", "Controller", "Status", "Currently Irrigating",
                "Active", "# Irrigations", "Next Irrigation Due");
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                System.out.format("%-25s%-20s%-25s%-10s%-15s%-28s\n", c.getName(), c.getStatus(), c.isIrrigating(),
                        c.isActive(), c.getIrrigationResults().size(),
                        statusFormatter.print(irrigator.nextIrrigationAt()));
            }
        }
    }

    private void printControllerStatusAll(String input) {
        DateTimeFormatter statusFormatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm");
        System.out.format("%-25s%-20s%-25s%-10s%-15s%-28s\n", "Controller", "Status", "Currently Irrigating",
                "Active", "# Irrigations", "Next Irrigation Due");
        for (Controller c : irrigator.getControllers()) {
            System.out.format("%-25s%-20s%-25s%-10s%-15s%-28s\n", c.getName(), c.getStatus(), c.isIrrigating(),
                    c.isActive(), c.getIrrigationResults().size(),
                    statusFormatter.print(irrigator.nextIrrigationAt()));
        }
    }

    private void printControllerZones(String input) {
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                System.out.format("%-30s%-6s%-6s\n", "Name", "Id", "Duration");
                for (Zone z : c.getZones()) {
                    String durationAmount = "";
                    if (z.getDuration() < 60) {
                        durationAmount = z.getDuration() + "s";
                    } else {
                        durationAmount = (z.getDuration() / 60) + "m";
                    }
                    System.out.format("%-30s%-6s%-6s\n", z.getName(), z.getId(), durationAmount);
                }
            }
        }
    }

    private void printHelpMenu() {
        System.out.println("Available commands are:\n");
        for (String command : commands) {
            System.out.println(command);
        }
    }

    private void printIrrigationResults(String input) {
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                String[] amountString = input.split("results last ");
                int duration = Integer.parseInt(amountString[1]);
                IrrigationResult[] results = (IrrigationResult[]) c.getIrrigationResults().toArray();
                ArrayUtils.reverse(results);
                for (int i = 0; i < duration; i++) {
                    // Don't let the array go out of bounds.
                    if (i == results.length) {
                        break;
                    }
                    System.out.println("\n" + results[i]);
                }
            }
        }
    }

    private void printVersion() {
        System.out.println("v" + irrigator.getVersion() + " by Ben Steele.\n");
    }

    private void printWeatherStationInfo(String input) {
        DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm");
        System.out.format("%-25s%-15s%-10s%-12s%-20s%-20s\n", "Station", "Type", "Active", "# Records",
                "Oldest Record", "Newest Record");
        for (WeatherStation ws : irrigator.getWeatherStations()) {
            if (input.toLowerCase().contains(ws.getName().toLowerCase())) {
                System.out.format("%-25s%-15s%-10s%-12s%-20s%-20s\n", ws.getName(), ws.getType(), ws.isActive(),
                        ws.getNumberOfRecords(), formatter.print(ws.getOldestRecordTime()),
                        formatter.print(ws.getNewestRecordTime()));
            }
        }
    }

    private void printWeatherMultiplier(String input) {
        System.out.println("Multiplier Value: " + irrigator.getWeatherMultiplierValue());
        System.out.println("Multiplier Max Temp: " + irrigator.getWeatherMultiplierMaxTemp() + "C");
        System.out.println("Multiplier Days To Look Ahead: " + irrigator.getWeatherMultiplierDaysToLookAhead());
        System.out.println("Currently Triggered?: " + ((irrigator.getWeatherMultiplier() != 1.0) ? true : false));
    }

    private void printWeatherStationStatus(String input) {
        for (WeatherStation ws : irrigator.getWeatherStations()) {
            if (input.toLowerCase().contains(ws.getName().toLowerCase())) {
                System.out.println("Station: " + ws.getName());
                System.out.println("Record: " + ws.getStatus());
                System.out.println("Current Temp (C): " + ws.getCurrentTemperatureCelcius());
                System.out.println("Today's Max Temp (C): " + ws.getTodaysMaxTemperatureCelcius());
                System.out.println("Today's Min Temp (C): " + ws.getTodaysMinTemperatureCelcius());
                System.out.println("Current Temp (F): " + ws.getCurrentTemperatureFahrenheit());
                System.out.println("Today's Max Temp (F): " + ws.getTodaysMaxTemperatureFahrenheit());
                System.out.println("Today's Min Temp (F): " + ws.getTodaysMinTemperatureFahrenheit());
                System.out.println("Avg 7-day Temp (C): " + ws.getLastXDaysAvgTemperatureCelcius(7));
                System.out.println("Avg 7-day Temp (F): " + ws.getLastXDaysAvgTemperatureFahrenheit(7));
                System.out.println("Today's Rainfall (mm): " + ws.getTodaysRainfallMilliLitres());
                System.out.println("Today's Rainfall (in): " + ws.getTodaysRainfallInches());
                System.out.println("Last 7-day Rainfall (mm): " + ws.getLastXDaysRainfallMilliLitres(7));
                System.out.println("Last 7-day Rainfall (in): " + ws.getLastXDaysRainfallInches(7));
                System.out.println("Humidity (%): " + ws.getCurrentRelativeHumidityPercentage());
                System.out.println("Current Wind (kph): " + ws.getCurrentWindspeedKiloMetresPerHour());
                System.out.println("Current Wind (mph): " + ws.getCurrentWindspeedMilesPerHour());
                System.out.println("PoP 1-day (%): " + ws.getNextXDaysPercentageOfPrecipitation(1));
                System.out.println("PoP 3-day (%): " + ws.getNextXDaysPercentageOfPrecipitation(3));
                System.out.println("PoP 7-day (%): " + ws.getNextXDaysPercentageOfPrecipitation(7));
            }
        }
    }

    private void processConsoleInput(String input) {
        input = input.trim();

        if (input.matches("activate controller.*")) {
            activateController(input);
        }

        else if (input.matches("deactivate controller.*")) {
            deactivateController(input);
        }

        else if (input.matches("activate weatherstation.*")) {
            activateWeatherStation(input);
        }

        else if (input.matches("deactivate weatherstation.*")) {
            deactivateWeatherStation(input);
        }

        else if (input.matches("reload controller configuration")) {
            try {
                irrigator.reloadConfigurationFromFile();
                irrigator.processControllerConfiguration();
            } catch (Exception e) {
                System.out.println("Error re-loading configuration due to: " + e.getMessage());
            }
            addAutoCompleteCommands(reader);
            System.out.println("Configuration has been reloaded.");
        }

        else if (input.matches("reload watering day/time configuration")) {
            try {
                irrigator.reloadConfigurationFromFile();
                irrigator.processWateringDaysConfiguration();
                irrigator.processWateringStartTimeConfiguration();
            } catch (Exception e) {
                System.out.println("Error re-loading configuration due to: " + e.getMessage());
            }
            addAutoCompleteCommands(reader);
            System.out.println("Configuration has been reloaded.");
        }

        else if (input.matches("reload weatherstation configuration")) {
            try {
                irrigator.reloadConfigurationFromFile();
                irrigator.processWeatherStationConfiguration();
            } catch (Exception e) {
                System.out.println("Error re-loading configuration due to: " + e.getMessage());
            }
            addAutoCompleteCommands(reader);
            System.out.println("Configuration has been reloaded.");
        }

        else if (input.matches("reload weather multiplier configuration")) {
            try {
                irrigator.reloadConfigurationFromFile();
                irrigator.processWeatherMultiplierConfiguration();
            } catch (Exception e) {
                System.out.println("Error re-loading configuration due to: " + e.getMessage());
            }
            addAutoCompleteCommands(reader);
            System.out.println("Configuration has been reloaded.");
        }

        else if (input.matches("reload weather threshold configuration")) {
            try {
                irrigator.reloadConfigurationFromFile();
                irrigator.processWeatherThresholdConfiguration();
            } catch (Exception e) {
                System.out.println("Error re-loading configuration due to: " + e.getMessage());
            }
            addAutoCompleteCommands(reader);
            System.out.println("Configuration has been reloaded.");
        }

        else if (input.matches("show controller all info")) {
            printControllerInfoAll(input);
        }

        else if (input.matches("show controller.*info")) {
            printControllerInfo(input);
        }

        else if (input.matches("show controller all status")) {
            printControllerStatusAll(input);
        }

        else if (input.matches("show controller.*results last \\d")) {
            printIrrigationResults(input);
        }

        else if (input.matches("show controller.*status")) {
            printControllerStatus(input);
        }

        else if (input.matches("show controller.*zones")) {
            printControllerZones(input);
        }

        else if (input.matches("show license")) {
            printLicense();
        }

        else if (input.matches("show version")) {
            printVersion();
        }

        else if (input.matches("show weather multiplier")) {
            printWeatherMultiplier(input);
        }

        else if (input.matches("show weatherstation.*info")) {
            printWeatherStationInfo(input);
        }

        else if (input.matches("show weatherstation.*status")) {
            printWeatherStationStatus(input);
        }

        else if (input.matches("start irrigation all")) {
            startAllIrrigation();
        }

        else if (input.matches("stop irrigation all")) {
            stopAllIrrigation();
        }

        else if (input.matches("test controller.*zone.*duration \\d+")) {
            testZone(input);
        }

        else {
            printHelpMenu();
        }
    }

    private void printLicense() {
        String gnuV3License = "Jirrigate - A Java based irrigation control system.\n"
                + "Copyright (C) 2013  Ben Steele\n" + "https://github.com/bensteele/jirrigate\n\n"
                + "This program is free software: you can redistribute it and/or modify\n"
                + "it under the terms of the GNU General Public License as published by\n"
                + "the Free Software Foundation, either version 3 of the License, or\n"
                + "(at your option) any later version.\n" + "\n"
                + "This program is distributed in the hope that it will be useful,\n"
                + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
                + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
                + "GNU General Public License for more details.\n" + "\n"
                + "You should have received a copy of the GNU General Public License\n"
                + "along with this program.  If not, see [http://www.gnu.org/licenses/].";
        System.out.println(gnuV3License);
    }

    private void startAllIrrigation() {
        for (Controller c : irrigator.getControllers()) {
            System.out.print("Starting default irrigation for " + c.getName() + ": ");
            c.irrigationRequest(c.generateDefaultIrrigationRequest());
            System.out.println("OK");
        }
    }

    private void addAutoCompleteCommands(ConsoleReader reader) {
        // Clear any old auto-complete commands.
        commands.clear();
        reader.removeCompleter(completer);
        // Add the controllers to the auto-complete
        for (Controller c : irrigator.getControllers()) {
            commands.add("show controller " + c.getName() + " info");
            commands.add("show controller " + c.getName() + " results last <x>");
            commands.add("show controller " + c.getName() + " status");
            commands.add("show controller " + c.getName() + " zones");
            commands.add("deactivate controller " + c.getName());
            commands.add("activate controller " + c.getName());
        }
        commands.add("show controller all info");
        commands.add("show controller all status");

        // Add zone testing
        for (Controller c : irrigator.getControllers()) {
            for (Zone z : c.getZones()) {
                commands.add("test controller " + c.getName() + " zone " + z.getName() + " duration <seconds> ");
            }
        }

        // Add the weather stations to the auto-complete
        for (WeatherStation ws : irrigator.getWeatherStations()) {
            commands.add("show weatherstation " + ws.getName() + " info");
            commands.add("show weatherstation " + ws.getName() + " status");
            commands.add("deactivate weatherstation " + ws.getName());
            commands.add("activate weatherstation " + ws.getName());
        }

        // Add weather multiplier commands to the auto-complete
        commands.add("show weather multiplier");

        // Add irrigator specific commands to the auto-complete
        commands.add("reload controller configuration");
        commands.add("reload watering day/time configuration");
        commands.add("reload weatherstation configuration");
        commands.add("reload weather multiplier configuration");
        commands.add("reload weather threshold configuration");
        commands.add("stop irrigation all");
        commands.add("start irrigation all");
        commands.add("show license");
        commands.add("show version");

        completer = new StringsCompleter(commands);
        reader.addCompleter(completer);
    }

    public void startConsole() throws IOException {
        reader.setPrompt("jirrigate> ");

        addAutoCompleteCommands(reader);

        String line;
        PrintWriter out = new PrintWriter(reader.getOutput(), true);

        while ((line = reader.readLine()) != null) {

            if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) {
                out.println("Goodbye!");
                System.exit(0);
            }

            processConsoleInput(line);
        }
    }

    private void stopAllIrrigation() {
        for (Controller c : irrigator.getControllers()) {
            System.out.print("Stopping " + c.getName() + ": ");
            if (c.stopIrrigation()) {
                System.out.println("OK");
            } else {
                System.out.println("FAIL");
            }
        }
    }

    private void testZone(String input) {
        for (Controller c : irrigator.getControllers()) {
            if (input.toLowerCase().contains(c.getName().toLowerCase())) {
                for (Zone z : c.getZones()) {
                    if (input.toLowerCase().contains(z.getName().toLowerCase())) {
                        String[] durationString = input.split("duration ");
                        long duration = Long.parseLong(durationString[1]);
                        System.out.println("Testing " + c.getName() + " zone " + z.getName() + " for " + duration
                                + " seconds");
                        c.testZone(z, duration);
                    }
                }
            }
        }
    }
}