io.github.gsteckman.doorcontroller.DoorRestInterface.java Source code

Java tutorial

Introduction

Here is the source code for io.github.gsteckman.doorcontroller.DoorRestInterface.java

Source

package io.github.gsteckman.doorcontroller;

/*
 * DoorRestInterface.java
 * 
 * Copyright 2017 Greg Steckman
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in 
 * compliance with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is 
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing permissions and limitations under the License.
 *
 */

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.github.gsteckman.rpi_rest.SubscriptionManager;
import io.github.gsteckman.rpi_rest.SubscriptionManager.SubscriptionInfo;

/**
 * This class implements a REST interface to the Raspberry Pi for control of a door using the GPIO.
 * 
 * @author Greg Steckman
 */
@RestController
public class DoorRestInterface {
    private static final Log LOG = LogFactory.getLog(DoorRestInterface.class);
    private static final String SUBSCRIBE_METHOD = "SUBSCRIBE";
    private static final String UNSUBSCRIBE_METHOD = "UNSUBSCRIBE";
    private static final String SUBSCRIPTION_KEY = "/door/subscriptions";
    private DoorController dc;
    private SubscriptionManager subMgr;

    /**
     * Create a new DoorRestInterface using the provided SubscriptionManager and DoorController.
     * @param sm SubscriptionManager for supporting UPnP subscriptions.
     * @param doorController The DoorController to use for activating the door.
     */
    public DoorRestInterface(final SubscriptionManager sm, final DoorController doorController) {
        subMgr = sm;
        dc = doorController;

        dc.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent arg0) {
                ObjectMapper mapper = new ObjectMapper();
                try {
                    subMgr.fireEvent(SUBSCRIPTION_KEY, "application/JSON",
                            mapper.writeValueAsString(getDoorState()));
                } catch (JsonProcessingException e) {
                    LOG.error(e);
                }
            }
        });
    }

    /**
     * This method handles the UPnP defined HTTP methods SUBSCRIBE and UNSUBSCRIBE bound to the URL path /door/subscriptions.
     * @param req The request provided from the servlet container.
     * @param res The response object provided by the servlet container.
     * @throws IOException Thrown by HttpServletResponse.sendError if an error occurs writing the response.
     */
    @RequestMapping("/door/subscriptions")
    public void process(HttpServletRequest req, HttpServletResponse res) throws IOException {
        if (SUBSCRIBE_METHOD.equals(req.getMethod())) {
            LOG.debug("SUBSCRIBE /door/subscriptions");
            subMgr.processSubscribe(SUBSCRIPTION_KEY, req, res);
        } else if (UNSUBSCRIBE_METHOD.equals(req.getMethod())) {
            LOG.debug("UNSUBSCRIBE /door/subscriptions");
            subMgr.processUnsubscribe(SUBSCRIPTION_KEY, req, res);
        }
    }

    /**
     * GET /door/subscriptions.
     * 
     * Returns all current subscribers to door state change events.
     *  
     * @return A collection of subscribers.
     */
    @GetMapping(path = "/door/subscriptions")
    public Collection<SubscriptionInfo> getDoorSubscriptions() {
        LOG.debug("GET /door/subscroptions");
        return subMgr.getSubscriptions(SUBSCRIPTION_KEY);
    }

    /**
     * POST /door REST endpoint to open/close the door.
     * 
     * Body
     * 
     * {action: "open" | "close"}
     * 
     * Response:
     * 
     * { name: "door", state: "open" | "closed" }
     * 
     * @param model
     *            JSON data model provided in the body of the POST
     */
    @PostMapping(path = "/door")
    public Map<String, Object> door(@RequestBody Map<String, Object> model) {
        LOG.debug("POST /door");
        String action = (String) model.get("action");
        if ("open".equals(action)) {
            dc.openDoor();
        } else {
            dc.closeDoor();
        }
        return getDoorState();
    }

    /**
     * 
     * Response:
     * 
     * {name: "door", state: "open" | "closed"}
     * 
     * @return Map of name/value pairs that Spring converts to a HTTP JSON Response
     */
    @GetMapping(path = "/door")
    public Map<String, Object> getDoorState() {
        LOG.debug("GET /door");

        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("name", "door");
        returnMap.put("state", dc.getState().toString());
        return returnMap;
    }
}