SmartThings Community

Raspberry Pi Monitor


(Janos Elohazi) #41


I replied to your bug you opened in GitHub. For UPnP the host IP address must be specified in the configuration files first. I’ve tried to detail it in a reply on GitHub. Let me know if that worked.

(Working on a secret project, are we, sir?) #42

First as in BEFORE you compile ?

(Janos Elohazi) #43

Yes, modifiy properties file, save, mvn clean install and than start the jar up again

(Working on a secret project, are we, sir?) #44

Ya its not that clear then… you have BUILD first in the

(Working on a secret project, are we, sir?) #45

And you got a lot of misspellings too.

(Janos Elohazi) #46

The is not in order but you’re right I could do a better job documenting this. I’ll update the when I’ll have some time!

(Working on a secret project, are we, sir?) #47

For those of you that are using the JANI monitoring without the UPnP I have a modified version of the pom.xml file that will detect the new PI 3B+

Let me know if you want it.

(Working on a secret project, are we, sir?) #48

@cl0udninja KUDOS for your hard work !!

If you don’t mind I would like to port this over for HE… is that ok ?

(Janos Elohazi) #49

I don’t, but what is HE? :slight_smile:

(Working on a secret project, are we, sir?) #50

Hubitat Elevation – another smart hub

(Working on a secret project, are we, sir?) #51

For those who use AT and want to monitor your PI temperatures using the Raspberry Pi Monitor (Manual IP) groovy below is the modified version to do that.

 *  Raspberry Pi Monitor
 *  Monitor your Raspberry Pi using SmartThings and Raspberry Pi Monitor <>
 *  Licensed under the GNU v3 (
 *  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.
preferences {		
	input("ip", "string", title:"IP Address", description: "", defaultValue: "" ,required: true, displayDuringSetup: true)		
	input("port", "string", title:"Port", description: "80", defaultValue: "80" , required: true, displayDuringSetup: true)		
metadata {
	definition (name: "Raspberry Pi Monitor (Manual IP)", namespace: "cl0udninja", author: "Janos Elohazi") {
		capability "Polling"
		capability "Refresh"
		capability "Temperature Measurement"
        capability "Sensor"
        capability "Health Check"
        attribute "cpuFrequency", "number"       
        attribute "freeMemory", "number"
        attribute "cpuCoreVoltage", "number"
        attribute "modelName", "string"
        attribute "boardType", "string"
        attribute "javaVersion", "string"
        attribute "hostname", "string"
        attribute "serialNumber", "string"

	simulator {
		// TODO: define status and reply messages here

	tiles(scale: 2) {
		valueTile("Temperature", "device.cpuTemperature", width: 6, height: 4, canChangeIcon: true) {
            state "cpuTemperature", label:'${currentValue}°',
			icon: ""
            	[value: 25, color: "#153591"],
                [value: 35, color: "#1e9cbb"],
                [value: 47, color: "#90d2a7"],
                [value: 59, color: "#44b621"],
                [value: 67, color: "#f1d801"],
                [value: 76, color: "#d04e00"],
                [value: 77, color: "#bc2323"]
        valueTile("freeMemoryLabel", "device.label.freeMemory", width: 3, height: 1) {
        	state "default", label:'Free memory'
        valueTile("freeMemory", "device.freeMemory", width: 2, height: 1) {
        	state "default", label:'${currentValue}\nMB'
        valueTile("freeMemoryPercent", "device.freeMemoryPercent", width: 1, height: 1) {
            state "freeMemoryPercent", label:'${currentValue}%',
                [value: 0, color: "#44b621"],
                [value: 50, color: "#44b621"],
                [value: 70, color: "#f1d801"],
                [value: 80, color: "#d04e00"],
                [value: 90, color: "#bc2323"]
        valueTile("cpuCoreVoltage", "device.cpuCoreVoltage", width: 2, height: 2) {
        	state "default", label:'CPU:\n${currentValue} V',
                [value: 1.1, color: "#bc2323"],
                [value: 1.2, color: "#44b621"],
                [value: 1.3, color: "#bc2323"]
		valueTile("modelName", "device.modelName", width: 2, height:1) {
        	state "default", label:'Model name:\n${currentValue}'
        valueTile("boardType", "device.boardType", width: 2, height:1) {
        	state "default", label:'Board type:\n${currentValue}'
        valueTile("javaVersion", "device.javaVersion", width: 2, height:1) {
        	state "default", label:'Java version:\n${currentValue}'
        valueTile("hostname", "device.hostname", width: 2, height:1) {
        	state "default", label:'Hostname:\n${currentValue}'
        standardTile("refresh", "device.refresh", inactiveLabel: false, width: 1, height: 1, decoration: "flat") {
        	state "default", action:"refresh.refresh", icon: "st.secondary.refresh"
        main "Temperature"
        details(["Temperature", "freeMemoryLabel", "freeMemory", "freeMemoryPercent", "cpuCoreVoltage", "modelName", "boardType", "javaVersion", "hostname", "refresh"])

def installed() {
	log.debug "installed"

def updated() {
	log.debug "updated"

def ping() {
	log.debug "ping"

def initialize() {
	log.debug "initialize"
	sendEvent(name: "checkInterval", value: 60 * 10, data: [protocol: "cloud"], displayed: false)
// parse events into attributes
def parse(description) {
    log.debug "Parsing '${description?.json}'"
	def msg = parseLanMessage(description?.body)
    log.debug "Msg ${msg}"
	def json = parseJson(description?.body)
    log.debug "JSON '${json}'"
    if (json.containsKey("cpuTemperature")) {
    	if (getTemperatureScale() == "C") {
	    	sendEvent(name: "temperature", value: json.cpuTemperature)
        } else {
        	def fahrenheit = json.cpuTemperature * 9 / 5 + 32
            sendEvent(name: "temperature", value: fahrenheit)
    if (json.containsKey("freeMemory")) {
    	sendEvent(name: "freeMemory", value: (json.freeMemory/1024/1024).toDouble().round(2))
        if (json.containsKey("totalMemory")) {
        	sendEvent(name: "freeMemoryPercent", value: (json.freeMemory/json.totalMemory*100).toDouble().round())
    if (json.containsKey("cpuCoreVoltage")) {
    	sendEvent(name: "cpuCoreVoltage", value: json.cpuCoreVoltage)
    if (json.containsKey("modelName")) {
    	sendEvent(name: "modelName", value: json.modelName)
    if (json.containsKey("boardType")) {
    	sendEvent(name: "boardType", value: json.boardType)
    if (json.containsKey("javaVersion")) {
    	sendEvent(name: "javaVersion", value: json.javaVersion)
    if (json.containsKey("hostname")) {
    	sendEvent(name: "hostname", value: json.hostname)
    if (json.containsKey("serialNumber")) {
    	sendEvent(name: "serialNumber", value: json.serialNumber)

// handle commands
def poll() {
	log.debug "Executing 'poll'"

def refresh() {
	log.debug "Executing 'refresh'"

private getPiInfo() {
	def iphex = convertIPtoHex(ip)
    def porthex = convertPortToHex(port)
	def uri = "/api/pi"
    def headers=[:]
    headers.put("HOST", "${ip}:${port}")
    headers.put("Accept", "application/json")
    def hubAction = new physicalgraph.device.HubAction(
        method: "GET",
        path: uri,
		headers: headers,
        [callback: parse]
    log.debug "Getting Pi data ${hubAction}"

private String convertIPtoHex(ipAddress) {
	log.debug "convertIPtoHex ${ipAddress} to hex"
    String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02x', it.toInteger() ) }.join()
    return hex

private String convertPortToHex(port) {
	log.debug "convertPortToHex ${port} to hex"
	String hexport = port.toString().format( '%04x', port.toInteger() )
    return hexport

private Integer convertHexToInt(hex) {
    return Integer.parseInt(hex,16)

private String convertHexToIP(hex) {
    return [convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".")
def sync(ip, port) {
	log.debug "sync ${ip} ${port}"
	def existingIp = getDataValue("ip")
	def existingPort = getDataValue("port")
	if (ip && ip != existingIp) {
		updateDataValue("ip", ip)
	if (port && port != existingPort) {
		updateDataValue("port", port)
    def ipHex = convertIPToHex(ip)
    def portHex = convertPortToHex(port)
    device.deviceNetworkId = "${ipHex}:${portHex}"

(Gene Clark) #54

Making progress but sadly still not working yet. Says build success at the end but noticed that my .jar file doesn’t have the same name as the one mentioned in the GitHub installation info as mines named “raspberrypi.monitor-0.0.1-SNAPSHOT.jar” and not sure what the snapshot is all about. Worse yet I’m getting an error page saying “This site can’t be reached” when entering the URL “http://raspberrypi:8080/api/pi” but in my case it’s “http://pecan:8080/api/pi”.

Any ideas?

(Janos Elohazi) #55

if the name is different that’s not a big deal. You’ll have to run it with sudo though. I.e.: sudo java -jar /home/pi/raspberrypi.monitor-master/target/raspberrypi.monitor-0.0.1.SNAPSHOT.jar Then it would spit out on the console if it has any problems (it shouldn’t). If you want to run it as a service you’ll have to add the above line to your rc.local and reboot the pi. After that the URL should be available. Let me know if you need more help!

(Gene Clark) #56

Thanks for getting back to me - didn’t know that last step about running it with sudo-. I looked into putting that line of code into the rc.local file, but wasn’t sure if I should go after everything else that’s already in there or if I should go before the last line with the word exit.

(Janos Elohazi) #57

do it above the line with exit 0. exit 0 will quit the script and anything after it will never be executed.

(Gene Clark) #60

Will you ever add any control of GPIO pins or no? If not do you know of any SmartThings handlers/smartapps that control GPIO?

(Janos Elohazi) #61

This is just a monitor app. I have other apps that do control GPIO ports. Check out my repositories. Those are although public I didn’t document them at all… But if you look at the code you can see what they’re doing.

(Gene Clark) #62

This one?

With these installed?

(Gene Clark) #63

Another question for you - any idea why the temperature always shows up as 0° in webCoRE?

(Janos Elohazi) #64

I think because it’s called cpuTemperature not temperature