SimpliSafe Alarm Integration (cloud to cloud)

@tobycth3, what are you trying to display with the new Messages tile? I was going to link that on SS2 to the isAlarming flag, but not sure if that is your intention or not. Take a look at my results from JSON data from
System (a couple of posts above) and tell me if yours is similiar. Not sure where else I could get the messages from.

I did find that I could poll the settings and get the following information:

"error":{  
   "keypadBatteryLow":false,
   "communicationError":false,
   "noDialTone":true,
   "dialError":true,
   "checksumWrong":false,
   "notRegistered":false,
   "messageFailed":false,
   "outOfRange":false
}

I think that information could prove very useful. I would say we ignore the noDialTone and dialError as some people (myself included) do not connect the SS2 to a phone line. Let me know and I can implement something with these (maybe these are the equivalent of messages in SS3).

Another update. I wanted to be able to see the time of the most recent event (shown on the large tile in the Device Handler). So, I modified the Poll message and replaced the httpget section for events with the following. Now it will tell you the time of the last event.

//Get the most recent event
httpGet ([uri: getAPIUrl("events"), headers: state.auth.respAuthHeader, contentType: "application/json; charset=utf-8"]) { response ->
	if (response.status == 200 && response.data.events[0] != null) {
    	//Let's get the time for the event
    	def epochTime = Long.valueOf(response.data.events[0].eventTimestamp.toInteger()) * 1000
		def timeString = new Date(epochTime + location.timeZone.rawOffset ).format("h:mm a")
    	
        //Check events and format message
        def eventMsg = "${response.data.events[0].info} @ ${timeString}"
		sendEvent(name: "events", value: eventMsg)
		log.info "Events: $eventMsg"
    }
}

@tobycth3, I just sent you a pull request to your GitHub repository. That might make it easier for us to work on this together. Let me know if you are good with that and want to merge from there. Otherwise I can keep posting things up here and you can manually insert them.

Updated code posted to GitHub. Several fixes and started working on the framework for sensor alerts.

I am going to try and force my SS2 to give me a message this weekend. Low battery, no communication, etc
 Just something to see if I can figure out what the right call is to get messages.

oh! I like this change. nice. :slight_smile:

oh! I am also post number 666. :slight_smile:

I am getting Push notifications with Alarm Arm/Disarm events with these updates - 90% sure I did not before. Is there an option not too? For a short time, I had a mobile number in the field in the SA and the option for DO NOT send both - but I was also getting both. I have since blanked out the mobile number, so now I am just getting push.

I am on the 2/7/2018 SmartApp and the 2/9/2018 DTH. I have SS send me SMS, so I do not need any messages from ST.

thank you for all your hard work. its refreshing to see you working together. it benefits everyone. the dth changes alarm states on my ss2 just fine again. i wiped it from the ide in locations tab. added new code, added updated dth and created a device. set the device with username/pass/ss#. im not even sure ill install the smartapp if i can toggle alarm modes with webcore.

can the smartapp switch one switch per mode. im only seeing the option to select switches and modes, nothing to define switch a is on when mode is away

@tobycth3 - First of all thank you for all the hard work in creating the original handler and getting this new one up so fast (and everyone else who helped). I’m doing a little testing and I noticed that when setting the alarm to “Away”, it takes about 3 minutes for the app to reflect that it is in AWAY mode in both the app and SHM.

I created a simulator in the IDE and noticed that in the log there is a long delay between something called “Exit Delay” and the “Away” notification. Here is the log: notice the long lag between 12:29:13 and 12:32:40.

I’m kind of new to this, Anyway to speed this up?

I too was getting notifications when I didn’t used to. Try using the code below as a replacement to the SmartApp code. Once installed and activated, goto the smart app settings and select the correct options for notifications. Let me know if this corrects your issue. I need to get with Toby about rolling this into the GitHub page.

/**
 *  SimpliSafe Monitor
 *
 *  Author: toby@cth3.com
 *  Date: 2/7/2018
 *
 *  Monitors and controls the state of a SimpliSafe alarm system, syncs with Smart Home Monitor and can turn on/off switches based on SimpliSafe state.
 *  Works in conjunction with SimpliSafe Alarm Integration device type.
 */


// Automatically generated. Make future change here.
definition(
    name: "SimpliSafe Monitor",
    namespace: "tobycth3",
    author: "Toby Harris",
    description: "Monitors and controlls the state of a SimpliSafe alarm system, syncs with Smart Home Monitor and can turn on/off switchs based on SimpliSafe state. Works in conjunction with SimpliSafe Alarm Integration device type.",
    category: "Safety & Security",
    iconUrl: "https://pbs.twimg.com/profile_images/594250179215241217/LOjVA4Yf.jpg",
    iconX2Url: "https://pbs.twimg.com/profile_images/594250179215241217/LOjVA4Yf.jpg")

preferences {
  section("Monitor and control this SimpliSafe alarm system") {
    input "alarmsystem", "capability.alarm", title: "Select alarm system"
  }
  
  section("Control these switchs") {
	input "alarmtile", "capability.switch", title: "Select switches", multiple: true, required: false  
  } 
  
  section("Turn on switchs when SimpliSafe state matches") {
    input "alarmon", "enum", title: "Select on state", multiple: true, required: false, metadata:[values:["off", "home", "away"]]
  }
  
  section("Turn off switchs when SimpliSafe state matches") {
    input "alarmoff", "enum", title: "Select off state", multiple: true, required: false, metadata:[values:["off", "home", "away"]]
  }
  
  section("Notifications"){
  	input("recipients", "contact", title: "Send notifications to", required: false) {
    	input "sendPushMessage", "enum", title: "Send a push notification?", options: ["Yes", "No"], required: false
    	input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
        paragraph "If outside the US please make sure to enter the proper country code"
 	}
  }
}

def installed() {
  init()
  }

def updated() {
  unsubscribe()
  unschedule()
  init()
  }
  
def init() {
  subscribe(alarmsystem, "alarm", alarmstate)
  subscribe(location, "alarmSystemStatus", shmaction)
  }
  
def updatestate() {
	log.info("Checking SimpliSafe and Smart Home Monitor state")
	state.alarmstate = alarmsystem.currentState("alarm").value.toLowerCase()
	state.shmstate = location.currentState("alarmSystemStatus").value.toLowerCase()
	log.debug("SimpliSafe: '$state.alarmstate', Smart Home Monitor: '$state.shmstate'")
	
}

def shmaction(evt) {
log.info "Smart Home Monitor: $evt.displayName - $evt.value"
state.shmstate_raw = evt.value
state.shmstate = state.shmstate_raw.toLowerCase()

  if(shmOff && !alarmOff) {
    log.debug("Smart Home Monitor: '$state.shmstate', SimpliSafe: '$state.alarmstate'")
     setalarmoff()
  }
 else {
  if(shmAway && !alarmAway) {
    log.debug("Smart Home Monitor: '$state.shmstate', SimpliSafe: '$state.alarmstate'")
     setalarmaway()
  }
 else {
  if(shmStay && !alarmHome) {
    log.debug("Smart Home Monitor: '$state.shmstate', SimpliSafe: '$state.alarmstate'")
     setalarmhome()
  }
  else {
    log.debug("No condition match Smart Home Monitor: '$state.shmstate', SimpliSafe: '$state.alarmstate'")
   }  
  }
 }
}

def alarmstate(evt) {
log.info "SimpliSafe Alarm: $evt.displayName - $evt.value"
state.alarmstate_raw = evt.value
state.alarmstate = state.alarmstate_raw.toLowerCase()

  if (alarmOff && !shmOff) {
    log.debug("SimpliSafe: '$state.alarmstate', Smart Home Monitor: '$state.shmstate'")
     setshmoff()
  }
 else {
  if (alarmAway && !shmAway) {
    log.debug("SimpliSafe: '$state.alarmstate', Smart Home Monitor: '$state.shmstate'")
     setshmaway()
  }
 else {
  if (alarmHome && !shmStay) {
    log.debug("SimpliSafe: '$state.alarmstate', Smart Home Monitor: '$state.shmstate'")
     setshmstay()
  }
  else {
    log.debug("No condition match SimpliSafe: '$state.alarmstate', Smart Home Monitor: '$state.shmstate'")
  }
 }
}
  
  if (state.alarmstate in alarmon) {
    log.debug("SimpliSafe state: $state.alarmstate")
     alarmstateon()
  }
 else {
  if (state.alarmstate in alarmoff) {
    log.debug("SimpliSafe state: $state.alarmstate")
     alarmstateoff()
  }
 else {
    log.debug("No switch actions set for SimpliSafe state '${state.alarmstate}'")
    }
   }  
  }

def setalarmoff() {
	updatestate()
      log.debug("SimpliSafe: '$state.alarmstate'")
      if (!alarmOff) {
      def message = "Setting SimpliSafe to Off"
      log.info(message)
      sendMessage(message)
      alarmsystem.off()
  }
  else {
	 if (alarmOff) {  
     log.debug("SimpliSafe already set to '$state.alarmstate'")
  }
 }
}
  
def setalarmaway() {
	updatestate()
      log.debug("SimpliSafe: '$state.alarmstate'")
      if (!alarmAway) {
      def message = "Setting SimpliSafe to Away"
      log.info(message)
      sendMessage(message)
      alarmsystem.away()
  }
  else {
	 if (alarmAway) {  
     log.debug("SimpliSafe already set to '$state.alarmstate'")
  }
 }
}
  
def setalarmhome() {
	updatestate()
      log.debug("SimpliSafe: '$state.alarmstate'")
      if (!alarmHome) {
      def message = "Setting SimpliSafe to Home"
      log.info(message)
      sendMessage(message)
      alarmsystem.home()
  }
  else {
	 if (alarmHome) {  
     log.debug("SimpliSafe already set to '$state.alarmstate'")
  }
 }
}

def setshmoff() {
	updatestate()
      log.debug("Smart Home Monitor: '$state.shmstate'")
      if (!shmOff) {
      def message = "Setting Smart Home Monitor to Off"
      log.info(message)
      sendMessage(message)
      sendLocationEvent(name: "alarmSystemStatus", value: "off")
  }
  else {
	 if (shmOff) {  
     log.debug("Smart Home Monitor already set to '$state.shmstate'")
  }
 }
}
  
def setshmaway() {
	updatestate()
      log.debug("Smart Home Monitor: '$state.shmstate'")
      if (!shmAway) {
      def message = "Setting Smart Home Monitor to Away"
      log.info(message)
      sendMessage(message)
      sendLocationEvent(name: "alarmSystemStatus", value: "away")
  }
  else {
	 if (shmAway) {  
     log.debug("Smart Home Monitor already set to '$state.shmstate'")
  }
 }
}
  
def setshmstay() {
	updatestate()
      log.debug("Smart Home Monitor: '$state.shmstate'")
      if (!shmStay) {
      def message = "Setting Smart Home Monitor to Stay"
      log.info(message)
      sendMessage(message)
      sendLocationEvent(name: "alarmSystemStatus", value: "stay")
  }
  else {
	 if (shmStay) {  
     log.debug("Smart Home Monitor already set to '$state.shmstate'")
  }
 }
}

def alarmstateon() {
    log.debug ("Setting switches to on")
      alarmtile?.on()
  }
  
def alarmstateoff() {
    log.debug ("Setting switches to off")
      alarmtile?.off()
  } 
  
// TODO - centralize somehow
private getalarmOff() {
	def result = false
	if (state.alarmstate == "off") {
	result = true }
	log.trace "alarmOff = $result"
	result
}

private getalarmAway() {
	def result = false
	if (state.alarmstate == "away") {
	result = true }
	log.trace "alarmAway = $result"
	result
}

private getalarmHome() {
	def result = false
	if (state.alarmstate == "home") {
	result = true }
	log.trace "alarmHome = $result"
	result
}

private getshmOff() {
	def result = false
	if (state.shmstate == "off") {
	result = true }
	log.trace "shmOff = $result"
	result
}

private getshmAway() {
	def result = false
	if (state.shmstate == "away") {
	result = true }
	log.trace "shmAway = $result"
	result
}

private getshmStay() {
	def result = false
	if (state.shmstate == "stay") {
	result = true }
	log.trace "shmStay = $result"
	result
}
  
private sendMessage(msg) {
	Map options = [:]
    
	if (location.contactBookEnabled && recipients) {
		sendNotificationToContacts(msg, recipients, options)
	} else {
    	if (phone) {
        	options.phone = phone
			if (sendPushMessage && sendPushMessage != 'No') {
				log.debug 'Sending push and SMS'
				options.method = 'both'
			} else {
				log.debug 'Sending SMS'
				options.method = 'phone'
			}
        } else if (sendPushMessage && sendPushMessage != 'No') {
			log.debug 'Sending push'
			options.method = 'push'
		} else {
			log.debug 'Sending nothing'
			options.method = 'none'
		}
		sendNotification(msg, options)        
	}
}

Unfortunately at this time, no. I would have to research that more. What I ended up doing because I needed to know when a state changed and what it changed to was to utilize routines. I have one routine setup for each Alarm mode. I then went into the routine and told it to change to that routine based on the Smart Home Monitor mode (Off, Away, Home[Stay]). Then I told it to transition my Modes (at the hub level). I defined those as Off, Home, Away. And then I have whatever I need to monitor look for that transition (in my case my thermostat to change it to away mode if no one is home). I know it sounds confusing, but actually works really well.

Since this is an unofficial intergration, it only syncs every 5 minutes to
avoid unnecessary stress/traffic to the SimpliSafe servers.

I will have to play with this a little more. I think I know what is going on. If you set the alarm in SHM or the Simplisafe ST app, it typically (atleast for SS2 systems). Will timeout waiting for a response (the command always goes through). So, if the app sees a timeout event it will know to repoll for alarm state 10 seconds later. Well this works well for Home and Off as those change instantly. I can see where this wouldn’t work for Away, as you get the exitDelay that you see above. What we would have to do is to poll for the away mode an additional number of seconds later (we could get that additional number from the settings api as this is your exit delay time). I will play with this some later and see if I can’t tackle this capability.

Thanks Scott. That SA does the trick - no ST SMS or Push. Cheers.

The updated code fixed my system. Thanks to @ssilence and @tobycth3 for putting it out there.

I’m not sure if others are seeing this but whenever ST arms my system I’m getting a notification that says, “Smart Home Monitor is armed but SimpliSafe Alarm is open.” The interesting thing is that the SimpliSafe Alarm device seems to show the status matching that of my system so I’m not sure why ST is showing any open message. Has anyone else seen this? I’m really curious how to make it go away.

Yeah, not sure what Open means. That is strange. Can you copy and paste some of the logs from the api site here for us to look at it in more details.

Hey Ryan,
That is still a part that we have on our list to resolve. The previous code
would ‘open’ the contact sensor if an alarm in SS was triggered. That way
you could also trigger alerts or routines in ST. Since that part has not
been re-written yet, it may be showing open for you if you had a previous
alarm event.

1 Like

Just had a successful (unplanned) test of my smoke detectors on SS3 making Valentine’s dinner. All worked as expected with the intergration. Now just to figure out how to fix it for SS2


I don’t know if anyone answered this but I definitely think it’s worth replacing just because of the better base station design and especially because of the lighted keypads. I was lucky, though, because I didn’t have SS2 very long and they took it back and I ordered SS3.

1 Like

Yeah, I really want to upgrade to SS3, but to get an equivalent system (with sensors) would cost me over $700. So, it is on the todo list but low on the list.