Tutorial: How to monitor and control your Notebook with Velisphere

Tutorial: How to monitor and control your Notebook with Velisphere
Notebook monitoring tutorial app in action, with dashboard shown

In this tutorial, we will build a little application to monitor some parameters of a Linux Notebook (CPU core temperature, HDD SMART health status, battery charge level for batteries #1 and #2) and control certain actions on your notebook (sleep mode, reboot, shutdown).

The entire code for this tutorial can be found on https://github.com/thomeudt/VelisphereClientSDK/tree/master/DemoNotebookBatterySensor

What you need

Skills

As always, you should be reasonably familiar with the JAVA programming language and the Eclipse IDE. Some basic Linux skills are helpful, too.

Hardware

Any notebook computer with an x86 CPU (we have tested with a 64bit CPU, but a 32bit CPU should do as well) and Ubuntu Linux (tested on 15.10, but 14.04LTS should work, too). Other distros and older versions should also work, but might require some adaptation of the code.

Software


On your Developer Machine (PC, Mac, etc.):

Eclipse Standard IDE for you to build the JAVA client application that will then be deployed to your Linux notebook. The tutorial has been written for Eclipse “Luna” (Version 4.4), but other recent releases such as Mars or Kepler will also work. There might be slight differences to the UI though,therefore the tutorial might not be 100% accurate for these releases.

Eclipse requires a supported Java Runtime Environment (JRE). Please refer to the Eclipse documentation for further details.

On the Linux Notebook you want to monitor:

Ubuntu 14.04 or newer (Debian should also work out of the box, other distros might require some modification)

A working Java Runtime Environment, Oracle Java and OpenJDK will both do the job. Java 7 is tested, newer versions should also work.

If not already installed, on Ubuntu/Debian systems, you may install OpenJDK using the following command:

sudo apt-get install openjdk-8-jre

To obtain HDD S.M.A.R.T. status, SMARTMONTOOLS have to be installed:

sudo apt-get install smartmoontools

For other distributions, please refer to the respective documentation.

Physical Setup

There are no special requirements, other than that the Notebook has to have an internet connection.

Notebook monitoring tutorial app in action, with dashboard shown

Notebook monitoring tutorial app in action, with dashboard shown

Writing the Client Application in Java

On your developer machine, launch the Eclipse IDE. When asked, you can choose either to create a new workspace for your project, or use an existing one.

When Eclipse is started up, create a new project

FILE > NEW > JAVA PROJECT

In the dialog box, enter

NotebookDemo

in the PROJECT NAME field, leave all other options in their default settings and hit FINISH. The new project NotebookDemo should now show up in the package explorer on the left side of your Eclipse window.

We now need to create the default Velisphere configuration file, which we will later use to store information required to authenticate your Notebook in the Velisphere network as well as to validate messages your Notebook will receive from the network.

To do so, right-click on the newly create “ NotebookDemo” project and select NEW > FILE in the context menu.

In the new file dialog, please enter the following file name in the field “File name:”

velisphere_config.xml

and hit the FINISH button.

An empty file velisphere_config.xml will be created and opened on the right hand side of the screen.

Copy the following XML snippet into the newly created file

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>This file contains Velisphere authentication information. Do not overwrite!</comment>
<entry key="Secret Key"></entry>
<entry key="Endpoint ID"></entry>
<entry key="Endpoint Class ID">47bf8e2d-ba44-4438-bc96-414c2e6031d1</entry>
<entry key="isProvisioned">false</entry>
</properties>

and hit the SAVE (floppy disk) button in Eclipse.

Let’s have a look at this file. In essence, it is an XML file that specifies four different keys:

Secret Key

The secret key that your Notebook will use for checking the authenticity of an incoming message (i.e. to verify whether the message has truly been sent by the Velisphere system) and which will also be used to allow the Velisphere system to check whether it was truly your device that sent an outgoing message.

The principle used by Velisphere is based on the HMAC (Keyed hash message authentication code) concept:
https://en.wikipedia.org/wiki/Hash-based_message_authentication_code

The secret key will be provided by the Velisphere server during the provisioning process and automatically be stored in the configuration file.

Endpoint ID

The endpoint ID is a unique identifier that identifies your Notebook, it will also be assigned by the Velisphere server during provisioning.

Endpoint Class ID

The endpoint class ID defines which kind of endpoint your Notebook is, so that the system has a clear description of the capabilities of this device.

Think of it as follows (Germans like car analogies):

Endpoint Class > “Notebook Computer with Linux”
> Car Analogy: “2016 Volkswagen Passat Sedan SE”

Endpoint > “Thorsten’s Notebook Computer with Linux”
> Car Analogy: “VIN WVWZZZZZxyz123456”

Within the Velisphere System, multiple endpoints of the same endpoint class can exist. Any given endpoint is, in other words, the implementation of an endpoint class. The endpoint class describes the characteristics, the “properties” of and endpoint.

For this reason, the endpoint class ID needs to be provided to Velisphere when sending the provisioning request and therefore needs to be provided via the XML file before sending the provisioning request.

The endpoint class for this tutorial is

47bf8e2d-ba44-4438-bc96-414c2e6031d1

IsProvisioned Flag

Before provisioning a device for the first time (or re-provisioning a device that was previously provisioned), the isProvisioned-Flag needs to be set to “false”. We will later read this flag to determine on startup whether to send a provisioning request or continue with regular boot.

Download the SDK

Next, we need to download the Velisphere Software Development Kit JAR file and add it to the JAVA build bath of our newly created repository.

To download the file, go to

https://github.com/thomeudt/VelisphereClientSDK/releases
Under the “Downloads” section, you will find a file called VelisphereMilkSDK.jar (In case you wonder about the dairy content – all Velisphere components are codenamed around products you need to produce chai late, and milk certainly qualifies for that…)

Switch back to Eclipse and make a right click on you newly created project “NotebookDemo”, select Build Path > and Configure Build Path… .

Select the Libraries tab and click on Add external JARs… on the right side of the dialog box

In the JAR selection dialog box, navigate to the location in which you stored the downloaded VelisphereMilkSDK.jar. Select this file and click OK. The JAR selection dialog closes, then hit OK again to close the Java Build Path dialog.

We can now use routines from the SDK JAR file to build our client, which saves a lot of time.

Get GeoLite

Velisphere provides you with functionality to track location data of your devices and perform further analysis on this data. As most notebooks do not include a GPS receiver for precise location data, we will ahttp://www.connectedthingslab.com/wp-admin/options-general.phppproximate the device position based on its IP address, using GeoLite provided by MaxMind.

The required library geoip-api-1.2.15.jar can be downloaded from www.maxmind.com, and needs to be added to the build path following again steps 9-11.

Get Eclipse set up

Next, we will create a new Java package in which we will store the code that we are about to create. For the purpose of this tutorial, we are using the following package name, but you are certainly free to use whatever name you like (we suggest you stick to Java naming conventions):

com.velisphere.demo.notebookBatterySensor

Right click again on the “NotebookDemo” project and select New > and Package.

In the New Java Package dialog box, leave the default setting for the source folder (should be NotebookDemo/src) and enter the package name as above:

com.velisphere.demo.notebookBatterySensor

Within the newly created package, which will show up in the Eclipse Package Explorer after expanding the src folder, we need to create four Java classes that contain all of the code we need.

Three classes are the basic requirements for any Velisphere client implementation, but are always to be adapted specifically for the endpoint we are developing for.

In our case these are:

BatterySensorMain.java
Main class that will handle startup:

BatterySensorEventListener.java
An implementation of the com.velisphere.milk.interfaces.EventListener which is used to respond to incoming messages

PreDeployment.java
A class to trigger initial deployment of the device:

In addition, we will use two classes that provide additional functionality:

BatterySensorEngine.java
A class that will read sensor values and sends them, every 15 seconds, via AMQP to the Velisphere message broker.

In order to create these classes, please repeat the following steps for each class, using the respective class name:

Right click on the package com.velisphere.demo. notebookBatterySensor you created and select NEW > CLASS

In the New Java Class dialog box, enter the name of the class you are creating (see above), without the “.java” extension. Leave all other options in their default settings.

Hit the FINISH button to create the class

Write the Code!

After having created all four empty classes, it is time to create the code. We will start with the most simple class, the pre-deployment class, PreDeployment. In Eclipse file explorer, double click on the class, which will open the (mostly) empty class:

package com.velisphere.demo.notebookBatterySensor;
public class PreDeployment {
}

Add the following code to the PreDeployment class:

package com.velisphere.demo.notebookBatterySensor;

import com.velisphere.milk.restClient.ProvisioningClient;

public class PreDeployment {
	
	public static void initiateDeployment()
	{
		System.setProperty("jsse.enableSNIExtension", "false");
		String provisioningID = ProvisioningClient.macProvisioning();
		System.out.println("[IN] Provisioning request successfully submitted.");
		System.out.println("[IN] Go to www.velisphere.com, log in with your user name and start the provisioning wizard to complete.");
		System.out.println("[IN] Your Device ID is: " + provisioningID);
		
	}

}

This class calls the ProvisioningClient.macProvisioning static method that comes with the Velisphere Client SDK. This class files a provisioning request with Velisphere, using the MAC address of the network interface as the unique identifier.

There are other methods available for filing provisioning requests using the ProvisioningClient class, we will discuss these in later tutorials.

Calling the MAC provisioning method returns a string value that is the MAC address of the device, we print them to the console so that the user can use this identifier to finalize the provisioning, using the provisioning wizard provided by velisphere.com

Hit the “save” button in Eclipse to save your code.

Next, we will create the code for the BatterySensorEventListener class. It will have to look as follows:

package com.velisphere.demo.notebookBatterySensor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import com.velisphere.milk.amqpClient.AmqpClient;
import com.velisphere.milk.configuration.ConfigData;
import com.velisphere.milk.interfaces.EventListener;
import com.velisphere.milk.messageUtils.MessageFabrik;

public class BatterySensorEventListener implements EventListener {
	
	private static final String rebootID = "0439691d-ed98-4bf4-a199-0a7f39faa54c";
	private static final String sleepID = "a1e5ab03-264b-48b8-bcdd-90d1d31cad98";
	private static final String shutdownID = "99285f16-5a9e-4b26-912b-d5732c97adb7";

	
		@Override
		public void requestIsAlive(AmqpClient amqpClient) {
	
			System.out.println("IsAlive Requested...");
			
			HashMap<String, String> messageHash = new HashMap<String, String>();
			messageHash.put("setState", "REACHABLE");
			
			try {
				
				amqpClient.sendHashTable(messageHash, ConfigData.epid, "CTL");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		}

		@Override
		public void requestAllProperties(AmqpClient amqpClient) {
			
			System.out.println("AllProperties requested and discarded as not supported by the battery sensor demo");
			
		}

		@Override
		public void newInboundMessage(AmqpClient amqpClient, String message) {
		
			// First, notify that a new message has been received
			
			System.out.println(" [IN] New Inbound Message");
			System.out.println(" [IN] Content: " + message);
			
			// Now check for relevant messages
			
			// Do we have to reboot?
			
			try {
				String rebootRequest = MessageFabrik.extractProperty(message, rebootID);
				if(rebootRequest.equals("1")) triggerReboot();
			} catch (IOException e) {
				// do nothing if property not found
			}

			
			// Do we have to go to sleep?
			
			try {
				String sleepRequest = MessageFabrik.extractProperty(message, sleepID);
				System.out.println(" [IN] Sleep ID: " + sleepRequest);
				if(sleepRequest.equals("1")) triggerSleep();
			} catch (IOException e) {
				// do nothing if property not found
			}
			
			// Do we have to shut down?
			
			try {
				String shutdownRequest = MessageFabrik.extractProperty(message, shutdownID);
				if(shutdownRequest.equals("1")) triggerShutdown();
			} catch (IOException e) {
				// do nothing if property not found
			}


			
		}

		
		private void triggerReboot() throws IOException
		{
			System.out.println(" [IN] Reboot requested. Rebooting now.");
			Process retrieveChargeLevel = Runtime.getRuntime().exec("shutdown -r now");		
			InputStream inputStream = retrieveChargeLevel.getInputStream();
		    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		    String returnValue = bufferedReader.readLine();
		    System.out.println(" [IN] Reboot request returned value " + returnValue);
		}
		

		private void triggerSleep() throws IOException
		{
			System.out.println(" [IN] Sleep mode requested. Going to sleep now.");
			Process retrieveChargeLevel = Runtime.getRuntime().exec("pm-suspend");		
			InputStream inputStream = retrieveChargeLevel.getInputStream();
		    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		    String returnValue = bufferedReader.readLine();
		    System.out.println(" [IN] Sleep request returned value " + returnValue);
	
		}
		

		private void triggerShutdown() throws IOException
		{
			System.out.println(" [IN] Shutdown requested. Shutting down now.");
			Process retrieveChargeLevel = Runtime.getRuntime().exec("shutdown -h now");		
			InputStream inputStream = retrieveChargeLevel.getInputStream();
		    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		    String returnValue = bufferedReader.readLine();
		    System.out.println(" [IN] Shutdown request returned value " + returnValue);
	
			
		}
		
		
		
}

As already mentioned, this class implements the EventListener interface of the SDK, which takes care of responding to incoming messages.

The interface describes three methods we need to implement:

requestIsAlive
This method is triggered when the client receives a request asking if it is stil “alive”, similar to the PING command you might be familiar with. We respond with setting the state of the endpoint as “reachable”

requestAllProperties

This method is triggered when the client receives a request asking it to submit the current values of all sensors. We disregard this for the time being and leave the implementation for the next tutorial.

NewInboundMessage

This method is called when a new inbound message (other than the two above) is received. It provides the JSON message as a parameter so that the endpoint can be programmed to respond to it. We disregard this for the time being and leave the implementation for the next tutorial.

Please note the @Override annotation for each of these method, indicating that the method implements the abstract method inherited from the EventListener interface.

Next, we will create the code for the BatterySensorMonitoringEngine class. This is the class that reads data from the sensors connected to the interface kit and submits data to Velisphere in a defined interval.

package com.velisphere.demo.notebookBatterySensor;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.TimerTask;

import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import com.maxmind.geoip.regionName;
import com.velisphere.milk.amqpClient.AmqpClient;
import com.velisphere.milk.configuration.ConfigData;

public class BatterySensorEngine extends TimerTask {

	private static final String batteryOneID = "07da2f9d-7160-475d-9d3d-fcaccd9e3f6e";
	private static final String batteryTwoID = "da5e6822-64e2-45e7-b039-8d626ec8db3c";
	private static final String locationID = "befec1c0-076d-4d99-889f-754b194dde25";
	private static final String cpuCoreTempID = "23244969-8c57-46fb-8fe3-b5b0fc766d8d";
	private static final String smartHealthStateID = "dc47cbfb-76d1-41a3-b00d-ffb4960f45fa";

	private AmqpClient amqpClient;

	public BatterySensorEngine(AmqpClient amqpClient) {
		this.amqpClient = amqpClient;
	}

	public void run() {

		executeCpuCheck();
		executeSdaCheck();
		executeBatteryCheck();

	}

	private void executeBatteryCheck() {
		// determine battery count

		int batCount = determineBatteryCount();

		// determine charge level and submit to broker

		int i = 1;
		while (i <= batCount) {
			try {
				if (i == 1) {
					submitToBroker(batteryOneID, determineChargeLevel(1));
				}

				else if (i == 2) {
					submitToBroker(batteryTwoID, determineChargeLevel(2));
				}

			} catch (IOException e) {
				System.out
						.println(" [ER] Error determining charge levle for battery #"
								+ i);
				e.printStackTrace();
			}

			i = i + 1;
		}

	}

	private void executeCpuCheck() {
		// determine charge level
		try {

			Process retrieveCoreTemp = Runtime.getRuntime().exec(
					"cat /sys/class/hwmon/hwmon0/temp1_input");
			InputStream inputStream = retrieveCoreTemp.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);
			String coreTempString = bufferedReader.readLine();

			Double coreTempDouble = Double.parseDouble(coreTempString);
			coreTempDouble = coreTempDouble / 1000;

			System.out.println(" [IN] Core 1 temperature is " + coreTempDouble);
			submitToBroker(cpuCoreTempID, String.valueOf(coreTempDouble));
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void executeSdaCheck() {
		// determine health state of SDA using smartctl
		try {

			Process retrieveCoreTemp = Runtime.getRuntime().exec(
					"smartctl -H /dev/sda");
			InputStream inputStream = retrieveCoreTemp.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);
			String tempValue = bufferedReader.readLine();
			String output = "";
			while (tempValue != null) {
				System.out.println(" [IN] SMARTCTL raw output: " + tempValue);
				output = output + tempValue;
				tempValue = bufferedReader.readLine();
			}

			System.out.println(" [IN] SMARTCTL raw output: " + output);

			String stateIsHealthy = "0";
			if (output.contains("PASSED")) {

				System.out
						.println(" [IN] SMARTCTL datermined health check was PASSED");
				stateIsHealthy = "1";
			}

			submitToBroker(smartHealthStateID, stateIsHealthy);

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void submitToBroker(String batteryID, String chargeLevel) {

		// send to controller

		try {

			HashMap<String, String> messageHash = new HashMap<String, String>();

			// Sensor Data

			messageHash.put(batteryID, chargeLevel);

			// Geo Location

			File dbfile = new File("GeoLiteCity.dat");
			LookupService lookupService = new LookupService(dbfile,
					LookupService.GEOIP_MEMORY_CACHE);

			URL whatismyip = new URL("http://checkip.amazonaws.com");
			BufferedReader in = new BufferedReader(new InputStreamReader(
					whatismyip.openStream()));

			String ip = in.readLine(); // you get the IP as a String

			Location location = lookupService.getLocation(ip);

			// Populate region. Note that regionName is a MaxMind class, not an
			// instance variable
			if (location != null) {
				location.region = regionName.regionNameByCode(
						location.countryCode, location.region);
				messageHash.put(locationID, "{" +
						String.valueOf(location.latitude) + "}" + "[" +
						String.valueOf(location.longitude) + "]");
			}

	
			// Send out

			System.out.println(" [IN] Message Hash Sent to Controller: "
					+ messageHash);

			amqpClient.sendHashTable(messageHash, ConfigData.epid, "REG");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private String determineChargeLevel(int batNumber) throws IOException {
		// determine charge level

		Process retrieveChargeLevel = Runtime.getRuntime().exec(
				"cat /sys/class/power_supply/CMB" + batNumber + "/capacity");
		InputStream inputStream = retrieveChargeLevel.getInputStream();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		String chargeLevel = bufferedReader.readLine();
		System.out.println(" [IN] Battery #" + batNumber + " charge level is "
				+ chargeLevel);
		return chargeLevel;

	}

	private int determineBatteryCount() {
		// this method is to determine if and how many batteries are present

		int batCount = 0;

		Path path = Paths.get("/sys/class/power_supply/CMB1");

		if (Files.exists(path)) {
			batCount = batCount + 1;
		}

		path = Paths.get("/sys/class/power_supply/CMB2");

		if (Files.exists(path)) {
			batCount = batCount + 1;
		}

		return batCount;
	}

}

Let’s look at some aspects in more detail.

At the beginning of this class, we are defining several constants that contain the property id of the sensors of our device. Every sensor and every actor of each endpoint class carry their own ID.

	private static final String batteryOneID = "07da2f9d-7160-475d-9d3d-fcaccd9e3f6e";
	private static final String batteryTwoID = "da5e6822-64e2-45e7-b039-8d626ec8db3c";
	private static final String locationID = "befec1c0-076d-4d99-889f-754b194dde25";
	private static final String cpuCoreTempID = "23244969-8c57-46fb-8fe3-b5b0fc766d8d";
	private static final String smartHealthStateID = "dc47cbfb-76d1-41a3-b00d-ffb4960f45fa";

The id codes can be found in the endpoint class catalog available on velisphere.com.

We then declare an instance variable for the amqpClient class imported from the velisphereSDK.

private AmqpClient amqpClient;	

This variable is declared in the following constructor by injecting it as a dependency for later use.

public BatterySensorEngine(AmqpClient amqpClient) {
		this.amqpClient = amqpClient;
}

As a next step, we capture the sensor values from the system we are monitoring and package this data up in the standard Velisphere JSON format and sends it off to the message broker.

First, we read the data, and we do this for the batteries, SMART status and temperature sensor, using the following methods:

Battery


	private void executeBatteryCheck() {
		// determine battery count

		int batCount = determineBatteryCount();

		// determine charge level and submit to broker

		int i = 1;
		while (i <= batCount) {
			try {
				if (i == 1) {
					submitToBroker(batteryOneID, determineChargeLevel(1));
				}

				else if (i == 2) {
					submitToBroker(batteryTwoID, determineChargeLevel(2));
				}

			} catch (IOException e) {
				System.out
						.println(" [ER] Error determining charge levle for battery #"
								+ i);
				e.printStackTrace();
			}

			i = i + 1;
		}

	}

	private String determineChargeLevel(int batNumber) throws IOException {
		// determine charge level

		Process retrieveChargeLevel = Runtime.getRuntime().exec(
				"cat /sys/class/power_supply/CMB" + batNumber + "/capacity");
		InputStream inputStream = retrieveChargeLevel.getInputStream();
		InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
		String chargeLevel = bufferedReader.readLine();
		System.out.println(" [IN] Battery #" + batNumber + " charge level is "
				+ chargeLevel);
		return chargeLevel;

	}

	private int determineBatteryCount() {
		// this method is to determine if and how many batteries are present

		int batCount = 0;

		Path path = Paths.get("/sys/class/power_supply/CMB1");

		if (Files.exists(path)) {
			batCount = batCount + 1;
		}

		path = Paths.get("/sys/class/power_supply/CMB2");

		if (Files.exists(path)) {
			batCount = batCount + 1;
		}

		return batCount;
	}


Note that the battery read out has a bit of additional complexity as we need to determine the number of batteries first.

Temperature


	private void executeCpuCheck() {
		// determine charge level
		try {

			Process retrieveCoreTemp = Runtime.getRuntime().exec(
					"cat /sys/class/hwmon/hwmon0/temp1_input");
			InputStream inputStream = retrieveCoreTemp.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);
			String coreTempString = bufferedReader.readLine();

			Double coreTempDouble = Double.parseDouble(coreTempString);
			coreTempDouble = coreTempDouble / 1000;

			System.out.println(" [IN] Core 1 temperature is " + coreTempDouble);
			submitToBroker(cpuCoreTempID, String.valueOf(coreTempDouble));
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

SMART Status


private void executeSdaCheck() {
		// determine health state of SDA using smartctl
		try {

			Process retrieveCoreTemp = Runtime.getRuntime().exec(
					"smartctl -H /dev/sda");
			InputStream inputStream = retrieveCoreTemp.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);
			String tempValue = bufferedReader.readLine();
			String output = "";
			while (tempValue != null) {
				System.out.println(" [IN] SMARTCTL raw output: " + tempValue);
				output = output + tempValue;
				tempValue = bufferedReader.readLine();
			}

			System.out.println(" [IN] SMARTCTL raw output: " + output);

			String stateIsHealthy = "0";
			if (output.contains("PASSED")) {

				System.out
						.println(" [IN] SMARTCTL datermined health check was PASSED");
				stateIsHealthy = "1";
			}

			submitToBroker(smartHealthStateID, stateIsHealthy);

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

The good thing is, you don’t have to worry about the packaging, as we can use a single method of the amqpClient to take care of this:


amqpClient.sendHashTable(messageHash, ConfigData.epid, "REG");

messageHash in this case is a variable of the type HashMap that we have declared earlier:

HashMap<String, String> messageHash = new HashMap<String, String>();

A HashMap is a Java structure that takes stores key/value pairs. This is exactly what we need, as we need to store a sensor value (the value) that is assigned to a property (the key) of our endpoint.

In our case we have created a method to take care of building the hashmap and submitting it to the broker, adding location data using GeoLite data:

private void submitToBroker(String batteryID, String chargeLevel) {

		// send to controller

		try {

			HashMap<String, String> messageHash = new HashMap<String, String>();

			// Sensor Data

			messageHash.put(batteryID, chargeLevel);

			// Geo Location

			File dbfile = new File("GeoLiteCity.dat");
			LookupService lookupService = new LookupService(dbfile,
					LookupService.GEOIP_MEMORY_CACHE);

			URL whatismyip = new URL("http://checkip.amazonaws.com");
			BufferedReader in = new BufferedReader(new InputStreamReader(
					whatismyip.openStream()));

			String ip = in.readLine(); // you get the IP as a String

			Location location = lookupService.getLocation(ip);

			// Populate region. Note that regionName is a MaxMind class, not an
			// instance variable
			if (location != null) {
				location.region = regionName.regionNameByCode(
						location.countryCode, location.region);
				messageHash.put(locationID, "{" +
						String.valueOf(location.latitude) + "}" + "[" +
						String.valueOf(location.longitude) + "]");
			}

	
			// Send out

			System.out.println(" [IN] Message Hash Sent to Controller: "
					+ messageHash);

			amqpClient.sendHashTable(messageHash, ConfigData.epid, "REG");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

Refer to our RaspberryPi tutorial to learn more about how to add location information to your messages: Read it here

Let’s finally build our main class:

package com.velisphere.demo.notebookBatterySensor;

import java.io.IOException;
import java.util.Timer;
import com.velisphere.milk.amqpClient.AmqpClient;
import com.velisphere.milk.configuration.ConfigFileAccess;
import com.velisphere.milk.configuration.Provisioner;

public class BatterySensorMain {

	public static void main(String[] args) throws IOException  {
	
		System.out.println(" ----------------------------------------------------------------------------------------------");
		System.out.println(" VELISPHERE DEMO: Notebook Battery Sensor (for Linux machines, tested on Ubuntu 15.10");
		System.out.println(" (C) 2015 Thorsten Meudt");	
		System.out.println(" Licensed under the GPLv2 license, http://www.gnu.org/licenses/old-licenses/gpl-2.0.de.html");
		System.out.println(" Learn more about the VeliSphere IoT System at www.connectedthingslab.com");
		System.out.println(" ----------------------------------------------------------------------------------------------");
		System.out.println(" ");	
		System.out.println(" This Demo is designed for Ubuntu based systems and tested on Ubuntu 15.10. Older versions might");
		System.out.println(" still work.");
		System.out.println(" For the SMART monitoring function to work, smartmontools have to be installed.");
		System.out.println(" To install smartmontools, execute SUDO APT-GET INSTALL SMARTMONTOOLS");	
		System.out.println(" ----------------------------------------------------------------------------------------------");
		
		
		// Load Configuration Data
		
		ConfigFileAccess.loadParamChangesAsXML();
		
		// Check if device is already deployed. If not, trigger pre-deployment cycle
	
		System.out.println(" [IN] Calling provisioner to determine if device is flagged as provisioned.");	
		
		
		if (Provisioner.isProvisioned() == false)
			PreDeployment.initiateDeployment();
		else
			regularStartup();
					
	}
	
	public static void regularStartup()
	{


		// Activate Event Responders

		
		BatterySensorEventListener eventListener = new BatterySensorEventListener();

		
		// Start Server and activate listener

		AmqpClient amqpClient = new AmqpClient(eventListener);
		
		amqpClient.startClient();
		
		
		
	
		// Start timer to submit battery charge level at defined intervals
		
		Timer timer = new Timer();
		 timer.schedule(new BatterySensorEngine(amqpClient), 0, 5000);
	}	
}

This class consists of two static methods, main which is called when the Java executable is started, and regularStartup, which is called by main.

Looking at the main method first, the first step is to load the configuration data from the velisphere_config.xml file.

ConfigFileAccess.loadParamChangesAsXML();

Next, we do a simple if/then/else to determine whether the device needs to be provisioned first, or whether this step has already been completed and regular startup can commence:

if (Provisioner.isProvisioned() == false)
			PreDeployment.initiateDeployment();
		else
			regularStartup();

That’s all.

Now look at the regularStartup method:

First we instantiate an EventListener from (using the class in the SDK).

PiEventListener eventListener = new PiEventListener();

Next we instantiate an amqpClient in which we inject our eventListener and start the amqpClient.

AmqpClient amqpClient = new AmqpClient(eventListener);
amqpClient.startClient();

We finally call the PhidgetMonitoringEngine at 5 second intervals:

Timer timer = new Timer();
timer.schedule(new BatterySensorEngine(amqpClient), 0, 5000);

It is important that you do this after creating the amqpClient, as the monitoring engine depends on amqpClient.

Create a runnable configuration

Our code is complete! We now need to create a runnable configuration so that we can run it as a stand alone application on our notebook computer.

To do so, open the RUN menu in the Eclipse main menu bar and select RUN CONFIGURATIONS…

In the following dialog, click select Java Application in the list on the left, make a right click on it and click NEW in the context menu.

A new run configuration is created. On the right side of the dialog, we need to give a name to our configuration, we call it NotebookDemoConfig. Leave all other values at their defaults and hit APPLY and then CLOSE.

All that is left to do is to export everything into an executable JAR file. To do this, make a final right click on your project NotebookDemo and click EXPORT.

Expand the Java folder and select Runnable JAR file and hit the NEXT button

In the “Runnable JAR file export” dialog, select the runnable configuration we just created (“NotebookDemoConfig – NotebookDemo”) in the “Launch Configurations” dropdown list.

Select a path to which you want to export your file in “Export Destination”. On my computer, I chose “/home/thorsten/Documents/tutorials/NotebookDemo.jar”, but you are free to chose any path you like. However you need to be able to locate this file later on on your computer.

Make sure you select “Extract required libraries into generated JAR” under “Library handling”.

Hit FINISH

If a warning about referenced libraries shows up, confirm with OK.

Download the GeoLite city database binary from here

http://dev.maxmind.com/geoip/legacy/geolite/

and extract the contained GeoLiteCity.dat file to a temporary location.

Now, copy the following files into a directory on your notebook computer:

– the created JAR file
– velisphere_config.xml
– GeoLiteCity.dat

Starting the client

Now it’s time to start your client for the first time and provision it with Velisphere.

Go to your notbeook computer

Navigate to the directory where you stored your files in step 33 and enter the following command to start your client:

java -jar ./NotebookDemo.jar

Note that if you used a different file name in step III/29, you will have to use this filename here instead of NotebookDemo.jar

If everything goes well (it is important that your notebook has a working internet connection), the client will execute the PreDeployment routine and return a DeviceID – the MAC address of your Pi.

Go to www.velisphere.com, log in with your user account and click on “Deployment Wizard” on the right side of the screen.

Enter the DeviceID returned in step 2 and the captcha word and hit the SEARCH button

Velisphere should find your device in an unassigned state. In this screen, click on CLAIM OWNERSHIP to complete the provisioning process and add the newly created device to your inventory by giving it a name, like “My First Velisphere Client”.

Go back to your notebook and start our client:

java -jar ./NotebookDemo.jar

As the device is now fully provisioned, the client will connect with the message broker and start sending sensor values to VeliSphere. You can follow this on your screen as the client currently is fairly verbose, providing a lot of debug information.

Congratulations!

Comments ( 2,492 )

  1. ReplyThapiom
    Order Synthetic Viagra Direct Shipped Ups Amoxicilina Saturday Delivery Internet cialis Cialis Medicament Prix Kamagra Oral Jelly France
  2. ReplyJackssmiz
    Hello. Downloads music club Dj's, mp3 private server. http://0daymusic.org/premium.php Private FTP Music/Albums/mp3 1990-2018: Plan A: 20 EUR - 200GB - 30 Days Plan B: 45 EUR - 600GB - 90 Days Plan C: 80 EUR - 1500GB - 180 Days Best Regards, Robert
  3. ReplyWilliesAmaby
    Hello, Downloads music club Dj's, mp3 private ftp server. Private FTP Music/Albums/mp3 1990-2018: http://0daymusic.org/premium.php Best Regards, Robert
  4. Replyminecraft
    Inspiring quest there. What occurred after? Thanks!
  5. Replytinyurl.com
    A person necessarily help to make seriously posts I would state. This is the very first time I frequented your web page and so far? I amazed with the analysis you made to make this actual submit incredible. Magnificent job!
  6. Replyhttp://tinyurl.com/y57frnw4
    Thanks for the marvelous posting! I really enjoyed reading it, you could be a great author. I will remember to bookmark your blog and will often come back very soon. I want to encourage you continue your great job, have a nice afternoon!
  7. Replyminecraft
    I constantly spent my half an hour to read this website's articles or reviews every day along with a mug of coffee.
  8. ReplyUousrs
  9. ReplySsnxzu
    cialis pills purchase zoloft
  10. ReplyHljjak
    buy cialis cialis coupon
  11. ReplyWuepnf
    cialis professional paxil online
  12. ReplyOcyewd
  13. ReplyYwxmth
    propecia hair loss cialis 20 mg
  14. ReplyAltonBar
    Cтpoитeльcтвo кoттeджeй нa тeppитopии Mocквы имeeт нeмaлoe кoличecтвo нюaнcoв, кoтopыe нужнo учитывaть, подробности смотрите на сайте http://mirsmi24.ru
  15. ReplyGlxlea
    generic cialis online generic levitra
  16. ReplyAtmxiq
    xanax cost kamagra
  17. ReplyYivmzc
    cialis coupon generic cialis
  18. ReplyKidysn
    tadalafil online tadalafil
  19. ReplyNefzdf
    cialis generic tadalafil
  20. ReplyDxbqwz
    tadalafil coupon cialis
  21. ReplyUxfyuq
    finasteride price finasteride price
  22. ReplyDrqwdb
    cialis coupon tadalafil online
  23. ReplyKwxigb
  24. ReplyMjedgq
    online prescription canadian online pharmacy
  25. ReplyOyvxoy
    viagra soft canada order cheap viagra soft online
  26. Replydownload minecraft
    I don't even know the way I ended up right here, but I assumed this post was once great. I don't recognise who you might be but definitely you are going to a well-known blogger when you are not already. Cheers!
  27. ReplyScjtwg
  28. ReplyTtaufl
    buy generic cialis buy cialis
  29. ReplyWcmqtz
    cialis coupon buy cialis pills
  30. Replymojang minecraft download
    What's Going down i'm new to this, I stumbled upon this I've found It positively helpful and it has aided me out loads. I hope to contribute & assist different customers like its aided me. Great job.
  31. viagra for women
    viagra for women viagra for women
  32. viagra for sale
    viagra for sale viagra for sale
  33. cialis generic availability
    cialis generic availability cialis generic availability
  34. viagra generic
    viagra generic viagra generic
  35. cialis generic name
    cialis generic name cialis generic name
  36. viagra online
    viagra online viagra online
  37. cialis generic tadalafil
    cialis generic tadalafil cialis generic tadalafil
  38. viagra online canada pharmacy
    viagra online canada pharmacy viagra online canada pharmacy
  39. cialis generic tadalafil 10mg
    cialis generic tadalafil 10mg cialis generic tadalafil 10mg
  40. viagra pills
    viagra pills viagra pills
  41. cialis generic tadalafil 60mg
    cialis generic tadalafil 60mg cialis generic tadalafil 60mg
  42. cialis generic tadalafil walmart
    cialis generic tadalafil walmart cialis generic tadalafil walmart
  43. viagra prices
    viagra prices viagra prices
  44. cialis generic tadalafil for sale
    cialis generic tadalafil for sale cialis generic tadalafil for sale
  45. cialis generic tadalafil india
    cialis generic tadalafil india cialis generic tadalafil india
  46. viagra sex
    viagra sex viagra sex
  47. cialis prices 10mg
    cialis prices 10mg cialis prices 10mg
  48. viagra side effects
    viagra side effects viagra side effects
  49. viagra vs cialis
    viagra vs cialis viagra vs cialis
  50. cialis prices 100mg
    cialis prices 100mg cialis prices 100mg
  51. viagra without a doctor prescription
    viagra without a doctor prescription viagra without a doctor prescription
  52. viagra without a doctor prescription from canada
    viagra without a doctor prescription from canada viagra without a doctor prescription from canada
  53. cialis prices 20mg
    cialis prices 20mg cialis prices 20mg
  54. cialis prices 5mg
    cialis prices 5mg cialis prices 5mg
  55. generic cialis tadalafil 20mg
    generic cialis tadalafil 20mg generic cialis tadalafil 20mg
  56. cialis prices walmart
    cialis prices walmart cialis prices walmart
  57. generic cialis available
    generic cialis available generic cialis available
  58. generic cialis pricing
    generic cialis pricing generic cialis pricing
  59. best place to buy cialis online without script
    best place to buy cialis online without script best place to buy cialis online without script
  60. generic viagra sildenafil citrate
    generic viagra sildenafil citrate generic viagra sildenafil citrate
  61. buy cialis
    buy cialis buy cialis
  62. sildenafil
    sildenafil sildenafil
  63. buy cialis canada online
    buy cialis canada online buy cialis canada online
  64. sildenafil 100mg
    sildenafil 100mg sildenafil 100mg
  65. buy cialis generic tadalafil
    buy cialis generic tadalafil buy cialis generic tadalafil
  66. sildenafil 100mg tablets
    sildenafil 100mg tablets sildenafil 100mg tablets
  67. buy cialis online
    buy cialis online buy cialis online
  68. sildenafil 20 mg
    sildenafil 20 mg sildenafil 20 mg
  69. buy cialis online without script
    buy cialis online without script buy cialis online without script
  70. sildenafil 20 mg tablet
    sildenafil 20 mg tablet sildenafil 20 mg tablet
  71. where can i buy cialis over the counter at walmart
    where can i buy cialis over the counter at walmart where can i buy cialis over the counter at walmart
  72. sildenafil 20 mg tablet vs viagra
    sildenafil 20 mg tablet vs viagra sildenafil 20 mg tablet vs viagra
  73. where to buy cialis online safely
    where to buy cialis online safely where to buy cialis online safely
  74. sildenafil citrate
    sildenafil citrate sildenafil citrate
  75. sildenafil citrate 100mg
    sildenafil citrate 100mg sildenafil citrate 100mg
  76. sildenafil citrate 20 mg
    sildenafil citrate 20 mg sildenafil citrate 20 mg
  77. sildenafil coupons
    sildenafil coupons sildenafil coupons
  78. sildenafil dosage
    sildenafil dosage sildenafil dosage
  79. sildenafil generic
    sildenafil generic sildenafil generic
  80. sildenafil side effects
    sildenafil side effects sildenafil side effects
  81. 5mg cialis
    5mg cialis 5mg cialis
  82. buy viagra
    buy viagra buy viagra
  83. buy viagra online
    buy viagra online buy viagra online
  84. canadian viagra
    canadian viagra canadian viagra
  85. buying cialis online
    buying cialis online buying cialis online
  86. cheap viagra
    cheap viagra cheap viagra
  87. canadian cialis
    canadian cialis canadian cialis
  88. cialis vs viagra
    cialis vs viagra cialis vs viagra
  89. canadian pharmacy cialis
    canadian pharmacy cialis canadian pharmacy cialis
  90. cost of viagra
    cost of viagra cost of viagra
  91. cheap cialis
    cheap cialis cheap cialis
  92. female viagra
    female viagra female viagra
  93. cheap cialis generic
    cheap cialis generic cheap cialis generic
  94. female viagra pills
    female viagra pills female viagra pills
  95. cheap generic cialis
    cheap generic cialis cheap generic cialis
  96. generic viagra
    generic viagra generic viagra
  97. cialis
    cialis cialis
  98. generic viagra 100mg
    generic viagra 100mg generic viagra 100mg
  99. cialis 20 mg
    cialis 20 mg cialis 20 mg
  100. generic viagra available
    generic viagra available generic viagra available
  101. cialis 20mg
    cialis 20mg cialis 20mg
  102. generic viagra prices
    generic viagra prices generic viagra prices
  103. cialis 5mg
    cialis 5mg cialis 5mg
  104. herbal viagra
    herbal viagra herbal viagra
  105. cialis black
    cialis black cialis black
  106. levitra vs viagra
    levitra vs viagra levitra vs viagra
  107. cialis canada
    cialis canada cialis canada
  108. marley generic viagra
    marley generic viagra marley generic viagra
  109. cialis cost
    cialis cost cialis cost
  110. natural viagra
    natural viagra natural viagra
  111. cialis daily
    cialis daily cialis daily
  112. online pharmacy viagra
    online pharmacy viagra online pharmacy viagra
  113. cialis for sale
    cialis for sale cialis for sale
  114. online viagra
    online viagra online viagra
  115. cialis from canada
    cialis from canada cialis from canada
  116. pfizer generic viagra
    pfizer generic viagra pfizer generic viagra
  117. cialis generic
    cialis generic cialis generic
  118. real viagra
    real viagra real viagra
  119. cialis generic canada
    cialis generic canada cialis generic canada
  120. viagra
    viagra viagra
  121. viagra 100mg
    viagra 100mg viagra 100mg
  122. cialis on line
    cialis on line cialis on line
  123. viagra alternative
    viagra alternative viagra alternative
  124. cialis online
    cialis online cialis online
  125. viagra cost
    viagra cost viagra cost
  126. cialis online pharmacy
    cialis online pharmacy cialis online pharmacy
  127. viagra for men
    viagra for men viagra for men
  128. cialis pills
    cialis pills cialis pills
  129. cialis price
    cialis price cialis price
  130. cialis vs levitra
    cialis vs levitra cialis vs levitra
  131. viagra in action
    viagra in action viagra in action
  132. cost of cialis
    cost of cialis cost of cialis
  133. viagra on line
    viagra on line viagra on line
  134. generic cialis
    generic cialis generic cialis
  135. generic cialis canada
    generic cialis canada generic cialis canada
  136. viagra online pharmacy
    viagra online pharmacy viagra online pharmacy
  137. generic cialis online
    generic cialis online generic cialis online
  138. viagra pill
    viagra pill viagra pill
  139. generic cialis tadalafil
    generic cialis tadalafil generic cialis tadalafil
  140. generic for cialis
    generic for cialis generic for cialis
  141. viagra price
    viagra price viagra price
  142. natural cialis
    natural cialis natural cialis
  143. no prescription cialis
    no prescription cialis no prescription cialis
  144. ReplyPmudsl
    viagra soft cheap price viagra coupon
  145. ReplyUbguls
    cialis generic cialis
  146. ReplyWobgfa
    prozac prozac
  147. ReplyfrshAlisy
    http://canadadrugswikr.com/ canada drugs direct
  148. Replyfbssnafe
    http://canadapharmacywikd.com/ canadian drugs
  149. Replydcesnafe
    http://pharmacycialiswxrb.com/ canada drugs online
  150. ReplyTcwzgm
    cialis prices cialis prices
  151. ReplyZbzzsu
  152. Replyhow to get help in windows 10
    It's remarkable to visit this web page and reading the views of all colleagues about this post, while I am also keen of getting familiarity.
  153. ReplycwsAlisy
    http://canadianpharmacywezw.com/ canadian pharmacy online
  154. Replygamefly free trial
    Thank you for the good writeup. It in fact was a amusement account it. Look advanced to far added agreeable from you! However, how can we communicate?
  155. ReplyKzufrq
    buy generic cialis generic cialis
  156. Replyviagra online
    Rocca in September 2017, and most recently, Fiorentina Grasso of CГ  del Baio. buy viagra online Jul 25, 2016В В· I've been researching Bhang recipes for quite sometime now and have found quite a few references to "fresh" leaves and flowers.
  157. ReplyDapmcv
    cialis coupon cheap cialis
  158. ReplyVlfqrv
    cialis 20 mg buy tadalafil
  159. Replygamefly free trial
    First off I want to say terrific blog! I had a quick question that I'd like to ask if you do not mind. I was curious to find out how you center yourself and clear your mind before writing. I have had a difficult time clearing my thoughts in getting my ideas out. I do take pleasure in writing but it just seems like the first 10 to 15 minutes are generally wasted just trying to figure out how to begin. Any recommendations or hints? Kudos!
  160. ReplyMatMeashy
    Priligy Modo D'Uso Amoxil Chew Tabs Recall Zithromax Work For Uti buy viagra Pediatric Dosing Amoxicillin
  161. ReplyRebUnurne
    Amoxicillin Dosage In Dogs Viagra Wholesale China Viagra For Sale Malaysia Order Generic Propecia Male Pattern Hair Loss Ethanol Et Baclofen
  162. ReplyMatMeashy
    Achat Ligne Kamagra Quebec Buying Clomid kamagra jelly 100mg Dog Keflex Reaction
  163. ReplyTreatefh3
    generic ed drugs buy tadalafil ed meds
  164. ReplyTreatefg6
    online prescription generic drugs cialis generic
  165. ReplyTreatefh4
    india pharmacy cialis prices tadalafil generic
  166. ReplyTreatefw6
    buy cialis ed meds tadalafil coupon
  167. ReplyTreatefm6
    canada pharmacy buy cialis ed pills
  168. ReplyTreatefq7
    cialis 20 mg canada pharmacy canadian online pharmacy
  169. ReplyTreatefg9
    cialis coupon ed drugs ed pills
  170. ReplyTreatefo4
    online pharmacy tadalafil coupon ed drugs online
  171. ReplyTreatefq9
    online prescription viagra for men ed drug
  172. ReplyTreatefm6
    cialis vs viagra generic ed drugs tadalafil online
  173. ReplyTreatefl5
  174. ReplyTreatefy6
    buy generic ed pills online viagra online best ed pills
  175. Replyquest bars cheap
    This web site truly has all the info I needed about this subject and didn't know who to ask.
  176. ReplyTreatefl4
    cialis tadalafil generic ed drug
  177. ReplyTreatefg8
    cialis vs viagra buy tadalafil generic drugs
  178. ReplyTreatefi5
    buy cialis cialis prices ed drug
  179. ReplyTreatefc2
    cialis vs viagra cialis vs viagra cialis
  180. ReplyTreatefc4
    cialis coupon cialis price canada pharmacy
  181. ReplyTreatefa2
    cialis online cialis coupon buy tadalafil
  182. ReplyTreatefk7
    canadian online pharmacy tadalafil online tadalafil online
  183. Replyplenty of fish dating site
    Great delivery. Great arguments. Keep up the great work.
  184. ReplyItalia Ny drakt
    My spouse and I stumbled over here different web page and thought I may as well check things out. I like what I see so i am just following you. Look forward to looking over your web page repeatedly. Italia Ny drakt
  185. ReplyTreatefo5
    online prescription ed pills online tadalafil coupon
  186. Replyquest bars cheap
    Hello colleagues, its great paragraph about tutoringand entirely defined, keep it up all the time.
  187. ReplyTreatefp9
    india pharmacy buy cialis ed pills online
  188. ReplyTreatefq6
    canadian online pharmacy generic ed drugs tadalafil generic
  189. ReplyTreatefa6
    buy cialis buy cialis cialis price
  190. ReplyJanewef
  191. ReplyKiawef
  192. ReplyKiawef
  193. ReplyAmywef
  194. ReplyMatMeashy
    Sildenafil A Buon Mercato 120 Mg For Sale Progesterone Acheter Kamagra En France cialis 5mg Buying Propecia Propecia Kamagra Generique Avis Levitra Mit Viagra Kombinieren
  195. ReplyLisawef
  196. ReplyAaronclece
    http://buyalbenza.team/ - buy albenza
  197. ReplyRebUnurne
    Propecia Parafarmacia Comprar Propecia Finasteride Ordonnance Viagra Cialis Generico Alta Qualita
  198. ReplyBennywit
  199. ReplyAaronclece
    http://vermox.team/ - more about the author
  200. ReplyAaronclece
    http://prednisolone.best/ - buy prednisolone 5mg
  201. ReplyAaronclece
    http://prozac.surf/ - prozac
  202. ReplyAaronclece
    http://yasmin.team/ - read more
  203. ReplyAaronclece
    http://buyseroquel.us.com/ - seroquel mastercard
  204. ReplyAaronclece
    http://buycolchicine.company/ - buy colchicine online
  205. ReplyAjax Fußball Trikots
    I absolutely love your blog.. Very nice colors & theme. Did you make this site yourself? Please reply back as I'm looking to create my own personal blog and want to know where you got this from or just what the theme is called. Thanks! Ajax Fußball Trikots
  206. ReplyBennywit
  207. ReplyAaronclece
    http://1stlisinoprilnow.com/ - lisinopril oral
  208. ReplyAaronclece
    http://buyprednisone.team/ - example
  209. ReplyAaronclece
    http://propecia.cc/ - propecia
  210. ReplyAaronclece
    http://lexapro.company/ - cipralex generic best price
  211. ReplyAaronclece
    http://1stprednisonenow.com/ - medication prednisone
  212. ReplyMatMeashy
    Zithromax Picture Propranolol Buy Mastercard Viagra Without Prescription. cialis 5mg Viagra Generico Controindicazioni
  213. ReplyendumS
    Buy cialis ontario buy generic cialis online
  214. ReplyAaronclece
    http://1stpaxilnow.com/ - check this out
  215. ReplyAaronclece
    http://buyzithromax.company/ - zithromax
  216. ReplyChusdoof
    Otc cialis pills buy generic cialis online buy cialis online without a rx cialis
  217. Replytinyurl.com
    We are a group of volunteers and opening a new scheme in our community. Your web site offered us with valuable information to work on. You've done an impressive job and our entire community will be thankful to you.
  218. ReplyAaronclece
    http://buyacyclovir.company/ - where can i buy acyclovir online
  219. ReplyAaronclece
    http://buyfluoxetine.us.com/ - buy fluoxetine
  220. ReplyAaronclece
    http://metformin.yoga/ - metformin
  221. ReplyAaronclece
    http://buylisinopril.company/ - buy lisinopril
  222. ReplyAaronclece
    http://1stantabusenow.com/ - antabuse
  223. ReplyAaronclece
    http://lexapro.cc/ - buy lexapro
  224. ReplyAaronclece
    http://buyzithromax.company/ - buy zithromax
  225. ReplyAaronclece
    http://tricor.team/ - for more
  226. Replyprieddy
    India generic cialis Buy Cialis Online
  227. ReplyAaronclece
    http://albuterol.surf/ - albuterol
  228. ReplyAaronclece
    http://buyprednisolone.company/ - buying prednisoline tablets
  229. ReplyAaronclece
    http://buymetformin.team/ - metformin xr 500mg
  230. ReplyAaronclece
    http://strattera.team/ - strattera
  231. Replyorder
    http://canadian-pharmacyyhzg.com/ click to investigate
  232. Replyphysician
    http://canadian-pharmacyyhzg.com/ find
  233. ReplyAaronclece
    http://sildenafil03.us.com/ - sildenafil citrate 50mg
  234. ReplyAaronclece
    http://1stpropecianow.com/ - finasteride 5mg+
  235. Replystuff
    http://canadapharmacyonlinestbh.com/ diagnosis
  236. ReplyAaronclece
    http://vardenafil.cc/ - online vardenafil
  237. ReplyRobertchone
    cialis generic cost http://cialisxtl.com cialis online
  238. ReplyAaronclece
    http://clindamycin.team/ - clindamycin hcl 300 mg buy
  239. ReplyAaronclece
    http://buycelebrex.company/ - celebrex
  240. Replygelmnumn
    Cheap generic cialis pills cialis Buy Cialis Online
  241. ReplyAaronclece
    http://buytadalafil.team/ - tadalafil 20
  242. ReplyAaronclece
    http://tadalafil.best/ - tadalafil
  243. Replyshop
    http://canadian-pharmaciesthsh.com/ caverta
  244. Replyampoule
    http://pharmacy-onlineasxs.com/ check this site out
  245. ReplyAaronclece
    http://cheapvardenafil365.us.com/ - Vardenafil
  246. ReplyAaronclece
    http://buymotilium.us.com/ - buy motilium
  247. Replyillness
    http://pharmacyonlinevfr.com/ visit this site right here
  248. ReplyAaronclece
    http://buydoxycycline.team/ - doxycycline 500mg
  249. ReplyAaronclece
    http://sildenafil.agency/ - generic sildenafil citrate 100mg
  250. Replylevitra
    http://pharmacy-onlineasxs.com/ dig this
  251. ReplyRobertchone
    their website cialis prices is generic cialis effective
  252. ReplyAaronclece
    http://buyviagra.company/ - viagra
  253. ReplyAaronclece
    http://buystromectol.company/ - stromectol
  254. ReplyAaronclece
    http://buyallopurinol.company/ - allopurinol
  255. ReplyAaronclece
    http://tadalafil.best/ - cialis tadalafil
  256. Replystore
    http://onlinepharmacyzefb.com/ this hyperlink
  257. ReplyAaronclece
    http://proscar.team/ - proscar
  258. ReplyAaronclece
    http://betnovate.team/ - betnovate
  259. ReplyKimwef
  260. ReplyRobertchone
    find out cialis over the counter at walmart cialis generic when
  261. ReplyFrandit
    Herbal Remedy Propecia cialis canada Where To Buy Orlistat Online Synkapton Kaufen
  262. ReplyMatMeashy
    Cialis Ohne Rezept Kaufen Generic Amoxicillin Comprar Cialis Farmacia Barcelona viagra Diferencias Entre Cialis Y Viagra
  263. ReplyAaronclece
    http://buyestrace.team/ - estrace cream
  264. ReplyAaronclece
    http://buyxenical.team/ - xenical
  265. Replyavana
    http://canadadrugslopl.com/ aurogra
  266. ReplyAaronclece
    http://valtrex.rodeo/ - valtrex
  267. ReplyRobertchone
    generic cialis 2016 http://cialisxtl.com cialis coupon
  268. ReplyAaronclece
    http://artane.team/ - artane generic
  269. ReplyRobertchone
    www cialis com 20 mg http://cialisxtl.com cialis online
  270. ReplyAaronclece
    http://1stlasixnow.com/ - lasix online
  271. ReplyRobertchone
    cialis generic side effects http://cialisxtl.com cialis coupon
  272. ReplyRobertchone
    cialis canada over the counter http://cialisxtl.com cialis prices
  273. ReplyAaronclece
    http://buypropranolol.us.org/ - propranolol
  274. ReplyAaronclece
    http://buyprednisolone.company/ - buy prednisolone
  275. ReplyAaronclece
    http://levitra.surf/ - levitra
  276. ReplyAaronclece
    http://1stventolinnow.com/ - ventolin
  277. ReplyAaronclece
    http://onlinecolchicine.us.com/ - online colchicine
  278. ReplyMatMeashy
    Le Viagra Est Il En Vente Libre En Pharmacie En France buy viagra Order Celebrex Propecia Dha
  279. ReplyRobertchone
    cialis adverse effects http://cialisxtl.com cialis prices
  280. ReplyAaronclece
    http://1stcephalexinnow.com/ - cephalexin
  281. ReplyAaronclece
    http://atarax.us.com/ - cheap atarax
  282. ReplyAaronclece
    http://fluoxetine.team/ - fluoxetine
  283. ReplyAaronclece
    http://lexapro.team/ - cipralex medication
  284. ReplyAaronclece
    http://1stalbenzanow.com/ - buy albenza
  285. ReplyAaronclece
    http://elocon.team/ - elocon
  286. ReplyAaronclece
    http://levaquin.team/ - levaquin
  287. ReplyAaronclece
    http://get-drugs-now.com/ - diflucan
  288. ReplyWilliammok
  289. ReplyAaronclece
    http://buyfurosemide.company/ - furosemide
  290. ReplyWilliammok
    viagra joke https://viagra20c.com# generic viagra online pharmacy
  291. ReplyAaronclece
    http://metformin.surf/ - metformin
  292. ReplyAaronclece
    http://buylisinopril.team/ - lisinopril
  293. ReplyAaronclece
    http://hyzaar.team/ - hyzaar blood pressure
  294. ReplyAaronclece
    http://levitraprofessional.us.com/ - Levitra Professional
  295. ReplyAaronclece
    http://gystyle.com/ - tadalafil canada
  296. ReplyEvawef
  297. ReplyWilliammok
    melanoma and viagra https://viagra20c.com# viagra
  298. ReplyBennywit
  299. ReplyWilliammok
    resource viagra how much does 100mg viagra cost
  300. Replyhttps://www.mvhlvjjtu.online
    You are so interesting! I don't suppose I've truly read anything like that before. So wonderful to discover someone with some genuine thoughts on this issue. Really.. thanks for starting this up. This web site is one thing that is needed on the internet, someone with some originality!
  301. Replyhttps://www.wcdppuoq60.online
    Everyone loves it whenever people get together and share thoughts. Great blog, stick with it!
  302. Replyhttps://www.rbqrid4fsz.online
    I used to be able to find good advice from your blog posts.
  303. ReplyAaronclece
    http://synthroid.wtf/ - synthroid
  304. Replyhttps://www.sejongtile.kr/
    Wow! This blog looks just like my old one! It's on a totally different subject but it has pretty much the same layout and design. Outstanding choice of colors!
  305. ReplyWilliammok
    his comment is here generic viagra available cheap viagra canada
  306. ReplyWilliammok
    that site generic viagra pfizer viagra discount
  307. ReplyBennywit
  308. ReplyWilliammok
    Home Page generic viagra available what does viagra do to blood pressure
  309. ReplyEvawef
  310. ReplyWilliammok
    canadian pharmacy generic viagra https://viagra20c.com# pfizer generic viagra
  311. ReplyAaronclece
    http://atenolol.wtf/ - atenolol medication
  312. ReplyMatMeashy
    discount free shipping cheapeast isotretinoin worldwide amex viagra Viagra Im Internet Bestellen Strafbar Generic Viagra 100 Mg Cheap Cialis And Viagra
  313. Replyhttps://www.hxwbrap6a.online
    I will right away take hold of your rss feed as I can't to find your email subscription hyperlink or e-newsletter service. Do you have any? Please allow me understand in order that I may subscribe. Thanks.
  314. Reply해적바둑이사이트
    I think this is one of the most vital info for me. And i'm glad reading your article. But wanna remark on some general things, The web site style is wonderful, the articles is really excellent : D. Good job, cheers
  315. Replyhttps://www.kulmfuelf.online
    Hello! I simply want to give you a huge thumbs up for the great information you have right here on this post. I'll be returning to your website for more soon.
  316. ReplyAaronclece
    http://baclofen.run/ - baclofen 20mg
  317. ReplyLhckls
    buy tadalafil 20mg ildenafil citrate
  318. ReplyCleantriext
    Employees "Cleaning Service" can decide diverse task, conjugate with guidance purity. You personally always can contact in "Cleaning Service" - we always well cope with the work of any volume. The Benefits partnerships with us: The use of professional disinfectants, detergents. Among other things, there are strictly fixed patterns consumer quality cleaning, what guided our the firm. If a Client considers thinks that standards good quality were not respected, we promptly we carry out "work on errors". We work on the final result, then to Client was satisfied and additionally wholeheartedly the introduced our firm to your environment. This is today a very extensive cleaning, that help to do your building accomplished. Not Important what you do, drive in you or notClean Master able there to help to get your old apartment pure look. Cleaning apartment houses, as well as houses, office premises. Cleaning general. Washing windows professional apparatus. The Calling to our specialized company, you will get: QUALIFIED EMPLOYEES - Only professionals with work experience, previously trained, work. Maid service jobs New-York - Maids NYC
  319. Reply슬롯머신
    You need to take part in a contest for one of the highest quality sites on the internet. I am going to highly recommend this web site!
  320. Reply정선 카지노 게임 종류
    Hello, Neat post. There's a problem along with your site in web explorer, could test this? IE nonetheless is the marketplace leader and a large component of other people will omit your fantastic writing because of this problem.