DSC Binding - how to send a command string similar to keypad

Thank you all for replies!!

thanks for the confirmations. It seams I will need to try it out to see what the lag will be on my system if it’s less than 1s it should be usable. I tried the GENERAL_STATUS works fine only difficult to say what lag will there be with smart lights… they are still on the way…

@rsstephens thanks for the hint to update DSC alarm bundle to 1.8. Would have definitely lost an hour on that… Can you explain shortly this binding update. Is it enough to just download this bundle and overwrite in the addons folder or do I need to do something more? In online guide that I followed to install OpenHAB there was one command

sudo chown -hR openhab:openhab /usr/share/openhab

that I didn’t fully understood is this what needs to be done after every addon? (I’m new not only to OpenHAB but to unix to…)

For Images I was thinking that maybe I’m missing some of the functionality, thanks for the clarification, replaced it with default siren icon seems fine need to test it, don’t want to wake the neighborhood right now :slight_smile:

You can just overwrite the 1.7 bundles

Hello @intruder82,

Is it enough to just download this bundle and overwrite in the addons folder or do I need to do something more?

You can download the latest addon zip file from here. Then extract the DSC Alarm Binding and DSC Alarm Action JAR files to your openHAB addon folder. It will not overwrite your current binding version, because the name is different, so you will need to remove the older binding file. I have my openHAB server on a Windows based machine but I assume this procedure will work similarly in Unix/Linux.

In online guide that I followed to install OpenHAB there was one command

sudo chown -hR openhab:openhab /usr/share/openhab

that I didn’t fully understood is this what needs to be done after every addon?

This command is basically changing the ownership of the openHAB folder and all it’s subfolders/files to the openHAB user account and group. You shouldn’t have to run it again to make these changes.

Can you explain shortly this binding update.

This action adds the ability to send DSC commands to your alarm system using scripts and rules. Here is the wiki for the action that might help explain it in a little more detail.

@rsstephens thank you for comprehensive explanation. I removed the 1.7 DSC addon and copied 1.8 DSC Alarm Binding and DSC Alarm Action binding. Restarted Openhab and all seems to work. Except one thing the same was with the 1.7 setup to. I send “Set time/date” command
Panel message reads
500: A command has been received successfully.
502: An error has been detected
And I get Panel system error:
011: Keybus Transmit Time Timeout

Arm, Disarm functions, I get the sensor openings to. this is the only “bug” that I found… Is this known?

@JjS had this same issue also. I don’t have any idea why it returns that error. As stated earlier I run openHAB on a Windows system and I can’t seem to duplicate that error when sending the “Set time/date” command. Maybe @JjS found a solution.

My workaround, a rule run once a day, sending individual keystrokes. Enough to compensate the time drift of the control panel. I was not able to send it at once with 071 as the payload was to long. BTW: Is it possible to change this limit in the action to accept ‘*6code1HHMMmmDDYY’ or at least the date in one shot (10 bytes)?

Change 1234 sample code to master code of your panel:

import org.openhab.core.library.types.*     
import java.util.Date     
import java.text.SimpleDateFormat 
rule "dscSetTime"
when 
Time cron "0 10 21 ? * *"
then
var SimpleDateFormat df = new SimpleDateFormat( "HHmmMMddYY" )
var String Timestamp = df.format( new Date() )             
logInfo( "DSC", "Settime to:{}", Timestamp )
logInfo( "DSC", "Settime sending *")
sendDSCAlarmCommand('070','*')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending 6")
sendDSCAlarmCommand('070','6')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending c")
sendDSCAlarmCommand('070','1')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending o")
sendDSCAlarmCommand('070','2')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending d")
sendDSCAlarmCommand('070','3')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending e")
sendDSCAlarmCommand('070','4')
Thread::sleep(2000)

logInfo( "DSC", " Settime sending 1")
sendDSCAlarmCommand('070','1')
Thread::sleep(1000)

logInfo( "DSC", " Settime sending H1:{}",Timestamp.charAt(0))
sendDSCAlarmCommand('070',Timestamp.charAt(0).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending H2:{}",Timestamp.charAt(1))
sendDSCAlarmCommand('070',Timestamp.charAt(1).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending m1:{}",Timestamp.charAt(2))
sendDSCAlarmCommand('070',Timestamp.charAt(2).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending m2:{}",Timestamp.charAt(3))
sendDSCAlarmCommand('070',Timestamp.charAt(3).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending M1:{}",Timestamp.charAt(4))
sendDSCAlarmCommand('070',Timestamp.charAt(4).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending M2:{}",Timestamp.charAt(5))
sendDSCAlarmCommand('070',Timestamp.charAt(5).toString)
Thread::sleep(1000)

logInfo( "DSC", " Settime sending D1:{}",Timestamp.charAt(6))
sendDSCAlarmCommand('070',Timestamp.charAt(6).toString)
Thread::sleep(1000)

logInfo( "DSC", "Settime sending D2:{}",Timestamp.charAt(7))
sendDSCAlarmCommand('070',Timestamp.charAt(7).toString)
Thread::sleep(1000)

logInfo( "DSC", "Settime sending Y1:{}",Timestamp.charAt(8))
sendDSCAlarmCommand('070',Timestamp.charAt(8).toString)
Thread::sleep(1000)

logInfo( "DSC", "Settime sending Y2:{}",Timestamp.charAt(9))
sendDSCAlarmCommand('070',Timestamp.charAt(9).toString)
Thread::sleep(2000)

logInfo( "DSC", "Settime sending #")
sendDSCAlarmCommand('070','#')

logInfo( "DSC", "Settime done")

end
1 Like

Hello @JjS,

Great workaround. I am glad to see you got a solution to this issue. Thanks for your response.

BTW: Is it possible to change this limit in the action to accept ‘*6code1HHMMmmDDYY’ or at least the date in one shot (10 bytes)?

I don’t think it will be possible, sorry. The limitation is built into the binding API itself which is actually based on the Envisalink’s keystroke limit for the ‘071’ command. It is a pre-check the API does before sending the command and logs an error if the keystroke length is over 6. All the action does is pass the command and info to the binding API, therefore it needs to comply with the limitations in order to work. It would be nice if the Envisalink allowed more keystrokes in the command, unfortunately it doesn’t. I guess they have their reasons for the limit.

This is a good workaround. I was doing something similar with my Haiku system setting my Omnipro security/automation board daily to keep everything synced with NTP.

Works for me too. I had to add another couple of digit transmissions as I’m using 6 digit codes on my system. But that worked as expected.

Don’t suppose you know whether the panel will tolerate this time update while it’s armed? Or will it go into alarm?! i.e. should I be checking to see if it’s armed before sending this?

Thanks!

I can also confirm sending arming codes too.

rule "DSC ARM"
when
	Item armAlarm changed
then
	sendDSCAlarmCommand("030", "1")

Works like a charm, Away arming the system.

Hi @rsstephens,

I am working on getting the DSC action working. I have an IT100 over TCP trying to send the Single Keystroke command (070).

From IT100 developer’s manual, it states that “To accomodate this requirement, each simulated Keypress (070, D, XX, CR/LF) command must be followed by a keybreak (070, ^, F5, CR/LF)”

When I try to send the sendDSCAlarmCommand(“070”,"^"), I got

sendCommand(): ‘keystroke’ must be a single character string from 0 to 9, *, #, or A, it was: ^

Just wondering would the IT100 still take the keystroke when not keybreak was sent?

Thanks,
Joe

Hello @goodfore,

Unfortunately, at this point, the ‘keystroke’ internal API command doesn’t support all the characters for the IT100, which includes ‘^’ key break character. The binding was originally built around the Envisalink TPI protocol, although similar to the IT100 API, it has its differences this being one of them. The ‘keystroke’ command for the Envisalink only allows for the characters 0-9, *, #, and A, and that’s why you are seeing that message. You can try it with out the ‘^’ character but I’m not sure how that will turn out.

Incorporating the extra characters for the IT100 will require a programming change, and looking at the specifications for the IT100, the ‘keybreak’ character requires at least a 1.5 second delay before sending it after the previous character. So it is a little more complicated than just allowing for those characters to pass. I will look into making the changes, but not sure how long it will be. Sorry for the inconvenience.

Hi @rsstephens,

Thank you for the swift response.

I have tried sending the command over without the key break (^), it doesn’t seem to work. I think the IT 100 needs that key break to work.

Looking over the spec, I think the 1.5 second delay is only required if we are trying to send in a long press. Otherwise, the key break can be sent immediately after the key code.

Looking thru the code, with my limited knowledge of openhab source, I think we can modify the 070 case inside openhab/bundles/binding/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/protocol/API.java

case KeyStroke: /* 070 */
        if (interfaceType.equals(DSCAlarmInterfaceType.ENVISALINK)) {
                    if (apiData[0] == null || apiData[0].length() != 1 || !apiData[0].matches("[0-9]|A|#|\\*")) {
                        logger.error("sendCommand(): \'keystroke\' must be a single character string from 0 to 9, *, #, or A, it was: {}", apiData[0]);
                        break;
                    }
        } else if (interfaceType.equals(DSCAlarmInterfaceType.IT100)) {
                    if (apiData[0] == null || apiData[0].length() != 1 || !apiData[0].matches("[0-9]|\\^|#|\\*")) {
                        logger.error("sendCommand(): \'keystroke\' must be a single character string from 0 to 9, *, #, or ^, it was: {}", apiData[0]);
                        break;
                    }
        } else {
                     break;
        }
        data = apiData[0];
        validCommand = true;
        break;

Not sure if the ^ needs escape. Not the nicest code nor the complete, but I think this can get us started.
I don’t have an IDE setup, if someone can compile a jar, I can test it.

Thanks

Hello @goodfore,

Your exactly right the delay is only required for a long key press, and what you have there would work. I think you do have to escape the ^ character as it is a special character in regular expressions. I don’t have the IDE setup at the moment either, at least it’s not current. I might be able to get to it this weekend and have you a compiled jar to test.

Hi @rsstephens,

Thank you so much for your help. No rush, whenever you are available.

Hello @goodfore,

I have a .jar file you can test located here. I instituted your code plus I allowed for all keystrokes according to the documentation. Also, I put in the possibility to perform a long key press by implementing a slight delay when the character ‘L’ is received through the sendDSCAlarmCommand (ex. sendDSCAlarmCommand(“070”, “L”), not sure how it is going to work. This will only work for the IT100 and you would need to follow it with the key break character ‘^’. Try it out let us know how it goes. Thanks.

Hi @rsstephens,

Thank you very much for putting the jar together.

I have tried the jar. I tried the “^” key and function 3 (“c”), both seems to be wrong great. Also the 1-9, * and # is working as they should.

I also try to use the special long press key, (“L”), but can’t get it to work.

I tried
sendDSCAlarmCommand(“070”,“c”)
sendDSCAlarmCommand(“070”,“L”)
sendDSCAlarmCommand(“070”,"^")

Doesn’t do anything, but if I do

        sendDSCAlarmCommand("070","c")
        Thread::sleep(1500)
        sendDSCAlarmCommand("070","^")

It does what it supposes to do.

Thanks

Hello @goodfore,

Thank you for testing this. I’m glad it is mostly working. To bad the long key press delay isn’t working. I’m thinking it is because there are separate threads running and the delay in the binding has no effect on the rule. Oh well it was a good try. It seems to work when the delay is in the rule itself. Maybe that is the way to do it at this point. Thanks.

Hello @goodfore,

I figured out why the long key press delay wasn’t working. If you are still willing to test the new .jar file is located here. Now, instead of sending a break key (’^’) after the long key press (‘L’), just send the long key press. So, you would only need to have the following in the rule:

sendDSCAlarmCommand(“070”,“c”)
sendDSCAlarmCommand(“070”,“L”)

I know you can get the same results in the rule, but it is just another way of doing it. I appreciate your feedback. Hope this helps. Thank you.

Hi @rsstephens,

Thanks for looking this. I gave the new jar a try. It’s working as expected.

I finally got the IDE setup and working on some issues I found with the IT100.

  1. the zone bypass status doesn’t seem to work
  2. the “040”, disarm command doesn’t seem to work either.

For issue #1, I found out that IT 100 only send zone bypass status update if the zone is bypassed by the IT100. For example if I send a “*108#” using the 070 command (sending the characters individually), IT 100 will send a 901 update with message along the line of “Zone 08 B”, with B being bypassed and O being armed.

I tweaked the code a bit for DSCAlarmActiveBinding/dscAlarmEventRecieved adding

case LCDUpdate: /* 901 */
                if (interfaceType.equals(DSCAlarmInterfaceType.IT100)) {

                    if (apiData.substring(5, 9).equals("Zone")) {
                        logger.debug(
                                "dscAlarmEventRecieved(): Event 901 received, zone status update detected! Looking for zone: {}",
                                dscAlarmItemType);
                        int aZone = Integer.parseInt(apiData.substring(13, 15));
                        if (String.valueOf(apiData.charAt(apiData.length() - 1)).equals("O")) {
                            updateItemType(DSCAlarmItemType.ZONE_BYPASS_MODE, 1, aZone, 0);
                        } else if (String.valueOf(apiData.charAt(apiData.length() - 1)).equals("B")) {
                            updateItemType(DSCAlarmItemType.ZONE_BYPASS_MODE, 1, aZone, 1);
                        }
                    }
                }
                break;

As you can tell, there is no way to tell which partition the zone is in from the message, so I don’t this solution is good enough for general use.

For issue #2, I have not start looking into it. Would you have any insight on why it isn’t working?

Thanks