schedule.java

来自「这是一个以JAVA编写的程序,本人还没有试过,是一个简单的温度控制系统」· Java 代码 · 共 667 行 · 第 1/2 页

JAVA
667
字号
package net.sf.dz.scheduler;import java.io.File;import java.io.FileNotFoundException;import java.net.URL;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.SortedSet;import java.util.StringTokenizer;import java.util.TreeSet;import java.util.Comparator;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.conf.ConfigurationFactory;import org.freehold.jukebox.conf.TextConfiguration;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.scheduler.Scheduler;import org.freehold.jukebox.scheduler.TaskListener;import org.freehold.jukebox.service.PassiveService;import org.freehold.jukebox.scheduler.Task;import org.freehold.jukebox.scheduler.TaskDescriptor;import org.freehold.jukebox.scheduler.RecurringTaskDescriptor;import net.sf.dz.device.model.Thermostat;/** * Coordinates the {@link ScheduleEvent schedule events} comprising the * schedule. */public class Schedule extends PassiveService {    public static final LogChannel CH_SCHEDULE = new LogChannel("Schedule");        /**     * Two-letter abbreviations for days of week, just in case.     */    public static final String days[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" };        /**     * Event set for this schedule.     */    private SortedSet eventSet[] = new SortedSet[7];        /**     * The actual scheduler.     */    private Scheduler scheduler;        /**     * Thermostat to control.     */    private Thermostat ts;        /**     * URL to get the configuration from.     */    private URL scheduleURL;        /**     * Persistent configuration.     *     * While the original (global) configuration defines the initial state,     * this object stores all the changes so there's no need to touch the     * global configuration.     */    private Configuration persistentConf;        public Schedule(Thermostat ts) {            this.ts = ts;    }    protected void configure() throws Throwable {            scheduler = new Scheduler();        scheduler.setLogger(getLogger());        String cfroot = getConfigurationRoot();        Configuration conf = getConfiguration();                String persistentDirName = conf.getString("dz.persistent_schedule");                File persistentDir = new File(persistentDirName);                if ( !persistentDir.exists() ) {                    persistentDir.mkdirs();                        if ( !persistentDir.exists() ) {                            throw new IllegalArgumentException(persistentDirName + ": unable to create");            }        }                File scheduleName = new File(persistentDir, ts.getName() + ".conf");        scheduleURL = new URL("file:" + scheduleName);                Configuration cf = null;                try {                    persistentConf = new ConfigurationFactory().getConfiguration(scheduleURL);            complain(LOG_NOTICE, CH_SCHEDULE, "Reading persistent data from " + scheduleURL);                    } catch ( FileNotFoundException fnfex ) {                    complain(LOG_WARNING, CH_SCHEDULE, "Persistent data not found in " + scheduleURL + ", will store later");                        persistentConf = new TextConfiguration();        }                complain(LOG_DEBUG, CH_SCHEDULE, "Persistent configuration for " + ts.getName() + ":");                for ( Iterator ci = persistentConf.keySet().iterator(); ci.hasNext(); ) {                    String key = ci.next().toString();                        complain(LOG_DEBUG, CH_SCHEDULE, "" + key + ": " + persistentConf.getString(key));        }                persistentConf.setDefaultConfiguration(getConfiguration());                for ( int idx = 0; idx < 7; idx++ ) {                    String day = days[idx];            String dayRoot = cfroot + ".day." + day + ".period";                        eventSet[idx] = new TreeSet(new EventComparator());                        List eventNameList = persistentConf.getList(dayRoot);                        complain(LOG_DEBUG, CH_SCHEDULE, "Event list at " + dayRoot + ": " + eventNameList);            for ( Iterator i = eventNameList.iterator(); i.hasNext(); ) {                            String eventName = i.next().toString();                            try {                                    TaskDescriptor td = createEvent(idx, day, eventName);                    eventSet[idx].add(td);                                        Task t = new Command(ts, td, eventName);                                        try {                                            // VT: NOTE: Running a late task results in a mess                        // when the periods from the different days overlap.                                                scheduler.schedule(t);                                            } catch ( Throwable x ) {                                            complain(LOG_ERR, CH_SCHEDULE, x.getMessage());                    }                                    } catch ( Throwable x2 ) {                                    complain(LOG_ERR, CH_SCHEDULE, "Failed to create " + day + "/" + eventName + ", cause:", x2);                }            }        }                // Now that we know what exactly the schedule looks like, we can        // just run the current event without hurry:                ScheduleEvent current = getCurrentEvent();                if ( current != null ) {                    current.run(ts);        }    }        /**     * Create the event.     *     * Read the configuration values for the given set of arguments and try     * to create the event out of them.     *     * @param dayOffset Day number (0 is Monday).     *     * @param dayName Weekday name.     *     * @param periodName Period name.     */    private ScheduleEvent createEvent(int dayOffset, String dayName, String periodName) {            String cfroot = getConfigurationRoot() + ".day." + dayName + ".period." + periodName;        Configuration conf = getConfiguration();                // VT: NOTE: Configuration segment looks like this:        //        // <start_time>        //     XX        // </start_time>        // <setpoint enabled="true">        //     XX        // </setpoint>        // <voting enabled="true"/>        // <dump_priority>        //     XX        // </dump_priority>                String startTime = persistentConf.getString(cfroot + ".start_time", "00:00");        double setpoint = persistentConf.getDouble(cfroot + ".setpoint", 22);        boolean enabled = persistentConf.getBoolean(cfroot + ".setpoint.enabled", true);        boolean voting = persistentConf.getBoolean(cfroot + ".voting.enabled", true);        int dumpPriority = persistentConf.getInteger(cfroot + ".dump_priority", 0);                ScheduleEvent e = new ScheduleEvent(dayOffset,                                            periodName,                                            parseTime(startTime),                                             setpoint,                                            enabled,                                            voting,                                            dumpPriority);                                                    complain(LOG_DEBUG, CH_SCHEDULE, dayName + "/" + e);                return e;    }        /**     * @param time Time in HH:MM or NNNN format.     *     * @return Absolute value of that time for today in milliseconds.     */    private long parseTime(String time) {            long result = 0;                // Find out if there's a semicolon                if ( time.indexOf(":") == -1 ) {                    // No semicolon, treat it as a literal                        result = Long.parseLong(time);        } else {                    // Full parse, expect 24 hour HH:MM                        StringTokenizer st = new StringTokenizer(time, ":");            String hours = st.nextToken();            String minutes = st.nextToken();                        result = Long.parseLong(hours) * 60 + Long.parseLong(minutes);        }                // Now, figure out the milliseconds                // Find the milliseconds value of the start of the day                Calendar c = new GregorianCalendar();                c.set(Calendar.MILLISECOND, 0);        c.set(Calendar.SECOND, 0);        c.set(Calendar.MINUTE, 0);        c.set(Calendar.HOUR_OF_DAY, 0);                Date d = c.getTime();        //complain(LOG_WARNING, CH_SCHEDULE, "Day:   " + d);        //complain(LOG_WARNING, CH_SCHEDULE, "Today: " + new Date(d.getTime() + (result * 60 * 1000)));        return d.getTime() + (result * 60 * 1000);    }        protected void startup() throws Throwable {            scheduler.start();    }    protected void shutdown(Throwable cause) throws Throwable {        }        /**     * Return the set of events for the requested day.     *     * @param day Day of week, 0 being Monday.     */    public SortedSet getEvents(int day) {            return eventSet[day];    }        /**     * Get the currently running event.     *     * @return The event that is supposed to be run[ning] right now.     */    public ScheduleEvent getCurrentEvent() {            int today = new GregorianCalendar().get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;        SortedSet s = getEvents(today);        long currentOffset = RecurringTaskDescriptor.getOffset(System.currentTimeMillis());        ScheduleEvent current = null;                //complain(LOG_NOTICE, CH_SCHEDULE, ts.getName() + ": current offset: " + currentOffset);                try {                    ScheduleEvent first = (ScheduleEvent)s.first();            for ( Iterator i = s.iterator(); i.hasNext(); ) {                            ScheduleEvent e = (ScheduleEvent)i.next();                                long offset = e.getStartOffset();                                //complain(LOG_NOTICE, CH_SCHEDULE, ts.getName() + ": offset: " + offset + " " + e.getName());                                if ( currentOffset > offset ) {                                    current = e;                } else {                                    // We've reached the wrong one                                        //complain(LOG_NOTICE, CH_SCHEDULE, ts.getName() + ": stepped beyond");                                        if ( e == first ) {                                            // VT: NOTE: OK, the first period is already in the                        // future. This means that there was no period today                        // yet, and the one we're looking for is the last                        // one for yesterday.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?