Jump to content
View in the app

A better way to browse. Learn more.

Universal Devices Forum

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Subscribe to events happening on a single node?

Featured Replies

I can successfully subscribe to all events on my EISY but that is not optimal since I have 100+ nodes.

I receive a huge dump (212 kB) of the status of every node when I first connect. I am using a SOAPAction subscribe query to X_Insteon_Lighting_Service like so:

POST /services HTTP/1.1
Host: 192.168.0.212
Content-Type: text/xml; charset=utf-8
Authorization: Basic MyPassword==
Content-Length: 192
SOAPAction: "urn:udi-com:service:X_Insteon_Lighting_Service:1#Subscribe"

<s:Envelope><s:Body><u:Subscribe xmlns:u="urn:udi-com:service:X_Insteon_Lighting_Service:1"><reportURL>REUSE_SOCKET</reportURL><duration>infinite</duration></u:Subscribe></s:Body></s:Envelope>

Is there some other EISY service name I can use to receive events from only one node? Is there some parameter I can pass to X_Insteon_Lighting_Service that limits events to a single node (like 3C 80 F 1)

Note: I am not talking abou PolyGlot/Portal subscriptions. I intend to subscribe to and parse EISY event text on some local hardware running on the same LAN as the EISY.

In addition to the soap api there is the rest API.

There you'll find:

/rest/query/<node>

queries the given node

Returns: Success or Error status

EDIT: Scroll way down and there is a websockets section. Pretty sure you'd have to take all events as they came and filter on the handful you want, but you'd get just the updates coming from the ISY and opposed to getting all devices every time. Old school, I know but pre polyglot nodeservers like NODELINK made use of it and it can work well

Edited by paulbates

  • Author
26 minutes ago, paulbates said:

In addition to the soap api there is the rest API.

There you'll find:

/rest/query/<node>

queries the given node

Returns: Success or Error status

Yes, my current Arduino software uses /rest/query/<node> but due to system loading issues, this isn't working reliably for me.

Is the SOAP API documented somewhere? I tried doing a WSDL import query to get some basic documentation but was not successful. AI searches on Google indicate that the UD SOAP documentation is not up to date.

I could not get a REST subscribe/WebSockets session to work.

I reverse engineered UD Mobile and see that it is using SOAP to read/update its device screen in real-time. That method works OK for me, but it will be difficult to read the huge stream of data in an Arduino program. I am looking in to using streams and filtering out the node data I don't need.

2 hours ago, skydvrz said:

Yes, my current Arduino software uses /rest/query/<node> but due to system loading issues, this isn't working reliably for me.

Is the SOAP API documented somewhere? I tried doing a WSDL import query to get some basic documentation but was not successful. AI searches on Google indicate that the UD SOAP documentation is not up to date.

I could not get a REST subscribe/WebSockets session to work.

I reverse engineered UD Mobile and see that it is using SOAP to read/update its device screen in real-time. That method works OK for me, but it will be difficult to read the huge stream of data in an Arduino program. I am looking in to using streams and filtering out the node data I don't need.

rest/query queries the device, this is more resource intensive than a retained status lookup. Use /rest/status/address or rest/node/address instead.

If you can subscribe then you just need to parse the events. Basically any <control> which does not start with "_" is a Device Property Status Event where the control is the Property ID.

//<?xml version="1.0" encoding="UTF-8"?>
//<Event seqnum=\"113\" sid=\"uuid:90\">
//  <control>ST</control>
//  <action uom=\"2\" prec=\"0\">1</action>
//  <node>n003_po_pushover</node>
//  <eventInfo>
//  </eventInfo>
//  <fmtAct>True</fmtAct>
//  <fmtName>Last Status</fmtName>
//</Event>
  • 3 weeks later...
  • Author

I have been running my Arduino/Insteon Thermostat code for several days now. The EISY SOAP-subscription code works great! It is way more reliable than my old polling code and seems to be less EISY-cpu intense. Subscription events are very fast.

Dozens of Events are sent to my Arduino hardware on initial subscription, but then drop to a reasonable frequency. I filter out any events that do not belong to the Thermostat Node ID I am listening for. I wrote a simple XML parser that grabs the parameters out of the event stream. The reset of the code forms up an Infrared data stream that gets beamed to my AC unit.

I can think of many alternate uses for the subscription paradigm so if anyone is interested, I'd be happy to publish my full code. Here is some partial code:

	// Send the SOAP/Subscribe query (This is part of Setup())
	MyLogger(TLogDestinations(ESerial + ETCPIP), EStatus, "Subscribing to EISY");
	client.println("POST /services HTTP/1.1");
	client.printf("Host: %s\r\n", ISYAddress);
	client.println("Content-Type: text/xml; charset=utf-8");
	client.printf("Authorization: Basic %s\r\n", ISYBasicAuth);
	client.println("Content-Length: 192");
	client.println("SOAPAction: \"urn:udi-com:service:X_Insteon_Lighting_Service:1#Subscribe\"\r\n");
	client.println("<s:Envelope><s:Body><u:Subscribe xmlns:u=\"urn:udi-com:service:X_Insteon_Lighting_Service:1\"><reportURL>REUSE_SOCKET</reportURL><duration>infinite</duration></u:Subscribe></s:Body></s:Envelope>\r\n");

String ExtractString(String InString, String BeginMarker, String EndMarker) {
	int ValueBegin;
	int ValueEnd;

	ValueBegin = InString.indexOf(BeginMarker);  // try to find the BeginMarker
	if (ValueBegin >= 0) {
		ValueBegin += BeginMarker.length();                  // move past the marker
		ValueEnd = InString.indexOf(EndMarker, ValueBegin);  // try to find the EndMarker
		if (ValueEnd >= 0)
			return InString.substring(ValueBegin, ValueEnd);  // Get the string found between the two markers
		else
			return "";  // no end marker
	} else
		return "";  // no begin marker
}

// In subscribe mode, each EISY XML line contains a single variable name and value
// Something like this:
// <?xml version="1.0" encoding="UTF-8"?><Event seqnum="952" sid="uuid:89" timestamp="2025-12-01T13:04:04.212685-05:00"><control>CLISPH</control><action uom="101" prec="0">148</action><node>3C 50 F 1</node><eventInfo></eventInfo><fmtAct>74.0°</fmtAct><fmtName>Heat Setpoint</fmtName></Event>POST reuse HTTP/1.1

void Process() {
	char NodeBuff[15];
	String CurrVal;
	float fCurrVal;
	int TempVal;

	String NodeID = ExtractString(LineBuff, "<node>", "</node>");

	// We are looking for the ""hh hh hh 1" node id for an Insteon 2441TH thermostat 
	// Is this the droid we are looking for?
	if (NodeID.equals(THERMID)) {
		// Yes: Now get the thermostat varname
		String Control = ExtractString(LineBuff, "<control>", "</control>");
		Control.toCharArray(NodeBuff, sizeof(NodeBuff));

		// Now get the var value
		CurrVal = ExtractString(LineBuff, "<fmtAct>", "</fmtAct>");
		CurrVal.toCharArray(NodeBuff, sizeof(NodeBuff) - 1);

		MyLogger(TLogDestinations(ESerial + ETCPIP), EStatus, "Node Traffic: %s = %s", Control.c_str(), CurrVal.c_str());

		// now do something with the Control = CurrVal string pairs
.
.
.
.
    }
}

void loop() {
	int bytesRead;

	// Note:  This loops every time we hear an EISY event line of http header/XML.  This happens even if the event is not intended for us.
	while (true) {
		bytesRead = client.readBytesUntil('\n', LineBuff, sizeof(LineBuff) - 1);  // read single line from EISY Subscription stream
		LineBuff[bytesRead] = '\0';                                               // overwrite the \n with a string termination

		Process();  // parse the XML payload, if any.  Some lines are blank, contain HTTP Headers or are not intended for us

		if ((CurrMode != tmAuto) && (ModeChanged && SetpointTempChanged)) {
			SendIR();
			ModeChanged = false;
			SetpointTempChanged = false;
		}
	}
}

Create an account or sign in to comment

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.