org.wso2.devicemgt.raspberry.agent.SidhdhiQuery.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.devicemgt.raspberry.agent.SidhdhiQuery.java

Source

/*
 * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * 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.
 */

package org.wso2.devicemgt.raspberry.agent;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.log4j.Logger;
import org.wso2.siddhi.core.SiddhiManager;
import org.wso2.siddhi.core.event.Event;
import org.wso2.siddhi.core.stream.input.InputHandler;
import org.wso2.siddhi.core.stream.output.StreamCallback;
import org.wso2.siddhi.core.util.EventPrinter;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.concurrent.FutureCallback;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

/**
 * This class reads the sonar reading and injects values
 * to the siddhiEngine for processing on a routine basis
 * also if the siddhiquery is updated the class takes
 * care of re-initializing same.
 */
public class SidhdhiQuery implements Runnable {
    private static final Logger log = Logger.getLogger(SidhdhiQuery.class);
    final AgentConstants constants = new AgentConstants();

    //Bam data push client
    private static PushBamData pushBamData = new PushBamData();
    private static SiddhiManager siddhiManager = new SiddhiManager();

    public static PushBamData getPushBamData() {
        return pushBamData;
    }

    public static SiddhiManager getSiddhiManager() {
        return siddhiManager;
    }

    public static void setSiddhiManager(SiddhiManager siddhiManager) {
        SidhdhiQuery.siddhiManager = siddhiManager;
    }

    //keeps track of bulb status. The start status is assumed as off
    //TODO : pick up current bulb status from a API
    boolean isBulbOn = false;

    public void run() {

        //Initialize Push data client
        PushBamData pushdata = getPushBamData();
        pushdata.initializeDataPublisher();

        //Start the execution plan with pre-defined or previously persisted Siddhi query
        StartExecutionPlan startExecutionPlan = new StartExecutionPlan().invoke();

        while (true) {

            //Check if there is new policy update available
            if (AgentInitializer.isUpdated()) {
                System.out.print("### Policy Update Detected!");
                //Restart execution plan with new query
                restartSiddhi();
                startExecutionPlan = new StartExecutionPlan().invoke();
            }
            InputHandler inputHandler = startExecutionPlan.getInputHandler();

            //Sending events to Siddhi
            try {
                //If sonar URL is present in the config file the program will read stats off the API
                //If not it will look for a file which is also configurable via a property
                String sonarUrl = constants.prop.getProperty("sonar.reading.url");
                String sonarReading = null;
                if (sonarUrl != null) {
                    sonarReading = readSonarData(sonarUrl);
                }
                if (sonarReading == null || sonarReading.equalsIgnoreCase("")) {
                    sonarReading = readFile(constants.prop.getProperty("sonar.reading.file.path"),
                            StandardCharsets.UTF_8);
                }
                log.info("Pushing data to CEP - Sonar : " + sonarReading.trim());
                inputHandler.send(new Object[] { "FIRE_1", Double.parseDouble(sonarReading) });
                Thread.sleep(Integer.parseInt(constants.prop.getProperty("read.interval")));
                //                executionPlanRuntime.shutdown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Re-Initialize SiddhiManager
     */
    private void restartSiddhi() {
        siddhiManager.shutdown();
        siddhiManager = new SiddhiManager();
    }

    /**
     * Make http call to specified endpoint with events
     * @param inEvents
     * @param bulbEP
     * @param logText
     */
    private void performHTTPCall(Event[] inEvents, String bulbEP, String logText) {
        if (inEvents != null && inEvents.length > 0) {
            EventPrinter.print(inEvents);
            String url = constants.prop.getProperty(bulbEP);

            CloseableHttpAsyncClient httpclient = null;

            httpclient = HttpAsyncClients.createDefault();
            httpclient.start();
            HttpGet request = new HttpGet(url);
            log.info("Bulb Status : " + logText);
            final CountDownLatch latch = new CountDownLatch(1);
            Future<HttpResponse> future = httpclient.execute(request, new FutureCallback<HttpResponse>() {
                @Override
                public void completed(HttpResponse httpResponse) {
                    latch.countDown();
                }

                @Override
                public void failed(Exception e) {
                    latch.countDown();
                }

                @Override
                public void cancelled() {
                    latch.countDown();
                }
            });

            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Read content from a given file and return as a string
     * @param path
     * @param encoding
     * @return
     */
    static String readFile(String path, Charset encoding) {
        byte[] encoded = new byte[0];
        try {
            encoded = Files.readAllBytes(Paths.get(path));
        } catch (IOException e) {
            log.error("Error reading Sidhdhi query from file.");
        }
        return new String(encoded, encoding);
    }

    /**
     * Read sonar data from API URL
     * @param sonarAPIUrl
     * @return
     */
    private String readSonarData(String sonarAPIUrl) {
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(sonarAPIUrl);
        String responseStr = null;
        try {
            HttpResponse response = client.execute(request);
            log.debug("Response Code : " + response);
            InputStream input = response.getEntity().getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8"));
            responseStr = String.valueOf(br.readLine());
            br.close();

        } catch (IOException e) {
            //log.error("Exception encountered while trying to make get request.");
            log.error("Error while reading sonar reading from file!");
            return responseStr;
        }
        return responseStr;
    }

    /**
     * Initialize SiddhiExecution plan
     */
    private class StartExecutionPlan {
        private InputHandler inputHandler;

        public InputHandler getInputHandler() {
            return inputHandler;
        }

        public StartExecutionPlan invoke() {
            String executionPlan;
            executionPlan = readFile(constants.prop.getProperty("execution.plan.file.location"),
                    StandardCharsets.UTF_8);

            //Generating runtime
            siddhiManager.addExecutionPlan(executionPlan);

            siddhiManager.addCallback("bulbOnStream", new StreamCallback() {
                @Override
                public void receive(Event[] events) {
                    System.out.println("Bulb on Event Fired!");
                    if (events.length > 0) {
                        if (!isBulbOn) {
                            performHTTPCall(events, "bulb.on.api.endpoint", "Bulb Switched on!");
                            System.out.println("#### Performed HTTP call! ON.");
                            pushBamData.publishData(constants.prop.getProperty("device.id"),
                                    constants.prop.getProperty("device.type"),
                                    constants.prop.getProperty("device.user"), "BULB SWITCHED ON");
                            isBulbOn = true;
                        }
                    }
                }
            });

            siddhiManager.addCallback("bulbOffStream", new StreamCallback() {
                @Override
                public void receive(Event[] inEvents) {
                    System.out.println("Bulb off Event Fired");
                    if (isBulbOn) {
                        performHTTPCall(inEvents, "bulb.off.api.endpoint", "Bulb Switched off!");
                        System.out.println("#### Performed HTTP call! OFF.");
                        pushBamData.publishData(constants.prop.getProperty("device.id"),
                                constants.prop.getProperty("device.type"),
                                constants.prop.getProperty("device.user"), "BULB SWITCHED OFF");
                        isBulbOn = false;
                    }
                }

            });

            //Retrieving InputHandler to push events into Siddhi
            inputHandler = siddhiManager.getInputHandler("fireAlarmEventStream");

            //Starting event processing
            System.out.println("Execution Plan Started!");
            return this;
        }
    }
}