Intelliflow pump RS485 protocol

Thanks.  Did that (solved that problem), and did full update just to be sure.  But I still get the exact same crash as before:
 


16:17:28.041 SILLY after push packet: 255,0,255,165,10,16,34,209,1,10,1,189 Message: 165,10,16,34,209,1,10,1,189
16:17:28.049 VERBOSE Just Queued Message to send: 255,0,255,165,10,16,34,209,1,11,1,190
16:17:28.056 SILLY after push packet: 255,0,255,165,10,16,34,209,1,11,1,190 Message: 165,10,16,34,209,1,11,1,190
16:17:28.064 VERBOSE Just Queued Message to send: 255,0,255,165,10,16,34,209,1,12,1,191
16:17:28.072 SILLY after push packet: 255,0,255,165,10,16,34,209,1,12,1,191 Message: 165,10,16,34,209,1,12,1,191
16:17:28.089 VERBOSE Wrote 255,0,255,165,10,16,34,200,1,0,1,170 and # of bytes undefined Error?: null

/home/pi/pool2/index.js:618
if (b.data == 0) {
^
TypeError: Cannot read property '0' of undefined
at SerialPort.<anonymous> (/home/pi/pool2/index.js:618:35)
at SerialPort.emit (events.js:95:17)
at SerialPort.module.exports.raw (/home/pi/pool2/node_modules/serialport/lib/parsers.js:7:13)
at SerialPort._emitData (/home/pi/pool2/node_modules/serialport/lib/serialport.js:310:18)
at SerialPort.<anonymous> (/home/pi/pool2/node_modules/serialport/lib/serialport.js:290:14)
at SerialPort.<anonymous> (/home/pi/pool2/node_modules/serialport/lib/serialport.js:303:7)
at Object.wrapper [as oncomplete] (fs.js:466:17)


What version of node and npm are you using?
 
Node v4.4.3
NPM v2.15.1
 
Can you add the following line right before 618 (the one causing the error) and add
 

logger.warn('b: ', b ) ;
 
 
 
It will spit out 'b' and at least give us an idea why it's crashing.
It should spit out b.data and whatever else is in there.  Maybe that will give us a clue!
 
Here is a sample of what my output looks like:
Code:
16:12:13.461 VERBOSE Sending packet: 255,0,255,165,10,16,34,202,1,6,1,178
16:12:13.463 VERBOSE Wrote 255,0,255,165,10,16,34,202,1,6,1,178 and # of bytes 12
16:12:13.574 WARN b: 
	{"type":"Buffer","data":[255,255,255,255,255,255,255,255,0,255,165,10,15,16,10,12,6,85,83,69,82,78,65,77,69,45,48,55,3,222]}
16:12:13.575 WARN b: 
	{"type":"Buffer","data":[255,255,255,255,255,255,255,255,0,255,165,10,15,16,10,12,6,85,83,69,82,78,65,77,69,45,48,55,3,222]}
16:12:13.576 WARN b: 
	{"type":"Buffer","data":[255,255,255,255,255,255,255,255,0,255,165,10,15,16,10,12,6,85,83,69,82,78,65,77,69,45,48,55,3,222]}
16:12:13.577 WARN b: 
	{"type":"Buffer","data":[255,255,255,255,255,255,255,255,0,255,165,10,15,16,10,12,6,85,83,69,82,78,65,77,69,45,48,55,3,222]}
 
I am going to first do a clean re-install on my Pi.  I think I might have some trash left over from prior projects.  I upgraded to the same Node and npm as yours, and got all modules loaded with same versions as yours, but I get dozens of errors when trying to install serialport.  Best just to start from scratch I think.  
 
EDIT: ah, I think I need g++ 4.8 installed.  I was on 4.7.  Will try that.
 
EDIT2: that did not help.  Did a clean resinstall with new Wheezy.  Got your version of Node and NPM.  But still get many, many errors trying to install serialport.  Upgraded to g++4.8, still no joy.  I am reading that the Armv6 version of serialport is badly broken right now.  I might try again but on a Pi3 vs the old Pi1B I was using.  
 
OK, finally got my RPi1 updated with the correct versions.  Your program is working now, showing all the flow of data to and from the pump (on the Pi terminal screen running 'node index.js').  So that is good!
 
Looking at the web page, under pumps, I get this:
Capture.PNG
 
So no pump data.  I also tried to do the JSON call with /pump and got:
 
["blank",{},{}] 
 
Here is a clip of data flow shown on my screen in Debug mode.  
View attachment debug.txt
 
 
EDIT: I stripped out the line that queries for circuits/names since I have none of that.  That simplified the data a bit more.  Your program is capturing all communications just perfectly.  
View attachment stripped.txt
 
blueman2 said:
The data flow seems to indicate your program is getting all the right data from the pump, but is not showing on the screen. 
 
Glad you got it up and running!  I suspect because there are differences in your Intematic vs. the Intellitouch that it may not be picking these up pump messages properly.  I'm propagating this information from the broadcast from the Intellitouch to the Screenlogic (or generic broadcast).  
 
The messages like

16:04:04.368 VERBOSE Msg# 15 Main sent response _undefined, undefined_ to write command: [96,16,1,4,3,33,0,16,1,78]

 
are more relevant to many of the others here in this group that read/write directly to/from the pumps.  Most of my code deals with the Intellitouch messages, but I do have the ability to easily add decoding for these.  I'd be happy to work with you, or anyone else, to include the interpretation of these messages more fully in my code.  It might even be possible to populate the UI (or API) with this information directly from the pumps, but again, that hasn't been my primary focus.
 
It would be great to combine all of the efforts of others here and myself into a single codebase if there is interest.  EG a program that would be able to run with or without Intellitouch; with or without Intematic; with or without any 3rd party integrations etc.  
 
In the next release of the code, I'll include a bit you can toggle to enable/disable the initial pump commands so it will be more straightforward for you.
 
Can anyone here provide a succinct interpretation of the pump messages?  I'll be happy, again, to incorporate into my code and add it to my wiki.  EG clearly Intellitouch gets the RPM/watts from the messages from the pump and as a fallback I could use these to get the pump status for scenarios where the Intellitouch isn't present.
 
tag
 
Thanks!  I was just now working on adding all the interpretations for messages sent by the IntelliComII to the pump. I have done a lot of research on this and think I know most of them.  I will try to add that into your code and send you what I come up with, if that works for you.  I was going to put in info for things like setting pump speed settings, etc:
 
action   data               data explanation
====  ========   ====================================================================
<01>  <03><21> = Set current speed to speed setting <00><08>=1, <00><10>=2, <00><18>=3, <00><20>=4
<01>  <03><27> = Set Speed Setting 1 to speed <xx><xx> in rpm
<01>  <03><28> = Set Speed Setting 2 to speed <xx><xx> in rpm
<01>  <03><29> = Set Speed Setting 3 to speed <xx><xx> in rpm
<01>  <03><2A> = Set Speed Setting 4 to speed <xx><xx> in rpm
<01>  <03><2B> = Set timer to <xx><xx> minutes (or maybe <hr><mn>?)
<04>  <00>         = set pump to local
<04>  <FF>        = set pump to remote
<06>  <04>         = Turn pump off
<06>  <0A>         = Turn pump on
 
 
BTW, I was able to get your debug web screen to display messages!  I forgot that I needed to add all 3 data elements or it would not output.  So that is working great. 
 
The only thing I was not able to figure out was how to send the packet to the pump to tell it to provide a status update.  I was thinking that putting in /pump for the GET command would trigger that, but did not find that in your code.  Thus the blank response.  
 
And yes, I MUCH prefer one set of code.  So adding the ability for someone to use this who only has a VS and an IntelliComII (which is basically what I have) would be wonderful.   I will be happy do to whatever I can to support this. 
 
blueman2 said:
The only thing I was not able to figure out was how to send the packet to the pump to tell it to provide a status update.  I was thinking that putting in /pump for the GET command would trigger that, but did not find that in your code.  Thus the blank response.  
 
It's here.  But again, this is the request to the Intellitouch.  I'm not sure what would be the command to send directly to the pumps.
 
tag
 
Well, I just decided to insert that Pump Status request data in the areas of your code where you do the query for heater status, etc.  
 


function getConfiguration(callback) {
sp.drain();
logger.verbose('Queueing messages to retrieve Pump Status')

//get Pump Status
queuePacket([165, 0, 96, 16, 7, 0]);


}

 

 
 
And sure enough I got the desired response, which was a very long string with all the pump status.  
 


18:52:47.884 INFO
*******************************
Important:
Configuration is now read from your pool. The application will send the commands to retrieve the custom names and circuit names.
It will dynamically load as the information is parsed.
Visit http://_your_machine_name_:3000 to see a basic UI
Visit http://_your_machine_name_:3000/debug.html for a way to listen for specific messages

*******************************
18:52:53.391 VERBOSE Express Server listening at port 3000
18:52:53.421 VERBOSE Serial Port opened
18:52:53.433 VERBOSE Queueing messages to retrieve Pump Status
18:52:53.450 VERBOSE Just Queued Message to send: 255,0,255,165,0,96,16,7,0,1,28
18:52:53.460 VERBOSE Sending packet: 255,0,255,165,0,96,16,7,0,1,28
18:52:53.497 VERBOSE Wrote 255,0,255,165,0,96,16,7,0,1,28 and # of bytes undefined Error?: null
18:52:54.809 INFO Msg# 2 is UNKNOWN: [16,96,7,15,10,0,0,0,87,2,238,0,0,0,0,0,1,19,1,2,145]
18:52:54.850 INFO Msg# 2 is UNKNOWN: [16,96,7,15,10,0,0,0,87,2,238,0,0,0,0,0,1,19,1,2,145]


 

There is a portion of your code that should have caught this and put the values into the status variable for this.  At least, that is the way I interpreted your code at line 1031 "Case 7".  Not sure why it did not pick it up.  But this is VERY cool!!!!
 
 
EDIT: I did notice that the page in your WIKI that provides details on the Pump Status response is off a bit compared to what I am seeing with my pump.  Here is what I am seeing from my pump:
 
Byte      Meaning
1  Dest (usually 16) //note, I had this listed incorrectly as 10 before, meaning 10 hex.  But correct is 16 dec.  
2  Source (usually 96)
3  Action (7 in this case)
4  length (15 in this case)
5 Pump On or Off (10 for on, 4 for off)
6 Mode (???)
7 pmp (??)
8  Watts high byte
9  Watts low byte
10  rpm high byte
11  rpm low byte
12 GPM 
13 ??
14 PPC
15 ??
16 ?? (reported in some posts as 'Error', but I think it is Hrs for Timer, with 17 being Mins) 
17 timer, how long before pump shuts off
18  hours
19  minutes
20  checksum
21  checksum
 
Tag,
 
As far as added functionality to your code, here is what I was looking to accomplish:
 
1) Ability to send data via HTTP URL GET format from your program to other devices.  In my case, the other device is an ISY home automation system which allows you to set variables using http URL format.  This would allow my home automation system to always know the status of my pump.  For others, it would allow their ISY to always know the value of any variable they want.  Format is
 
http://<user>:<pwd>@<ISY address>/rest/vars/set/<1>/<8>/ ; where 1=type of variable (1 or 2) and 8=variable number (0-255)
 
I only send the variables when they change.  My send function (in c) was:
 

void ISY_snd(int var, int value) //This function sends REST data to my ISY
{
CURL *curl;
char user[] = "user";
char password[] = "passwd";
char ISYip[] = "192.168.1.145";
char url[100] = "";
FILE* devnull = fopen("nul", "w"); //null file to send ISY response to
snprintf(url,sizeof(url),"http://%s:%s@%s/rest/vars/set/2/%d/%d",user,password,ISYip,var,value);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, devnull); //supresses return message from the ISY
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return;

 
 
 
2) Ability to accept commands from a JSON GET sent to your program.  For me, the commands would be to turn pump off and On by triggering one of the 4 internal speeds in the pump.  This would be very similar to the IntelliComII module.
 
I think I can hack the first into your code pretty easily, and over time even the latter.  But it would be very cool if this could be configured via web interface somehow.  That would allow others to do the same integration of their Pentair system with other systems such as home automation.  
 
blueman2 said:
There is a portion of your code that should have caught this and put the values into the status variable for this.  At least, that is the way I interpreted your code at line 1031 "Case 7".  Not sure why it did not pick it up.  But this is VERY cool!!!!
 
I'm not in front of my dev computer (away this weekend), but I may have to rework some code.  The packets are coming through as 165,X,DEST,SRC,... etc.  Right now I'm dropping the 165,X portion when I do the Checksum calculation.  I believe, but haven't verified, that 165,10 relates to Intellitouch controller messages;  165,7 (although this could be 165,0... need to double check) relates to the pump messages.  Line 1031 would be looking at 165,10,DEST,SRC,*7* and not the 165,*7* messages.
 
Right now, the 16,96,7 message you are seeing would be evaluated in the Switch command at line 1414.  But you can see that I have no case 7 there so it is spitting out the "Unknown" message from Default case at line 1488.
 
I'll look into the other stuff more in-depth at the end of the weekend, but can continue to answer some basic questions to help you out for now.
 
Everything in my world (No intellitouch controller, only pump + IntelliComII) is FF-00-FF-A5-00.  Never anything following A5 other than 00.  
 
A potential future state for your code would be a configuration flag for 
 
1) people with Intellitouch controller (basically, what you have written so far)
2) people with only a pump, and no controller
3) people with a pump and the IntelliComII  controller (or 3rd party controller like my Intermatic Muti-wave)
 
#1 is what you have now, so nothing for me to add there.
 
#2 requires the ability to mimic the iComII code Michael wrote.  When the IntelliComII is set to ON, it sends a message to the pump every 10 seconds or so to go into remote mode, turn on to the speed that the intellicom wants, sets the pump timer for 1 minute, then returns the pump to local mode.  When there is no request to the IntelliCom for a pump speed, it sends nothing. So no traffic whatsoever when not in use.   Only difference between my Intermatic Multi-wave controller and the Pentair IntelliComII is the mine leave the pump in remote mode at all times, whereas the IntelliComII returns it to local mode after each command.  
 
#3 requires 2 parts.  First, the ability to monitor requests from the IntelliComII TO the pump, providing hooks to write this data out for other devices to use (HTTP/URL format curls).   Second, and more difficult, is the ability allows other programs to write HTTP GET commands to your software to turn the pump on/off/speed1-2-3-4, and to request full pump status.  Of course, to do this, you will have to break the link between the Pump and the iComII using the "man in the middle" concept as you put it.  Otherwise, the IntelliCom (or my Intermatic) will overwrite the command you just gave the pump.       
 
It would be great to have the same code base for all 3 scenarios.  And makes it easier to add other scenarios in the future that I might not have considered. 
 
Tag, just a quick update.  I have been very successfully using your code (well, a stripped down version of it) to monitor my pool for the past week.  No issues at all from a monitoring standpoint.  It successfully decodes all the commands provided by the Intermatic Multi-wave controller and sends them to my ISY home automation controller so that I can run programs based on pool pump status.  I love it!  
 
The only thing that I find unreliable is the ability to send a query to the pump for its status and then get a reply consistently.  I send the request every other cycle of data, in the 'dead' 8 or so seconds between requests.  It appears to send just fine based on the logging in your program.  However, I only get a response from the pump sporadically.  No rhyme or reason to it either.  Sometimes is responds immediately.  Other times it will go for several minutes without responding.  Not sure what I am doing wrong, but I plan to wait for your next code drop before I try to resolve it. But for what I need, this is great.  
 
Somewhere down the road, perhaps we can get the 'man in the middle' concept to work, but I fear that will be rather complex.  
 
Thanks again for sharing your great work!
 
Blueman,
great to hear.  I've been working hard over the past couple weeks on some new changes.  Hopefully, I can post it tonight with more details.
 
Based on your 3 scenarios
1) people with Intellitouch controller (basically, what you have written so far)
2) people with only a pump, and no controller
3) people with a pump and the IntelliComII  controller (or 3rd party controller like my Intermatic Muti-wave)
 
I believe (and y'all will need to test) that I can automatically determine this.
1.  Intellitouch has Address 16.
2.  IntellicomII has Address 10.
 
The logic goes, that if the app detects:
- Address 16, it will send the configuration commands and retrieve the pump status from the Intellitouch controller.  
- Address 10 is detected, it will not send the configuration commands and populate the pump status directly from the pump responses.
- Neither of these, it will just listen.
 
There do also seem to be differences in the packets between what you posted and I see, so that will need to be worked out but I put in as much as I could now.  I also will need help understanding what else needs to be specifically coded in for the IntellicomII.
 
I'll need to understand you 'unreliable is the ability to send a query to the pump for its status and then get a reply consistently' situation a little more too be able to help out here.
 
tag said:
I believe (and y'all will need to test) that I can automatically determine this.
1.  Intellitouch has Address 16.
2.  IntellicomII has Address 10.
 
The logic goes, that if the app detects:
- Address 16, it will send the configuration commands and retrieve the pump status from the Intellitouch controller.  
- Address 10 is detected, it will not send the configuration commands and populate the pump status directly from the pump responses.
- Neither of these, it will just listed.
 
Well, perhaps I mixed Hex vs Dec in some of my posts.  But I thought (I will confirm) both the IntelliTouch and the IntellicomII are both 0x10, or 16 decimal. At least, my Intermatic MultiWave system uses 16 (0x10)     
 
blueman2 said:
Well, perhaps I mixed Hex vs Dec in some of my posts.  But I thought (I will confirm) both the IntelliTouch and the IntellicomII are both 0x10, or 16 decimal. At least, my Intermatic MultiWave system uses 16 (0x10)     
 
Well, that would be a problem, then!  I think you are right... From https://github.com/tagyoureit/nodejs-Pentair/wiki/Broadcast, another user posted
 

252 = SW Version Info
253 = Get SW Version 
 
I wonder if we can use that to determine the controller type.  Can you query the IntellicomII and see if that works?  Or do you have any other thoughts on how to differentiate the two controllers?  A config file is nice and good, but automatically determining it would be ideal.
 
Back
Top