Help required to write my first Hubitat app

Good Day All.

I am trying to code inside Habitat-> Apps Code-> New App. Please help me with below questions if possible.

  1. In which development language we can start writing code
  2. What is the prerequisite to start with application development.

Mainly I want to develop an app from which I can read and pull sensor data on cloud.

Thanks in advance.

Regards,
Yogesh

.

The language is called "groovy". If you Google it you can find a lot of references and tutorials.

1 Like

There is also Hubitat specific api documentation at the link:

https://docs.hubitat.com/index.php?title=Developer_Documentation

This provides detailed information on interacting with Hubitat (i.e., the actual API for the Hubitat box). Hubitat uses groovy for general purpose processing (logic) and the API to interact with the environment).

There are a few examples at:

Throughout the forums, there are numerous chances to view other persons code. Before using someone elses code, it is strongly recommended you contact the author for permission.

Dave

3 Likes

Many thanks Angus_M. :slight_smile:

1 Like

Thanks a lot for your response Djgutheinz. Let me go through this and I will get back if required.

1 Like

I am getting error message while trying to execute below code inside Hubitat->Apps Code->New Code section.

class Example {
static void main(String[] args) {
// Using a simple println statement to print output to the console
println('Hello World');
}
}

Error-> Cannot cast object 'org.codehaus.groovy.runtime.InvokerHelper$1@1463534' with class 'org.codehaus.groovy.runtime.InvokerHelper$1' to class 'com.hubitat.hub.executor.AppDelegatingScript' on line null

Kindly suggest.

Sounds more like a Driver. Drivers 'abstract' the physical device into a series of 'capabilities' that are common among similar devices. Thus a ZWave Switch and a Zigbee Switch, are able to be controlled by... yep.. by Apps.

An App tells devices to turn on/off, for example, and that causes the Driver to send the correct Zwave or Zigbee commands to make it so.

Here's a prototype/template that I use when creating a new Driver from scratch. It can be pasted into Driver Code: New Driver and attached to a virtual device. It doesn't actually do anything, but it's got all the minimum code to compile and run.

Because it's a template/proto, it's got code in it you may end up discarding. You can find an App template, as well as this Driver code at:

/*
 * Import URL: https://raw.githubusercontent.com/HubitatCommunity/??/master/??-Driver.groovy"
 *
 *	Copyright 2019 C Steele
 *
 *	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.
 *
 *
 */
	public static String version()      {  return "v???"  }
 
 
import groovy.transform.Field

metadata 
{
	definition(name: "JustA Driver", namespace: "yourname", author: "your Name", importUrl: "https://raw.githubusercontent.com/HubitatCommunity/??/master/??.groovy")
	{
 		capability "Switch"
	}

      preferences 
      {
      

          //standard logging options
          input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
      }
}


/*
	updated
    
	Doesn't do much other than call initialize().
*/
def updated()
{
	initialize()
	unschedule()
      if (debugOutput) runIn(1800,logsOff) //disable debug logs after 30 min
	log.trace "Msg: updated ran"
}







/*

	generic driver stuff

*/


/*
	installed
    
	Doesn't do much other than call initialize().
*/
def installed()
{
	initialize()
	log.trace "Msg: installed ran"
}



/*
	initialize
    
	Doesn't do anything.
*/
def initialize()
{
	log.trace "Msg: initialize ran"
}


/*
	parse
    
	In a virtual world this should never be called.
*/
def parse(String description)
{
	log.trace "Msg: Description is $description"
}

/*
	on
    
	Turns the device on.
*/
def on()
{
	// The server will update on/off status
	log.trace "Msg: $device ON"
	
}


/*
	off
    
	Turns the device off.
*/
def off()
{
	// The server will update on/off status
	log.trace "Msg: $device OFF"
}

First: As csteele mentioned, there is a specific structure to an app and a driver... You can not run arbitrary code on the HE.

Second:

You are trying to define a class. Classes are not supported within user code on the HE.

If you are looking to pull data into HE, I would suggest looking at an existing app that does something similar... like maybe the Netatmo app... for ideas and inspiration...

But, as previously mentioned, get permission from the original author if you are going to copy...

Many thanks Cybrmage. Sure I will take permission before doing anything.

Hi,

I too am struggling with my first Hubitat app. I'm trying to create an app that will run every X minute (or hours) and check to see if it can reach a web site. If it fails some number of times, it will power cycle my cable modem. I'd like to define a static integer variable that I can use as a counter for the number of failures, so that, after, say, three failures it will power cycle the modem. But I seem to be getting an exception when the relevant method runs, specifically when it increments the counter.

This is a snippet of code (just for testing purposes, obviously not what the ultimate code will look like):

counter = 0

def initialize() {
  log.debug "initialize"
  counter = 0
  checkWeb()  
  runEvery5Minutes(checkWeb)
}

def uninstalled() {
  log.debug "uninstalled"
}

def checkWeb() {
    
    def params = [
    uri: "http://httpbin.org",
    path: "/get"
    ]

try {
    httpGet(params) { resp ->
        resp.headers.each {
           log.debug "${it.name} : ${it.value}"
        }
    }
        log.debug "WebCheck success!"
        counter++
        log.debug("Counter is " + counter)
} catch (e) {
    log.debug "WebCheck failed: $e"
    plugReset()
    }
}

def plugReset() {
    resetOff()
    runIn(5, resetOn)
}

def resetOff() {
    theswitch.off()
}

def resetOn() {
    theswitch.on()
}

The first call to checkWeb() works as expected. The second (after 5 mins) generates an exception, so that in my log I get:

2019-09-26 11:38:45.221 am [debug] ... WebCheck failed: java.lang.NullPointerException: Cannot invoke method next() on null object

2019-09-26 11:38:45.218 am [debug] ... WebCheck success!

So it seems like "counter++" is throwing an exception.

I'm sure this is a dumb question. But any help would be appreciated.

Thanks!

You can do this with existing apps and Rule Machine. Lemme go try to find them for you and post back here in a while...

Web pinger:

Momentary switch (to post the reboot command):

Reboot command:

Http://your-hub-ip:8080/hub/reboot

Bingo!

(not that I'm trying to stop you from having fun writing your own app) :smile:

When you are writing code to run on the platform you are not writing a full class, you are writing a groovy script. As such you cannot have variables outside of methods and access them unless you tell the groovy compiler that they are there. You need to use the @Field annotation in that case.

So at the top of your App you would want this:

import groovy.transform.Field
@Field int counter = 0

Granted, that will get rid of the errors, but not really do what you want it to do since it won't be saved between runs. In that case you should be using state.

1 Like

Aha! state.counter is exactly what I want. Thanks very much!

Thanks very much for your help. These examples are great to have!

1 Like

Good Morning,

I am planning to write my first Hubitat app , Can we write an app on Hubitat to send motion sensors data/logs/events on cloud?

Currently I have added Marker API app on Hubitat which gives me URL's to get device info.

At another end I have created one .net application which hits URL's(given by Marker API) on every 3 seconds to read current status/attribute of my sensors.

Basically I am expecting that, there could be an app on habitat side which will directly send data to cloud whenever sensors status/motion will get changed or triggered.

Thanks in advance.

Regards,
Yogesh

If you're into .Net, you should check out this thread.

3 Likes