Programmatically receiving notifications from Omni Controller

BobS0327

Active Member
Listed below is an excerpt from the HAI Omni Link II protocol document.  It describes how to receive notifications from the controller.  I can successfully enable notifications but am having a difficult time with receiving these notifications.  Has anybody successfully implemented notifications via code?  If so, please shed some light on how it is done.
 
 
 
NOTIFICATION MESSAGES
HAI controllers generate event notifications upon the occurrence of various changes in the controller. When the ENABLE
NOTIFICATIONS feature is enabled and a change or event occurs in the controller, the event is automatically sent to the client.
When the ENABLE NOTIFICATIONS feature is enabled, the system does not need to be polled, the notifications are automatically
sent to the client.
• Enable notifications
• Object event notifications
• Other event notifications
ENABLE NOTIFICATIONS
The ENABLE NOTIFICATIONS message requests the HAI controller to send event notifications as they occur. If the ENABLE
NOTIFICATIONS feature is disabled, the HAI controller will not send event data.
Start character 0x21
Message length 0x02
Message type 0x15
Data 1 enable byte (0=disable, 1=enable)
CRC 1 varies
CRC 2 varies
Expected reply ACKNOWLEDGE
OBJECT EVENT NOTIFICATIONS
When a zone, unit, thermostat, auxiliary sensor, area, audio zone, access control reader, access control reader lock, or message events
occurs, the HAI controller will send the respective OBJECT STATUS report message to the client.
ZONE NOTIFICATIONS:
When an event occurs with a zone (e.g. a zone becomes not ready, secure, bypassed, or restored), the
HAI controller will automatically send the ZONE STATUS message for the respective zone. See ZONE STATUS for
message details.
UNIT NOTIFICATIONS:
When an event occurs with a control unit (e.g. a unit is turned on or off, the light level of a unit changes, the value of a flag
changes, etc.), the HAI controller will automatically send the UNIT STATUS message for the respective control unit. See
UNIT STATUS for message details
 

BobS0327

Active Member
Ranger Digital said:
Is there a board or module that needs to be added to an Omni IIe to allow event notification??
Nope.  I'm using the Omni Pro II.  HAI's .Net SDK has an example app that handles notifications.  This example app works with my controller.  The only problem is that the example app is written in C# and I'm essentially writing a new app from the ground up in plain C and I'm trying to develop C code to handle event notifications from the controller.  Right now, I'm pretty much pulling at straws.  But I think I may have to implement a message pump such as  what is found in a WIN32 GUI app.
 
But to reiterate, a board or module isn't needed.   I believe it's done somehow in the client software using the TCP stack.
 
Thanx
 

aard3

Active Member
Bob,
 
When reading from the TCP Stream, you should look at the Sequence Number (it's defined in the protocol document). If it's 0x00 (zero), then the message is a notification message. You can then parse the message as if it is any other status message.
 
If the Sequence Number is non-zero, then the message is a response to a request you sent.
 
Aaron
 

BobS0327

Active Member
Aaron,
 
Thanx for the reply.  I'm having difficulty writing the C equivalent of  the HandleUnsolicitedPackets method found in Example1 from the SDK.  In other words,  I believe I may have to use a nonblocking recv function in a loop to receive the unsolicited notifications.  Unfortunately, everything I try just doesn't seem to work.    I'm using wire shark and I don't see any notification packets being sent from the controller to my client.
 
Any guidance, assistance etc would be greatly appreciated.
 
Bob
 

Ranger Digital

Active Member
Hmmm, interesting. I assumed if an Omni could sent out text or emails, there would simply be a drop down menu in PC Access whereby you just pick what you want to send out and where. Appears thats not the case. Seems crazy to me.
 

ano

Senior Member
With the email notifier board installed, it definitely can send texts and email.
 

Desert_AIP

Senior Member
Ranger Digital said:
Hmmm, interesting. I assumed if an Omni could sent out text or emails, there would simply be a drop down menu in PC Access whereby you just pick what you want to send out and where. Appears thats not the case. Seems crazy to me.
 
With the e-mailer board, you enter in the e-mail messgaes into PCAccess in the setup area.
Then, in the programming area, you select the message you want to send and to what address(es) based on what events.
 

BobS0327

Active Member
Ranger Digital said:
Hmmm, interesting. I assumed if an Omni could sent out text or emails, there would simply be a drop down menu in PC Access whereby you just pick what you want to send out and where. Appears thats not the case. Seems crazy to me.
Ranger,
Yep, as others have indicated the controller can send out text or emails.  But the notifications that I am interested in are notifications that can be programmatically received from controller.  For example, we have an Arduino that is acting as a home energy usage monitor.  We could then load the Arduino with code to monitor controller notifications sent out via TCP traffic (over the network).  This would give the Ardino the capability to know when a unit is turned off or on or the heat/AC is turned on/off.  The Arduino could store this information along with the energy usage information in some sort of database.  Review of this database would allow us to determine how energy (in)efficient our home is.
 
To reiterate, these notifications aren't of the text/email type but rather notifications sent out over the network. For lack of a better description, notifications sent out in packet form.
 

JonW

Senior Member
For those that aren't clear on what the OP is trying to do, this is all related to the OmniPro API programming.  Don't confuse OmniPro notifications with the notifier board stuff.  OmniPro notifications are messages that are sent to a client to alert for all changes that happen in the controller in real time.  As a client app, you can send a message to the controller to enable the notifications and then you will receive the continuous messages for all status updates.  This is how all the 3rd party apps keep themselves in sync with the controller.
 
OP - you will likely want to write an interrupt driven routine for receiving the messages instead of a continuous poll method.  Unfortunately, I don't have any experience with Arduino, so I can't help you on that platform.
 

aard3

Active Member
BobS0327 said:
Aaron,
 
Thanx for the reply.  I'm having difficulty writing the C equivalent of  the HandleUnsolicitedPackets method found in Example1 from the SDK.  In other words,  I believe I may have to use a nonblocking recv function in a loop to receive the unsolicited notifications.  Unfortunately, everything I try just doesn't seem to work.    I'm using wire shark and I don't see any notification packets being sent from the controller to my client.
 
Any guidance, assistance etc would be greatly appreciated.
 
Bob
Hi Bob,
 
If you aren't seeing anything being sent out via Wireshark
- Do you have wireshark configured correctly? Do you see other traffic?
- If YES, I would take a look at how you are enabling notifications (The message you are sending). Once you send that message to enable them, they should start coming. Each time you connect / disconnect, you need to re-enable them for that session.
 
We need to get that resolved before we go any further. If you are not getting notifications, really take a hard look at how you are enabling them. I don't have the docs in front of me, but I seem to recall you have to set it to 0 to disable, 255 to enable? Something like that.
 
After you start seeing the notification messages in wireshark, then you need to put some thought into your design, which is going to depend on the platform, along with what language you are using. I'm not an Arduino expert, but if it has an RTOS I would have a separate task whose only job is to service the TCP socket and place messages into a queue for someone else to handle... This one could use a blocking call.
 
If you have more of a super-loop type approach, you'll need some sort of non-blocking call that checks to see if there is data in your stream.
 
Hope that helps
 
Aaron
 

BobS0327

Active Member
If you aren't seeing anything being sent out via Wireshark
- Do you have wireshark configured correctly? Do you see other traffic?
- If YES, I would take a look at how you are enabling notifications (The message you are sending). Once you send that message to enable them, they should start coming. Each time you connect / disconnect, you need to re-enable them for that session.
 
We need to get that resolved before we go any further.
 
Aaron,
My bad on enabling notifications.  I was using the WRONG hex value.  Controller is now sending notifications.
 Listed below is the code that I am using.  Essentially, I trying to capture a Zone Not Ready notification.
 
 

typedef struct
{
    unsigned char status;
    unsigned char loop;
} zone;


typedef struct
{
    zone zones[MAX_ZONES];
} zone_stat;


 
 
 
 

/* EnableN = 1 to enable  set enableN to Zero to disable*/
    unsigned char enableN = 1; /* 1   to enable notifications*/

    if ((err = hai_net_send_msg(&id, (hai_msg_type)ENABLE_NOTIFICATIONS,  /*0X15 */
        &enableN, 1)) != 0)
        return err;
    else
        printf("Notifications enabled\n");
    

    zone_stat data;

    /* Set up socket as nonblocking  */
    u_long ulMode = 1;  // Non blocking
    ioctlsocket(id.s, FIONBIO, &ulMode);

    
    do {
        err = omni_get_notifications(&id, &data);
        if (err == 0)
            printf("Got zone status\n");
        else
        printf("Failed to get zone status\n");
    } while (err > 0);

 
Code:
 int omni_get_notifications(hai_comm_id *id, zone_stat *data)
{
    omni_msg_req_zone_stat req;
    omni_msg_zone_stat resp;
    int err, type, len;
    if ((err = omni_send_msg(id, REQUEST_OBJECT_STATUS, //  0X22
        &req, sizeof(req))) != 0)
        return err;
    /* Get zone status */
    len = sizeof(resp);
    if ((err = omni_recv_msg(id, &type,
        &resp, &len)) != 0)
        return err;

    if (type != OMNI_TYPE_ZONE_STATUS)  //  0X23
        return EOMNIRESPONSE;
    /* Return results */
    memcpy(data, &resp.data, sizeof(sys_info));
    return 0;
}

 
I'm not an Arduino expert either.  I want to implement notifications and post the C code for the Windows and *inx platforms to the internet so that others who are experienced Arduino programmers can port the code to that platform.  I've done an extensive internet search to find C code that implements notifications.  But none was found.   So, it looks like I'm charting new ground.  But anyway, I like the super loop approach such as found in HAI's Example1.
 
Again, any assistance offered would be greatly appreciated.
 
Bob
 

aard3

Active Member
You will probably want to research threading, and have a separate thread that services the TCP Socket, and then places received messages in a queue to be processed by another thread.
 
 
Unfortunately, threads are heavily dependent on the operating system (managing processes and threads is a core feature of an OS), and each does it differently. pthreads are common on unix/Linux systems,  Microsoft has it's own support for threading
 
http://msdn.microsoft.com/en-us/library/y6h8hye8.aspx
 
and every RTOS will have some sort of support. You can use preprocessor directives
 
http://www.cplusplus.com/doc/tutorial/preprocessor/
 
to make the code where it can build on different platforms.
 

JonW

Senior Member
This is Arduino, there is no multithreading.
 
BobS0327 - look at using interrupts like I mentioned above.  That is the preferred way to program an embedded controller so you don't have to sit and keep checking for data.
 
Here is an Arduino page relating to the ethernet board that refers to the interrupts to use:  http://arduino.cc/en/Main/arduinoBoardEthernet .
Within that page, they tell you to reference the AttachInterrupt function:  http://arduino.cc/en/Reference/AttachInterrupt .
 
You should be able to find many examples out there as that is going to be the standard way to interface with the ethernet board.
 

BobS0327

Active Member
JonW,
 
Thanx for the info.  At this point in time, I'm just trying to "flesh" out the previous C Windows code by adding the notifications feature. My immediate goal is to get a Windows and *nix version available.  I have a lot of C programming experience on both of these platforms.  Thus, the reason for my currently concentrating on only these two platforms.
 
I'll probably start on an Arduino port once I have the notifications issue resolved for Window/*nix.  Coding on the Arduino platform will definitely be a major learning experience/challenge for me.  I will definitely keep your links in my when I start on that Arduino endeavor.
 
Thanx again.
 
Top